[Lldb-commits] [lldb] e7c6147 - [lldb] Move DownloadObjectAndSymbolFile to SymbolLocator plugin (#71267)
via lldb-commits
lldb-commits at lists.llvm.org
Sat Nov 4 17:58:39 PDT 2023
Author: Jonas Devlieghere
Date: 2023-11-04T17:58:35-07:00
New Revision: e7c61479cecb3d4359936d323ae1c62c217a6e20
URL: https://github.com/llvm/llvm-project/commit/e7c61479cecb3d4359936d323ae1c62c217a6e20
DIFF: https://github.com/llvm/llvm-project/commit/e7c61479cecb3d4359936d323ae1c62c217a6e20.diff
LOG: [lldb] Move DownloadObjectAndSymbolFile to SymbolLocator plugin (#71267)
This builds on top of the work started in c3a302d to convert
LocateSymbolFile to a SymbolLocator plugin. This commit moves
DownloadObjectAndSymbolFile.
Added:
Modified:
lldb/include/lldb/Core/PluginManager.h
lldb/include/lldb/Symbol/LocateSymbolFile.h
lldb/include/lldb/lldb-private-interfaces.h
lldb/source/API/SBTarget.cpp
lldb/source/Commands/CommandObjectTarget.cpp
lldb/source/Core/DynamicLoader.cpp
lldb/source/Core/PluginManager.cpp
lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
lldb/source/Symbol/CMakeLists.txt
lldb/source/Symbol/LocateSymbolFile.cpp
Removed:
lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
################################################################################
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index 50f0662f4bb2b95..318f8b63c251a19 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -353,6 +353,8 @@ class PluginManager {
nullptr,
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file =
nullptr,
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file =
+ nullptr,
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr);
static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback);
@@ -366,6 +368,11 @@ class PluginManager {
LocateExecutableSymbolFile(const ModuleSpec &module_spec,
const FileSpecList &default_search_paths);
+ static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error,
+ bool force_lookup = true,
+ bool copy_executable = true);
+
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 3c0f069c27f8dd6..9247814a9e2ab22 100644
--- a/lldb/include/lldb/Symbol/LocateSymbolFile.h
+++ b/lldb/include/lldb/Symbol/LocateSymbolFile.h
@@ -24,20 +24,6 @@ class UUID;
class Symbols {
public:
- // Locate the object and symbol file given a module specification.
- //
- // Locating the file can try to download the file from a corporate build
- // repository, or using any other means necessary to locate both the
- // unstripped object file and the debug symbols. The force_lookup argument
- // controls whether the external program is called unconditionally to find
- // the symbol file, or if the user's settings are checked to see if they've
- // enabled the external program before calling.
- //
- static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
- Status &error,
- bool force_lookup = true,
- bool copy_executable = true);
-
/// Locate the symbol file for the given UUID on a background thread. This
/// function returns immediately. Under the hood it uses the debugger's
/// thread pool to call DownloadObjectAndSymbolFile. If a symbol file is
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 4c324a721029075..53d5fbb84cc92d3 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -96,6 +96,9 @@ 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 (*SymbolLocatorDownloadObjectAndSymbolFile)(
+ ModuleSpec &module_spec, Status &error, bool force_lookup,
+ bool copy_executable);
typedef bool (*BreakpointHitCallback)(void *baton,
StoppointCallbackContext *context,
lldb::user_id_t break_id,
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index a4a7ac338c20768..03134ff54fa46e9 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -38,6 +38,7 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StructuredDataImpl.h"
@@ -1525,8 +1526,9 @@ lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) {
true /* notify */));
if (!sb_module.IsValid() && module_spec.m_opaque_up->GetUUID().IsValid()) {
Status error;
- if (Symbols::DownloadObjectAndSymbolFile(*module_spec.m_opaque_up, error,
- /* force_lookup */ true)) {
+ if (PluginManager::DownloadObjectAndSymbolFile(*module_spec.m_opaque_up,
+ error,
+ /* force_lookup */ true)) {
if (FileSystem::Instance().Exists(
module_spec.m_opaque_up->GetFileSpec())) {
sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index ca8484cc79d4054..180210d45b7e000 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
@@ -2801,7 +2802,7 @@ class CommandObjectTargetModulesAdd : public CommandObjectParsed {
module_spec.GetSymbolFileSpec() =
m_symbol_file.GetOptionValue().GetCurrentValue();
Status error;
- if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
+ if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
ModuleSP module_sp(
target->GetOrCreateModule(module_spec, true /* notify */));
if (module_sp) {
@@ -4497,7 +4498,7 @@ class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
CommandReturnObject &result, bool &flush) {
Status error;
- if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
+ if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
if (module_spec.GetSymbolFileSpec())
return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush,
result);
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index efed29da0835ebf..f4baaf450ee97ac 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -232,8 +232,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// If we haven't found a binary, or we don't have a SymbolFile, see
// if there is an external search tool that can find it.
if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
- Symbols::DownloadObjectAndSymbolFile(module_spec, error,
- force_symbol_search);
+ PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
+ force_symbol_search);
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
module_sp = std::make_shared<Module>(module_spec);
} else if (force_symbol_search && error.AsCString("") &&
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 810e487f723de06..23c06357e2f95f3 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1090,15 +1090,18 @@ struct SymbolLocatorInstance
CallbackType create_callback,
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_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),
+ download_object_symbol_file(download_object_symbol_file),
find_symbol_file_in_bundle(find_symbol_file_in_bundle) {}
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file;
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file;
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file;
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle;
};
typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances;
@@ -1113,10 +1116,12 @@ bool PluginManager::RegisterPlugin(
SymbolLocatorCreateInstance create_callback,
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle) {
return GetSymbolLocatorInstances().RegisterPlugin(
name, description, create_callback, locate_executable_object_file,
- locate_executable_symbol_file, find_symbol_file_in_bundle);
+ locate_executable_symbol_file, download_object_symbol_file,
+ find_symbol_file_in_bundle);
}
bool PluginManager::UnregisterPlugin(
@@ -1157,6 +1162,21 @@ FileSpec PluginManager::LocateExecutableSymbolFile(
return {};
}
+bool PluginManager::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error,
+ bool force_lookup,
+ bool copy_executable) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.download_object_symbol_file) {
+ if (instance.download_object_symbol_file(module_spec, error, force_lookup,
+ copy_executable))
+ return true;
+ }
+ }
+ return false;
+}
+
FileSpec PluginManager::FindSymbolFileInBundle(const FileSpec &symfile_bundle,
const UUID *uuid,
const ArchSpec *arch) {
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index 5aeaf3ae24d7c7b..a255a3b9e760c94 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -798,8 +798,8 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
Status kernel_search_error;
if (IsKernel() &&
(!m_module_sp || !m_module_sp->GetSymbolFileFileSpec())) {
- if (Symbols::DownloadObjectAndSymbolFile(module_spec,
- kernel_search_error, true)) {
+ if (PluginManager::DownloadObjectAndSymbolFile(
+ module_spec, kernel_search_error, true)) {
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
target.GetArchitecture());
diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
index a1bf8efb064b614..8235cc7f1ba6445 100644
--- a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
@@ -345,7 +345,8 @@ bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture());
if (IsKernel()) {
Status error;
- if (Symbols::DownloadObjectAndSymbolFile(module_spec, error, true)) {
+ if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
+ true)) {
if (FileSystem::Instance().Exists(module_spec.GetFileSpec()))
m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
target.GetArchitecture());
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 9af544b31d89649..d10069f17cbbe3b 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -292,8 +292,8 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
if (!module_spec.GetSymbolFileSpec() ||
!module_spec.GetSymbolFileSpec()) {
Status symbl_error;
- Symbols::DownloadObjectAndSymbolFile(module_spec, symbl_error,
- true);
+ PluginManager::DownloadObjectAndSymbolFile(module_spec,
+ symbl_error, true);
}
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
index 2c57ef8b6a54ea0..fb94e5cb31d49bf 100644
--- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -66,7 +66,7 @@ void SymbolLocatorDebugSymbols::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
LocateExecutableObjectFile, LocateExecutableSymbolFile,
- FindSymbolFileInBundle);
+ DownloadObjectAndSymbolFile, FindSymbolFileInBundle);
}
void SymbolLocatorDebugSymbols::Terminate() {
@@ -390,7 +390,7 @@ static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec,
// 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
+// call through PluginManager::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,
@@ -447,7 +447,8 @@ static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec,
if (FileSystem::Instance().Exists(dsym_yaa_fspec)) {
ModuleSpec mutable_mod_spec = mod_spec;
Status error;
- if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, error, true) &&
+ if (PluginManager::DownloadObjectAndSymbolFile(mutable_mod_spec, error,
+ true) &&
FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) {
dsym_fspec = mutable_mod_spec.GetSymbolFileSpec();
return true;
@@ -789,3 +790,361 @@ std::optional<FileSpec> SymbolLocatorDebugSymbols::LocateExecutableSymbolFile(
return dsym_module_spec.GetSymbolFileSpec();
}
+
+static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
+ ModuleSpec &module_spec,
+ Status &error,
+ const std::string &command) {
+ Log *log = GetLog(LLDBLog::Host);
+ bool success = false;
+ if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) {
+ std::string str;
+ CFStringRef cf_str;
+ CFDictionaryRef cf_dict;
+
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGError"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ if (CFCString::FileSystemRepresentation(cf_str, str)) {
+ std::string errorstr = command;
+ errorstr += ":\n";
+ errorstr += str;
+ error.SetErrorString(errorstr);
+ }
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue(
+ (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ if (CFCString::FileSystemRepresentation(cf_str, str)) {
+ module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
+ LLDB_LOGF(log,
+ "From dsymForUUID plist: Symbol rich executable is at '%s'",
+ str.c_str());
+ }
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGDSYMPath"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ if (CFCString::FileSystemRepresentation(cf_str, str)) {
+ module_spec.GetSymbolFileSpec().SetFile(str.c_str(),
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
+ success = true;
+ LLDB_LOGF(log, "From dsymForUUID plist: dSYM is at '%s'", str.c_str());
+ }
+ }
+
+ std::string DBGBuildSourcePath;
+ std::string DBGSourcePath;
+
+ // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping.
+ // If DBGVersion 2, strip last two components of path remappings from
+ // entries to fix an issue with a specific set of
+ // DBGSourcePathRemapping entries that lldb worked
+ // with.
+ // If DBGVersion 3, trust & use the source path remappings as-is.
+ //
+ cf_dict = (CFDictionaryRef)CFDictionaryGetValue(
+ (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping"));
+ if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) {
+ // If we see DBGVersion with a value of 2 or higher, this is a new style
+ // DBGSourcePathRemapping dictionary
+ bool new_style_source_remapping_dictionary = false;
+ bool do_truncate_remapping_names = false;
+ std::string original_DBGSourcePath_value = DBGSourcePath;
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGVersion"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ std::string version;
+ CFCString::FileSystemRepresentation(cf_str, version);
+ if (!version.empty() && isdigit(version[0])) {
+ int version_number = atoi(version.c_str());
+ if (version_number > 1) {
+ new_style_source_remapping_dictionary = true;
+ }
+ if (version_number == 2) {
+ do_truncate_remapping_names = true;
+ }
+ }
+ }
+
+ CFIndex kv_pair_count = CFDictionaryGetCount((CFDictionaryRef)uuid_dict);
+ if (kv_pair_count > 0) {
+ CFStringRef *keys =
+ (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef));
+ CFStringRef *values =
+ (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef));
+ if (keys != nullptr && values != nullptr) {
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)uuid_dict,
+ (const void **)keys,
+ (const void **)values);
+ }
+ for (CFIndex i = 0; i < kv_pair_count; i++) {
+ DBGBuildSourcePath.clear();
+ DBGSourcePath.clear();
+ if (keys[i] && CFGetTypeID(keys[i]) == CFStringGetTypeID()) {
+ CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath);
+ }
+ if (values[i] && CFGetTypeID(values[i]) == CFStringGetTypeID()) {
+ CFCString::FileSystemRepresentation(values[i], DBGSourcePath);
+ }
+ if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) {
+ // In the "old style" DBGSourcePathRemapping dictionary, the
+ // DBGSourcePath values (the "values" half of key-value path pairs)
+ // were wrong. Ignore them and use the universal DBGSourcePath
+ // string from earlier.
+ if (new_style_source_remapping_dictionary &&
+ !original_DBGSourcePath_value.empty()) {
+ DBGSourcePath = original_DBGSourcePath_value;
+ }
+ if (DBGSourcePath[0] == '~') {
+ FileSpec resolved_source_path(DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(resolved_source_path);
+ DBGSourcePath = resolved_source_path.GetPath();
+ }
+ // With version 2 of DBGSourcePathRemapping, we can chop off the
+ // last two filename parts from the source remapping and get a more
+ // general source remapping that still works. Add this as another
+ // option in addition to the full source path remap.
+ module_spec.GetSourceMappingList().Append(DBGBuildSourcePath,
+ DBGSourcePath, true);
+ if (do_truncate_remapping_names) {
+ FileSpec build_path(DBGBuildSourcePath.c_str());
+ FileSpec source_path(DBGSourcePath.c_str());
+ build_path.RemoveLastPathComponent();
+ build_path.RemoveLastPathComponent();
+ source_path.RemoveLastPathComponent();
+ source_path.RemoveLastPathComponent();
+ module_spec.GetSourceMappingList().Append(
+ build_path.GetPath(), source_path.GetPath(), true);
+ }
+ }
+ }
+ if (keys)
+ free(keys);
+ if (values)
+ free(values);
+ }
+ }
+
+ // If we have a DBGBuildSourcePath + DBGSourcePath pair, append them to the
+ // source remappings list.
+
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGBuildSourcePath"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGSourcePath"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
+ }
+
+ if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) {
+ if (DBGSourcePath[0] == '~') {
+ FileSpec resolved_source_path(DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(resolved_source_path);
+ DBGSourcePath = resolved_source_path.GetPath();
+ }
+ module_spec.GetSourceMappingList().Append(DBGBuildSourcePath,
+ DBGSourcePath, true);
+ }
+ }
+ return success;
+}
+
+/// It's expensive to check for the DBGShellCommands defaults setting. Only do
+/// it once per lldb run and cache the result.
+static llvm::StringRef GetDbgShellCommand() {
+ static std::once_flag g_once_flag;
+ static std::string g_dbgshell_command;
+ std::call_once(g_once_flag, [&]() {
+ CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
+ CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
+ if (defaults_setting &&
+ CFGetTypeID(defaults_setting) == CFStringGetTypeID()) {
+ char buffer[PATH_MAX];
+ if (CFStringGetCString((CFStringRef)defaults_setting, buffer,
+ sizeof(buffer), kCFStringEncodingUTF8)) {
+ g_dbgshell_command = buffer;
+ }
+ }
+ if (defaults_setting) {
+ CFRelease(defaults_setting);
+ }
+ });
+ return g_dbgshell_command;
+}
+
+/// Get the dsymForUUID executable and cache the result so we don't end up
+/// stat'ing the binary over and over.
+static FileSpec GetDsymForUUIDExecutable() {
+ // The LLDB_APPLE_DSYMFORUUID_EXECUTABLE environment variable is used by the
+ // test suite to override the dsymForUUID location. Because we must be able
+ // to change the value within a single test, don't bother caching it.
+ if (const char *dsymForUUID_env =
+ getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE")) {
+ FileSpec dsymForUUID_executable(dsymForUUID_env);
+ FileSystem::Instance().Resolve(dsymForUUID_executable);
+ if (FileSystem::Instance().Exists(dsymForUUID_executable))
+ return dsymForUUID_executable;
+ }
+
+ static std::once_flag g_once_flag;
+ static FileSpec g_dsymForUUID_executable;
+ std::call_once(g_once_flag, [&]() {
+ // Try the DBGShellCommand.
+ llvm::StringRef dbgshell_command = GetDbgShellCommand();
+ if (!dbgshell_command.empty()) {
+ g_dsymForUUID_executable = FileSpec(dbgshell_command);
+ FileSystem::Instance().Resolve(g_dsymForUUID_executable);
+ if (FileSystem::Instance().Exists(g_dsymForUUID_executable))
+ return;
+ }
+
+ // Try dsymForUUID in /usr/local/bin
+ {
+ g_dsymForUUID_executable = FileSpec("/usr/local/bin/dsymForUUID");
+ if (FileSystem::Instance().Exists(g_dsymForUUID_executable))
+ return;
+ }
+
+ // We couldn't find the dsymForUUID binary.
+ g_dsymForUUID_executable = {};
+ });
+ return g_dsymForUUID_executable;
+}
+
+bool SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile(
+ ModuleSpec &module_spec, Status &error, bool force_lookup,
+ bool copy_executable) {
+ const UUID *uuid_ptr = module_spec.GetUUIDPtr();
+ const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
+
+ // If \a dbgshell_command is set, the user has specified
+ // forced symbol lookup via that command. We'll get the
+ // path back from GetDsymForUUIDExecutable() later.
+ llvm::StringRef dbgshell_command = GetDbgShellCommand();
+
+ // If forced lookup isn't set, by the user's \a dbgshell_command or
+ // by the \a force_lookup argument, exit this method.
+ if (!force_lookup && dbgshell_command.empty())
+ return false;
+
+ // We need a UUID or valid existing FileSpec.
+ if (!uuid_ptr &&
+ (!file_spec_ptr || !FileSystem::Instance().Exists(*file_spec_ptr)))
+ return false;
+
+ // We need a dsymForUUID binary or an equivalent executable/script.
+ FileSpec dsymForUUID_exe_spec = GetDsymForUUIDExecutable();
+ if (!dsymForUUID_exe_spec)
+ return false;
+
+ const std::string dsymForUUID_exe_path = dsymForUUID_exe_spec.GetPath();
+ const std::string uuid_str = uuid_ptr ? uuid_ptr->GetAsString() : "";
+ const std::string file_path_str =
+ file_spec_ptr ? file_spec_ptr->GetPath() : "";
+
+ Log *log = GetLog(LLDBLog::Host);
+
+ // Create the dsymForUUID command.
+ StreamString command;
+ const char *copy_executable_arg = copy_executable ? "--copyExecutable " : "";
+ if (!uuid_str.empty()) {
+ command.Printf("%s --ignoreNegativeCache %s%s",
+ dsymForUUID_exe_path.c_str(), copy_executable_arg,
+ uuid_str.c_str());
+ LLDB_LOGF(log, "Calling %s with UUID %s to find dSYM: %s",
+ dsymForUUID_exe_path.c_str(), uuid_str.c_str(),
+ command.GetString().data());
+ } else if (!file_path_str.empty()) {
+ command.Printf("%s --ignoreNegativeCache %s%s",
+ dsymForUUID_exe_path.c_str(), copy_executable_arg,
+ file_path_str.c_str());
+ LLDB_LOGF(log, "Calling %s with file %s to find dSYM: %s",
+ dsymForUUID_exe_path.c_str(), file_path_str.c_str(),
+ command.GetString().data());
+ } else {
+ return false;
+ }
+
+ // Invoke dsymForUUID.
+ int exit_status = -1;
+ int signo = -1;
+ std::string command_output;
+ error = Host::RunShellCommand(
+ command.GetData(),
+ FileSpec(), // current working directory
+ &exit_status, // Exit status
+ &signo, // Signal int *
+ &command_output, // Command output
+ std::chrono::seconds(
+ 640), // Large timeout to allow for long dsym download times
+ false); // Don't run in a shell (we don't need shell expansion)
+
+ if (error.Fail() || exit_status != 0 || command_output.empty()) {
+ LLDB_LOGF(log, "'%s' failed (exit status: %d, error: '%s', output: '%s')",
+ command.GetData(), exit_status, error.AsCString(),
+ command_output.c_str());
+ return false;
+ }
+
+ CFCData data(
+ CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)command_output.data(),
+ command_output.size(), kCFAllocatorNull));
+
+ CFCReleaser<CFDictionaryRef> plist(
+ (CFDictionaryRef)::CFPropertyListCreateWithData(
+ NULL, data.get(), kCFPropertyListImmutable, NULL, NULL));
+
+ if (!plist.get()) {
+ LLDB_LOGF(log, "'%s' failed: output is not a valid plist",
+ command.GetData());
+ return false;
+ }
+
+ if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) {
+ LLDB_LOGF(log, "'%s' failed: output plist is not a valid CFDictionary",
+ command.GetData());
+ return false;
+ }
+
+ if (!uuid_str.empty()) {
+ CFCString uuid_cfstr(uuid_str.c_str());
+ CFDictionaryRef uuid_dict =
+ (CFDictionaryRef)CFDictionaryGetValue(plist.get(), uuid_cfstr.get());
+ return GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec, error,
+ command.GetData());
+ }
+
+ if (const CFIndex num_values = ::CFDictionaryGetCount(plist.get())) {
+ std::vector<CFStringRef> keys(num_values, NULL);
+ std::vector<CFDictionaryRef> values(num_values, NULL);
+ ::CFDictionaryGetKeysAndValues(plist.get(), NULL,
+ (const void **)&values[0]);
+ if (num_values == 1) {
+ return GetModuleSpecInfoFromUUIDDictionary(values[0], module_spec, error,
+ command.GetData());
+ }
+
+ for (CFIndex i = 0; i < num_values; ++i) {
+ ModuleSpec curr_module_spec;
+ if (GetModuleSpecInfoFromUUIDDictionary(values[i], curr_module_spec,
+ error, command.GetData())) {
+ if (module_spec.GetArchitecture().IsCompatibleMatch(
+ curr_module_spec.GetArchitecture())) {
+ module_spec = curr_module_spec;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
index 72bd6de433dd706..efbe68bc5dae84f 100644
--- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
@@ -46,6 +46,18 @@ class SymbolLocatorDebugSymbols : public SymbolLocator {
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
+ // repository, or using any other means necessary to locate both the
+ // unstripped object file and the debug symbols. The force_lookup argument
+ // controls whether the external program is called unconditionally to find
+ // the symbol file, or if the user's settings are checked to see if they've
+ // enabled the external program before calling.
+ static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error, bool force_lookup,
+ bool copy_executable);
+
static std::optional<FileSpec>
FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, const UUID *uuid,
const ArchSpec *arch);
diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
index 831b2b1ae0c4961..1a58ecb38cb84e8 100644
--- a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
@@ -51,7 +51,8 @@ SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {}
void SymbolLocatorDefault::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
- LocateExecutableObjectFile, LocateExecutableSymbolFile);
+ LocateExecutableObjectFile, LocateExecutableSymbolFile,
+ DownloadObjectAndSymbolFile);
}
void SymbolLocatorDefault::Terminate() {
@@ -230,3 +231,10 @@ std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile(
return {};
}
+
+bool SymbolLocatorDefault::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error,
+ bool force_lookup,
+ bool copy_executable) {
+ return false;
+}
diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
index 99e0f0b1a78dc8c..7bf0a2ad4a5b130 100644
--- a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
@@ -45,6 +45,18 @@ class SymbolLocatorDefault : public SymbolLocator {
static std::optional<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
+ // repository, or using any other means necessary to locate both the
+ // unstripped object file and the debug symbols. The force_lookup argument
+ // controls whether the external program is called unconditionally to find
+ // the symbol file, or if the user's settings are checked to see if they've
+ // enabled the external program before calling.
+ static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error, bool force_lookup,
+ bool copy_executable);
};
} // namespace lldb_private
diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt
index cec49b8b2cb4b63..4de48097870e90e 100644
--- a/lldb/source/Symbol/CMakeLists.txt
+++ b/lldb/source/Symbol/CMakeLists.txt
@@ -1,11 +1,3 @@
-set(LLVM_OPTIONAL_SOURCES LocateSymbolFileMacOSX.cpp)
-
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
- set(PLATFORM_SOURCES
- LocateSymbolFileMacOSX.cpp
- )
-endif()
-
add_lldb_library(lldbSymbol NO_PLUGIN_DEPENDENCIES
ArmUnwindInfo.cpp
Block.cpp
@@ -40,8 +32,6 @@ add_lldb_library(lldbSymbol NO_PLUGIN_DEPENDENCIES
Variable.cpp
VariableList.cpp
- ${PLATFORM_SOURCES}
-
LINK_LIBS
lldbCore
lldbExpression
diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp
index 17f5a090c71882d..06b113f89827186 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -12,6 +12,7 @@
#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/Host/FileSystem.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -28,10 +29,6 @@
#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;
@@ -52,9 +49,9 @@ void Symbols::DownloadSymbolFileAsync(const UUID &uuid) {
Status error;
ModuleSpec module_spec;
module_spec.GetUUID() = uuid;
- if (!Symbols::DownloadObjectAndSymbolFile(module_spec, error,
- /*force_lookup=*/true,
- /*copy_executable=*/false))
+ if (!PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
+ /*force_lookup=*/true,
+ /*copy_executable=*/false))
return;
if (error.Fail())
@@ -63,15 +60,3 @@ void Symbols::DownloadSymbolFileAsync(const UUID &uuid) {
Debugger::ReportSymbolChange(module_spec);
});
}
-
-#if !defined(__APPLE__)
-
-bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
- Status &error, bool force_lookup,
- bool copy_executable) {
- // Fill in the module_spec.GetFileSpec() for the object file and/or the
- // module_spec.GetSymbolFileSpec() for the debug symbols file.
- return false;
-}
-
-#endif
diff --git a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp b/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
deleted file mode 100644
index be0bb37bab5350b..000000000000000
--- a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
+++ /dev/null
@@ -1,649 +0,0 @@
-//===-- LocateSymbolFileMacOSX.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 "lldb/Symbol/LocateSymbolFile.h"
-
-#include <dirent.h>
-#include <dlfcn.h>
-#include <pwd.h>
-
-#include <CoreFoundation/CoreFoundation.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 "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/DataBuffer.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/Endian.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 "mach/machine.h"
-
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/Support/FileSystem.h"
-
-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;
-
-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;
- 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<CFStringRef>(::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<CFURLRef> 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;
- }
- }
- }
- }
- }
- }
- }
- }
-
- return items_found;
-}
-
-static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
- ModuleSpec &module_spec,
- Status &error,
- const std::string &command) {
- Log *log = GetLog(LLDBLog::Host);
- bool success = false;
- if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) {
- std::string str;
- CFStringRef cf_str;
- CFDictionaryRef cf_dict;
-
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGError"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- if (CFCString::FileSystemRepresentation(cf_str, str)) {
- std::string errorstr = command;
- errorstr += ":\n";
- errorstr += str;
- error.SetErrorString(errorstr);
- }
- }
-
- cf_str = (CFStringRef)CFDictionaryGetValue(
- (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- if (CFCString::FileSystemRepresentation(cf_str, str)) {
- module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native);
- FileSystem::Instance().Resolve(module_spec.GetFileSpec());
- LLDB_LOGF(log,
- "From dsymForUUID plist: Symbol rich executable is at '%s'",
- str.c_str());
- }
- }
-
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGDSYMPath"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- if (CFCString::FileSystemRepresentation(cf_str, str)) {
- module_spec.GetSymbolFileSpec().SetFile(str.c_str(),
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(module_spec.GetFileSpec());
- success = true;
- LLDB_LOGF(log, "From dsymForUUID plist: dSYM is at '%s'", str.c_str());
- }
- }
-
- std::string DBGBuildSourcePath;
- std::string DBGSourcePath;
-
- // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping.
- // If DBGVersion 2, strip last two components of path remappings from
- // entries to fix an issue with a specific set of
- // DBGSourcePathRemapping entries that lldb worked
- // with.
- // If DBGVersion 3, trust & use the source path remappings as-is.
- //
- cf_dict = (CFDictionaryRef)CFDictionaryGetValue(
- (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping"));
- if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) {
- // If we see DBGVersion with a value of 2 or higher, this is a new style
- // DBGSourcePathRemapping dictionary
- bool new_style_source_remapping_dictionary = false;
- bool do_truncate_remapping_names = false;
- std::string original_DBGSourcePath_value = DBGSourcePath;
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGVersion"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- std::string version;
- CFCString::FileSystemRepresentation(cf_str, version);
- if (!version.empty() && isdigit(version[0])) {
- int version_number = atoi(version.c_str());
- if (version_number > 1) {
- new_style_source_remapping_dictionary = true;
- }
- if (version_number == 2) {
- do_truncate_remapping_names = true;
- }
- }
- }
-
- CFIndex kv_pair_count = CFDictionaryGetCount((CFDictionaryRef)uuid_dict);
- if (kv_pair_count > 0) {
- CFStringRef *keys =
- (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef));
- CFStringRef *values =
- (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef));
- if (keys != nullptr && values != nullptr) {
- CFDictionaryGetKeysAndValues((CFDictionaryRef)uuid_dict,
- (const void **)keys,
- (const void **)values);
- }
- for (CFIndex i = 0; i < kv_pair_count; i++) {
- DBGBuildSourcePath.clear();
- DBGSourcePath.clear();
- if (keys[i] && CFGetTypeID(keys[i]) == CFStringGetTypeID()) {
- CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath);
- }
- if (values[i] && CFGetTypeID(values[i]) == CFStringGetTypeID()) {
- CFCString::FileSystemRepresentation(values[i], DBGSourcePath);
- }
- if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) {
- // In the "old style" DBGSourcePathRemapping dictionary, the
- // DBGSourcePath values (the "values" half of key-value path pairs)
- // were wrong. Ignore them and use the universal DBGSourcePath
- // string from earlier.
- if (new_style_source_remapping_dictionary &&
- !original_DBGSourcePath_value.empty()) {
- DBGSourcePath = original_DBGSourcePath_value;
- }
- if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str());
- FileSystem::Instance().Resolve(resolved_source_path);
- DBGSourcePath = resolved_source_path.GetPath();
- }
- // With version 2 of DBGSourcePathRemapping, we can chop off the
- // last two filename parts from the source remapping and get a more
- // general source remapping that still works. Add this as another
- // option in addition to the full source path remap.
- module_spec.GetSourceMappingList().Append(DBGBuildSourcePath,
- DBGSourcePath, true);
- if (do_truncate_remapping_names) {
- FileSpec build_path(DBGBuildSourcePath.c_str());
- FileSpec source_path(DBGSourcePath.c_str());
- build_path.RemoveLastPathComponent();
- build_path.RemoveLastPathComponent();
- source_path.RemoveLastPathComponent();
- source_path.RemoveLastPathComponent();
- module_spec.GetSourceMappingList().Append(
- build_path.GetPath(), source_path.GetPath(), true);
- }
- }
- }
- if (keys)
- free(keys);
- if (values)
- free(values);
- }
- }
-
- // If we have a DBGBuildSourcePath + DBGSourcePath pair, append them to the
- // source remappings list.
-
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGBuildSourcePath"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
- }
-
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGSourcePath"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
- }
-
- if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) {
- if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str());
- FileSystem::Instance().Resolve(resolved_source_path);
- DBGSourcePath = resolved_source_path.GetPath();
- }
- module_spec.GetSourceMappingList().Append(DBGBuildSourcePath,
- DBGSourcePath, true);
- }
- }
- return success;
-}
-
-/// It's expensive to check for the DBGShellCommands defaults setting. Only do
-/// it once per lldb run and cache the result.
-static llvm::StringRef GetDbgShellCommand() {
- static std::once_flag g_once_flag;
- static std::string g_dbgshell_command;
- std::call_once(g_once_flag, [&]() {
- CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
- CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
- if (defaults_setting &&
- CFGetTypeID(defaults_setting) == CFStringGetTypeID()) {
- char buffer[PATH_MAX];
- if (CFStringGetCString((CFStringRef)defaults_setting, buffer,
- sizeof(buffer), kCFStringEncodingUTF8)) {
- g_dbgshell_command = buffer;
- }
- }
- if (defaults_setting) {
- CFRelease(defaults_setting);
- }
- });
- return g_dbgshell_command;
-}
-
-/// Get the dsymForUUID executable and cache the result so we don't end up
-/// stat'ing the binary over and over.
-static FileSpec GetDsymForUUIDExecutable() {
- // The LLDB_APPLE_DSYMFORUUID_EXECUTABLE environment variable is used by the
- // test suite to override the dsymForUUID location. Because we must be able
- // to change the value within a single test, don't bother caching it.
- if (const char *dsymForUUID_env =
- getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE")) {
- FileSpec dsymForUUID_executable(dsymForUUID_env);
- FileSystem::Instance().Resolve(dsymForUUID_executable);
- if (FileSystem::Instance().Exists(dsymForUUID_executable))
- return dsymForUUID_executable;
- }
-
- static std::once_flag g_once_flag;
- static FileSpec g_dsymForUUID_executable;
- std::call_once(g_once_flag, [&]() {
- // Try the DBGShellCommand.
- llvm::StringRef dbgshell_command = GetDbgShellCommand();
- if (!dbgshell_command.empty()) {
- g_dsymForUUID_executable = FileSpec(dbgshell_command);
- FileSystem::Instance().Resolve(g_dsymForUUID_executable);
- if (FileSystem::Instance().Exists(g_dsymForUUID_executable))
- return;
- }
-
- // Try dsymForUUID in /usr/local/bin
- {
- g_dsymForUUID_executable = FileSpec("/usr/local/bin/dsymForUUID");
- if (FileSystem::Instance().Exists(g_dsymForUUID_executable))
- return;
- }
-
- // We couldn't find the dsymForUUID binary.
- g_dsymForUUID_executable = {};
- });
- return g_dsymForUUID_executable;
-}
-
-bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
- Status &error, bool force_lookup,
- bool copy_executable) {
- const UUID *uuid_ptr = module_spec.GetUUIDPtr();
- const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
-
- // If \a dbgshell_command is set, the user has specified
- // forced symbol lookup via that command. We'll get the
- // path back from GetDsymForUUIDExecutable() later.
- llvm::StringRef dbgshell_command = GetDbgShellCommand();
-
- // If forced lookup isn't set, by the user's \a dbgshell_command or
- // by the \a force_lookup argument, exit this method.
- if (!force_lookup && dbgshell_command.empty())
- return false;
-
- // We need a UUID or valid existing FileSpec.
- if (!uuid_ptr &&
- (!file_spec_ptr || !FileSystem::Instance().Exists(*file_spec_ptr)))
- return false;
-
- // We need a dsymForUUID binary or an equivalent executable/script.
- FileSpec dsymForUUID_exe_spec = GetDsymForUUIDExecutable();
- if (!dsymForUUID_exe_spec)
- return false;
-
- const std::string dsymForUUID_exe_path = dsymForUUID_exe_spec.GetPath();
- const std::string uuid_str = uuid_ptr ? uuid_ptr->GetAsString() : "";
- const std::string file_path_str =
- file_spec_ptr ? file_spec_ptr->GetPath() : "";
-
- Log *log = GetLog(LLDBLog::Host);
-
- // Create the dsymForUUID command.
- StreamString command;
- const char *copy_executable_arg = copy_executable ? "--copyExecutable " : "";
- if (!uuid_str.empty()) {
- command.Printf("%s --ignoreNegativeCache %s%s",
- dsymForUUID_exe_path.c_str(), copy_executable_arg,
- uuid_str.c_str());
- LLDB_LOGF(log, "Calling %s with UUID %s to find dSYM: %s",
- dsymForUUID_exe_path.c_str(), uuid_str.c_str(),
- command.GetString().data());
- } else if (!file_path_str.empty()) {
- command.Printf("%s --ignoreNegativeCache %s%s",
- dsymForUUID_exe_path.c_str(), copy_executable_arg,
- file_path_str.c_str());
- LLDB_LOGF(log, "Calling %s with file %s to find dSYM: %s",
- dsymForUUID_exe_path.c_str(), file_path_str.c_str(),
- command.GetString().data());
- } else {
- return false;
- }
-
- // Invoke dsymForUUID.
- int exit_status = -1;
- int signo = -1;
- std::string command_output;
- error = Host::RunShellCommand(
- command.GetData(),
- FileSpec(), // current working directory
- &exit_status, // Exit status
- &signo, // Signal int *
- &command_output, // Command output
- std::chrono::seconds(
- 640), // Large timeout to allow for long dsym download times
- false); // Don't run in a shell (we don't need shell expansion)
-
- if (error.Fail() || exit_status != 0 || command_output.empty()) {
- LLDB_LOGF(log, "'%s' failed (exit status: %d, error: '%s', output: '%s')",
- command.GetData(), exit_status, error.AsCString(),
- command_output.c_str());
- return false;
- }
-
- CFCData data(
- CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)command_output.data(),
- command_output.size(), kCFAllocatorNull));
-
- CFCReleaser<CFDictionaryRef> plist(
- (CFDictionaryRef)::CFPropertyListCreateWithData(
- NULL, data.get(), kCFPropertyListImmutable, NULL, NULL));
-
- if (!plist.get()) {
- LLDB_LOGF(log, "'%s' failed: output is not a valid plist",
- command.GetData());
- return false;
- }
-
- if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) {
- LLDB_LOGF(log, "'%s' failed: output plist is not a valid CFDictionary",
- command.GetData());
- return false;
- }
-
- if (!uuid_str.empty()) {
- CFCString uuid_cfstr(uuid_str.c_str());
- CFDictionaryRef uuid_dict =
- (CFDictionaryRef)CFDictionaryGetValue(plist.get(), uuid_cfstr.get());
- return GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec, error,
- command.GetData());
- }
-
- if (const CFIndex num_values = ::CFDictionaryGetCount(plist.get())) {
- std::vector<CFStringRef> keys(num_values, NULL);
- std::vector<CFDictionaryRef> values(num_values, NULL);
- ::CFDictionaryGetKeysAndValues(plist.get(), NULL,
- (const void **)&values[0]);
- if (num_values == 1) {
- return GetModuleSpecInfoFromUUIDDictionary(values[0], module_spec, error,
- command.GetData());
- }
-
- for (CFIndex i = 0; i < num_values; ++i) {
- ModuleSpec curr_module_spec;
- if (GetModuleSpecInfoFromUUIDDictionary(values[i], curr_module_spec,
- error, command.GetData())) {
- if (module_spec.GetArchitecture().IsCompatibleMatch(
- curr_module_spec.GetArchitecture())) {
- module_spec = curr_module_spec;
- return true;
- }
- }
- }
- }
-
- return false;
-}
More information about the lldb-commits
mailing list