This revision was automatically updated to reflect the committed changes.
Closed by commit rLLDB355032: Move Host/Symbols.cpp to
Symbols/LocateSymbolFile.cpp (authored by zturner, committed by ).
Herald added subscribers: abidh, krytarowski.
Herald added a project: LLDB.
Changed prior to commit:
https://reviews.llvm.org/D58730?vs=188587&id=188613#toc
Repository:
rLLDB LLDB
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D58730/new/
https://reviews.llvm.org/D58730
Files:
include/lldb/Host/Symbols.h
include/lldb/Symbol/LocateSymbolFile.h
include/lldb/module.modulemap
source/Commands/CommandObjectTarget.cpp
source/Core/ModuleList.cpp
source/Host/CMakeLists.txt
source/Host/common/Symbols.cpp
source/Host/macosx/Symbols.cpp
source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
source/Symbol/CMakeLists.txt
source/Symbol/LocateSymbolFile.cpp
source/Symbol/LocateSymbolFileMacOSX.cpp
unittests/Host/CMakeLists.txt
unittests/Host/SymbolsTest.cpp
unittests/Symbol/CMakeLists.txt
unittests/Symbol/LocateSymbolFileTest.cpp
Index: include/lldb/module.modulemap
===================================================================
--- include/lldb/module.modulemap
+++ include/lldb/module.modulemap
@@ -48,7 +48,6 @@
module SocketAddress { header "Host/SocketAddress.h" export * }
module Socket { header "Host/Socket.h" export * }
module StringConvert { textual header "Host/StringConvert.h" export * }
- module Symbols { header "Host/Symbols.h" export * }
module TaskPool { header "Host/TaskPool.h" export * }
module Terminal { header "Host/Terminal.h" export * }
module ThreadLauncher { header "Host/ThreadLauncher.h" export * }
Index: include/lldb/Symbol/LocateSymbolFile.h
===================================================================
--- include/lldb/Symbol/LocateSymbolFile.h
+++ include/lldb/Symbol/LocateSymbolFile.h
@@ -0,0 +1,61 @@
+//===-- Symbols.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Symbols_h_
+#define liblldb_Symbols_h_
+
+#include <stdint.h>
+
+#include "lldb/Utility/FileSpec.h"
+
+namespace lldb_private {
+
+class ArchSpec;
+class ModuleSpec;
+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
+ // current computers global settings.
+ //----------------------------------------------------------------------
+ static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec);
+
+ static FileSpec FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
+ const lldb_private::UUID *uuid,
+ const ArchSpec *arch);
+
+ //----------------------------------------------------------------------
+ // 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,
+ bool force_lookup = true);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Symbols_h_
Index: unittests/Host/CMakeLists.txt
===================================================================
--- unittests/Host/CMakeLists.txt
+++ unittests/Host/CMakeLists.txt
@@ -9,7 +9,6 @@
ProcessLaunchInfoTest.cpp
SocketAddressTest.cpp
SocketTest.cpp
- SymbolsTest.cpp
TaskPoolTest.cpp
)
Index: unittests/Symbol/LocateSymbolFileTest.cpp
===================================================================
--- unittests/Symbol/LocateSymbolFileTest.cpp
+++ unittests/Symbol/LocateSymbolFileTest.cpp
@@ -0,0 +1,48 @@
+//===-- SymbolsTest.cpp -----------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
+
+using namespace lldb_private;
+
+namespace {
+class SymbolsTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ void TearDown() override {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
+};
+} // namespace
+
+TEST_F(
+ SymbolsTest,
+ TerminateLocateExecutableSymbolFileForUnknownExecutableAndUnknownSymbolFile) {
+ ModuleSpec module_spec;
+ FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
+ EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
+}
+
+TEST_F(SymbolsTest,
+ LocateExecutableSymbolFileForUnknownExecutableAndMissingSymbolFile) {
+ ModuleSpec module_spec;
+ // using a GUID here because the symbol file shouldn't actually exist on disk
+ module_spec.GetSymbolFileSpec().SetFile(
+ "4A524676-B24B-4F4E-968A-551D465EBAF1.so", FileSpec::Style::native);
+ FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
+ EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
+}
Index: unittests/Symbol/CMakeLists.txt
===================================================================
--- unittests/Symbol/CMakeLists.txt
+++ unittests/Symbol/CMakeLists.txt
@@ -1,4 +1,5 @@
add_lldb_unittest(SymbolTests
+ LocateSymbolFileTest.cpp
TestClangASTContext.cpp
TestDWARFCallFrameInfo.cpp
TestType.cpp
Index: source/Core/ModuleList.cpp
===================================================================
--- source/Core/ModuleList.cpp
+++ source/Core/ModuleList.cpp
@@ -11,10 +11,10 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/OptionValueFileSpec.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
Index: source/Symbol/LocateSymbolFile.cpp
===================================================================
--- source/Symbol/LocateSymbolFile.cpp
+++ source/Symbol/LocateSymbolFile.cpp
@@ -0,0 +1,388 @@
+//===-- Symbols.cpp ---------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/LocateSymbolFile.h"
+
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.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/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+#include "lldb/Utility/UUID.h"
+
+#include "llvm/Support/FileSystem.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;
+
+#if defined(__APPLE__)
+
+// Forward declaration of method defined in source/Host/macosx/Symbols.cpp
+int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
+ ModuleSpec &return_module_spec);
+
+#else
+
+int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
+ ModuleSpec &return_module_spec) {
+ // Cannot find MacOSX files using debug symbols on non MacOSX.
+ return 0;
+}
+
+#endif
+
+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 == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
+ (arch == NULL || (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;
+ if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, 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 = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ const FileSpec &exec_fspec = module_spec.GetFileSpec();
+ if (exec_fspec) {
+ if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec,
+ dsym_fspec)) {
+ if (log) {
+ log->Printf("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) {
+ log->Printf("dSYM with matching UUID & arch found at %s",
+ dsym_fspec.GetPath().c_str());
+ }
+ return true;
+ }
+ }
+ parent_dirs.RemoveLastPathComponent();
+ }
+ }
+ }
+ dsym_fspec.Clear();
+ return false;
+}
+
+static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
+ const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+ const ArchSpec *arch = module_spec.GetArchitecturePtr();
+ const UUID *uuid = module_spec.GetUUIDPtr();
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat,
+ "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
+ exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
+ arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
+
+ FileSpec symbol_fspec;
+ ModuleSpec dsym_module_spec;
+ // First try and find the dSYM in the same directory as the executable or in
+ // an appropriate parent directory
+ if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) {
+ // We failed to easily find the dSYM above, so use DebugSymbols
+ LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec);
+ } else {
+ dsym_module_spec.GetSymbolFileSpec() = symbol_fspec;
+ }
+ return dsym_module_spec.GetSymbolFileSpec();
+}
+
+ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
+ ModuleSpec result;
+ const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+ const ArchSpec *arch = module_spec.GetArchitecturePtr();
+ const UUID *uuid = module_spec.GetUUIDPtr();
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
+ exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
+ arch ? arch->GetArchitectureName() : "<NULL>", (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 Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
+ FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
+ if (symbol_file_spec.IsAbsolute() &&
+ FileSystem::Instance().Exists(symbol_file_spec))
+ return symbol_file_spec;
+
+ const char *symbol_filename = symbol_file_spec.GetFilename().AsCString();
+ if (symbol_filename && symbol_filename[0]) {
+ FileSpecList debug_file_search_paths(
+ Target::GetDefaultDebugFileSearchPaths());
+
+ // Add module directory.
+ FileSpec module_file_spec = module_spec.GetFileSpec();
+ // We keep the unresolved pathname if it fails.
+ FileSystem::Instance().ResolveSymbolicLink(module_file_spec,
+ module_file_spec);
+
+ const ConstString &file_dir = module_file_spec.GetDirectory();
+ {
+ FileSpec file_spec(file_dir.AsCString("."));
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
+
+ if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
+
+ // Add current working directory.
+ {
+ FileSpec file_spec(".");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
+
+#ifndef _WIN32
+#if defined(__NetBSD__)
+ // Add /usr/libdata/debug directory.
+ {
+ FileSpec file_spec("/usr/libdata/debug");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
+#else
+ // Add /usr/lib/debug directory.
+ {
+ FileSpec file_spec("/usr/lib/debug");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
+#endif
+#endif // _WIN32
+ }
+
+ std::string uuid_str;
+ const UUID &module_uuid = module_spec.GetUUID();
+ if (module_uuid.IsValid()) {
+ // Some debug files are stored in the .build-id directory like this:
+ // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
+ uuid_str = module_uuid.GetAsString("");
+ std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
+ ::tolower);
+ uuid_str.insert(2, 1, '/');
+ uuid_str = uuid_str + ".debug";
+ }
+
+ size_t num_directories = debug_file_search_paths.GetSize();
+ for (size_t idx = 0; idx < num_directories; ++idx) {
+ FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
+ FileSystem::Instance().Resolve(dirspec);
+ if (!FileSystem::Instance().IsDirectory(dirspec))
+ continue;
+
+ std::vector<std::string> files;
+ std::string dirname = dirspec.GetPath();
+
+ files.push_back(dirname + "/" + symbol_filename);
+ files.push_back(dirname + "/.debug/" + symbol_filename);
+ files.push_back(dirname + "/.build-id/" + uuid_str);
+
+ // Some debug files may stored in the module directory like this:
+ // /usr/lib/debug/usr/lib/library.so.debug
+ if (!file_dir.IsEmpty())
+ files.push_back(dirname + file_dir.AsCString() + "/" + symbol_filename);
+
+ const uint32_t num_files = files.size();
+ for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
+ const std::string &filename = files[idx_file];
+ FileSpec file_spec(filename);
+ FileSystem::Instance().Resolve(file_spec);
+
+ if (llvm::sys::fs::equivalent(file_spec.GetPath(),
+ module_file_spec.GetPath()))
+ continue;
+
+ if (FileSystem::Instance().Exists(file_spec)) {
+ lldb_private::ModuleSpecList specs;
+ const size_t num_specs =
+ ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);
+ assert(num_specs <= 1 &&
+ "Symbol Vendor supports only a single architecture");
+ if (num_specs == 1) {
+ ModuleSpec mspec;
+ if (specs.GetModuleSpecAtIndex(0, mspec)) {
+ // Skip the uuids check if module_uuid is invalid. For example,
+ // this happens for *.dwp files since at the moment llvm-dwp
+ // doesn't output build ids, nor does binutils dwp.
+ if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
+ return file_spec;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return LocateExecutableSymbolFileDsym(module_spec);
+}
+
+#if !defined(__APPLE__)
+
+FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle,
+ const lldb_private::UUID *uuid,
+ const ArchSpec *arch) {
+ // FIXME
+ return FileSpec();
+}
+
+bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ bool force_lookup) {
+ // Fill in the module_spec.GetFileSpec() for the object file and/or the
+ // module_spec.GetSymbolFileSpec() for the debug symbols file.
+ return false;
+}
+
+#endif
Index: source/Symbol/LocateSymbolFileMacOSX.cpp
===================================================================
--- source/Symbol/LocateSymbolFileMacOSX.cpp
+++ source/Symbol/LocateSymbolFileMacOSX.cpp
@@ -0,0 +1,653 @@
+//===-- Symbols.cpp ---------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/LocateSymbolFile.h"
+
+#include <dirent.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/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/CleanUp.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Endian.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/Support/FileSystem.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#if !defined(__arm__) && !defined(__arm64__) && \
+ !defined(__aarch64__) // No DebugSymbols on the iOS devices
+extern "C" {
+
+CFURLRef DBGCopyFullDSYMURLForUUID(CFUUIDRef uuid, CFURLRef exec_url);
+CFDictionaryRef DBGCopyDSYMPropertyLists(CFURLRef dsym_url);
+}
+#endif
+
+int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
+ ModuleSpec &return_module_spec) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
+ if (log)
+ log->Printf("Spotlight lookup for .dSYM bundles is disabled.");
+ return 0;
+ }
+
+ return_module_spec = module_spec;
+ return_module_spec.GetFileSpec().Clear();
+ return_module_spec.GetSymbolFileSpec().Clear();
+
+ int items_found = 0;
+
+#if !defined(__arm__) && !defined(__arm64__) && \
+ !defined(__aarch64__) // No DebugSymbols on the iOS devices
+
+ const UUID *uuid = module_spec.GetUUIDPtr();
+ const ArchSpec *arch = module_spec.GetArchitecturePtr();
+
+ 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(
+ ::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)) {
+ if (log) {
+ log->Printf("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)) {
+ log->Printf("DebugSymbols framework returned dSYM path of %s for "
+ "UUID %s -- looking for an exec file",
+ path, uuid->GetAsString().c_str());
+ }
+ }
+
+ CFCReleaser<CFDictionaryRef> dict(
+ ::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()));
+ }
+ if (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))) {
+ if (log) {
+ log->Printf("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;
+ }
+ }
+ }
+
+ if (!success) {
+ // No dictionary, check near the dSYM bundle for an executable that
+ // matches...
+ 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';
+ if (log) {
+ log->Printf("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;
+ if (log) {
+ log->Printf("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;
+ if (log) {
+ log->Printf("Executable binary %s next to dSYM is "
+ "compatible; using",
+ path);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif // #if !defined (__arm__) && !defined (__arm64__) && !defined
+ // (__aarch64__)
+
+ return items_found;
+}
+
+FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
+ const lldb_private::UUID *uuid,
+ const ArchSpec *arch) {
+ char path[PATH_MAX];
+ if (dsym_bundle_fspec.GetPath(path, sizeof(path)) == 0)
+ return {};
+
+ ::strncat(path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
+
+ DIR *dirp = opendir(path);
+ if (!dirp)
+ return {};
+
+ // Make sure we close the directory before exiting this scope.
+ CleanUp cleanup_dir(closedir, dirp);
+
+ FileSpec dsym_fspec;
+ dsym_fspec.GetDirectory().SetCString(path);
+ struct dirent *dp;
+ while ((dp = readdir(dirp)) != NULL) {
+ // Only search directories
+ if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) {
+ if (dp->d_namlen == 1 && dp->d_name[0] == '.')
+ continue;
+
+ if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
+ continue;
+ }
+
+ if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN) {
+ dsym_fspec.GetFilename().SetCString(dp->d_name);
+ ModuleSpecList module_specs;
+ if (ObjectFile::GetModuleSpecifications(dsym_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 == NULL ||
+ (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
+ (arch == NULL ||
+ (spec.GetArchitecturePtr() &&
+ spec.GetArchitecture().IsCompatibleMatch(*arch)))) {
+ return dsym_fspec;
+ }
+ }
+ }
+ }
+ }
+
+ return {};
+}
+
+static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
+ ModuleSpec &module_spec) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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("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());
+ if (log) {
+ log->Printf(
+ "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;
+ if (log) {
+ log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str());
+ }
+ }
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
+ CFSTR("DBGArchitecture"));
+ if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
+ if (CFCString::FileSystemRepresentation(cf_str, str))
+ module_spec.GetArchitecture().SetTriple(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(
+ ConstString(DBGBuildSourcePath.c_str()),
+ ConstString(DBGSourcePath.c_str()), 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(
+ ConstString(build_path.GetPath().c_str()),
+ ConstString(source_path.GetPath().c_str()), 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(
+ ConstString(DBGBuildSourcePath.c_str()),
+ ConstString(DBGSourcePath.c_str()), true);
+ }
+ }
+ return success;
+}
+
+bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ bool force_lookup) {
+ bool success = false;
+ const UUID *uuid_ptr = module_spec.GetUUIDPtr();
+ const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
+
+ // It's expensive to check for the DBGShellCommands defaults setting, only do
+ // it once per lldb run and cache the result.
+ static bool g_have_checked_for_dbgshell_command = false;
+ static const char *g_dbgshell_command = NULL;
+ if (!g_have_checked_for_dbgshell_command) {
+ g_have_checked_for_dbgshell_command = true;
+ CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
+ CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
+ if (defaults_setting &&
+ CFGetTypeID(defaults_setting) == CFStringGetTypeID()) {
+ char cstr_buf[PATH_MAX];
+ if (CFStringGetCString((CFStringRef)defaults_setting, cstr_buf,
+ sizeof(cstr_buf), kCFStringEncodingUTF8)) {
+ g_dbgshell_command =
+ strdup(cstr_buf); // this malloc'ed memory will never be freed
+ }
+ }
+ if (defaults_setting) {
+ CFRelease(defaults_setting);
+ }
+ }
+
+ // When g_dbgshell_command is NULL, the user has not enabled the use of an
+ // external program to find the symbols, don't run it for them.
+ if (!force_lookup && g_dbgshell_command == NULL) {
+ return false;
+ }
+
+ if (uuid_ptr ||
+ (file_spec_ptr && FileSystem::Instance().Exists(*file_spec_ptr))) {
+ static bool g_located_dsym_for_uuid_exe = false;
+ static bool g_dsym_for_uuid_exe_exists = false;
+ static char g_dsym_for_uuid_exe_path[PATH_MAX];
+ if (!g_located_dsym_for_uuid_exe) {
+ g_located_dsym_for_uuid_exe = true;
+ const char *dsym_for_uuid_exe_path_cstr =
+ getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
+ FileSpec dsym_for_uuid_exe_spec;
+ if (dsym_for_uuid_exe_path_cstr) {
+ dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr,
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
+ }
+
+ if (!g_dsym_for_uuid_exe_exists) {
+ dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID",
+ FileSpec::Style::native);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
+ if (!g_dsym_for_uuid_exe_exists) {
+ long bufsize;
+ if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) {
+ char buffer[bufsize];
+ struct passwd pwd;
+ struct passwd *tilde_rc = NULL;
+ // we are a library so we need to use the reentrant version of
+ // getpwnam()
+ if (getpwnam_r("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 &&
+ tilde_rc && tilde_rc->pw_dir) {
+ std::string dsymforuuid_path(tilde_rc->pw_dir);
+ dsymforuuid_path += "/bin/dsymForUUID";
+ dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(),
+ FileSpec::Style::native);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
+ }
+ }
+ }
+ }
+ if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) {
+ dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command,
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
+ }
+
+ if (g_dsym_for_uuid_exe_exists)
+ dsym_for_uuid_exe_spec.GetPath(g_dsym_for_uuid_exe_path,
+ sizeof(g_dsym_for_uuid_exe_path));
+ }
+ if (g_dsym_for_uuid_exe_exists) {
+ std::string uuid_str;
+ char file_path[PATH_MAX];
+ file_path[0] = '\0';
+
+ if (uuid_ptr)
+ uuid_str = uuid_ptr->GetAsString();
+
+ if (file_spec_ptr)
+ file_spec_ptr->GetPath(file_path, sizeof(file_path));
+
+ StreamString command;
+ if (!uuid_str.empty())
+ command.Printf("%s --ignoreNegativeCache --copyExecutable %s",
+ g_dsym_for_uuid_exe_path, uuid_str.c_str());
+ else if (file_path[0] != '\0')
+ command.Printf("%s --ignoreNegativeCache --copyExecutable %s",
+ g_dsym_for_uuid_exe_path, file_path);
+
+ if (!command.GetString().empty()) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ int exit_status = -1;
+ int signo = -1;
+ std::string command_output;
+ if (log) {
+ if (!uuid_str.empty())
+ log->Printf("Calling %s with UUID %s to find dSYM",
+ g_dsym_for_uuid_exe_path, uuid_str.c_str());
+ else if (file_path[0] != '\0')
+ log->Printf("Calling %s with file %s to find dSYM",
+ g_dsym_for_uuid_exe_path, file_path);
+ }
+ Status error = Host::RunShellCommand(
+ command.GetData(),
+ NULL, // current working directory
+ &exit_status, // Exit status
+ &signo, // Signal int *
+ &command_output, // Command output
+ std::chrono::seconds(
+ 30), // Large timeout to allow for long dsym download times
+ false); // Don't run in a shell (we don't need shell expansion)
+ if (error.Success() && exit_status == 0 && !command_output.empty()) {
+ CFCData data(CFDataCreateWithBytesNoCopy(
+ NULL, (const UInt8 *)command_output.data(), command_output.size(),
+ kCFAllocatorNull));
+
+ CFCReleaser<CFDictionaryRef> plist(
+ (CFDictionaryRef)::CFPropertyListCreateFromXMLData(
+ NULL, data.get(), kCFPropertyListImmutable, NULL));
+
+ if (plist.get() &&
+ CFGetTypeID(plist.get()) == CFDictionaryGetTypeID()) {
+ if (!uuid_str.empty()) {
+ CFCString uuid_cfstr(uuid_str.c_str());
+ CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue(
+ plist.get(), uuid_cfstr.get());
+ success =
+ GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec);
+ } else {
+ const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
+ if (num_values > 0) {
+ 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);
+ } else {
+ for (CFIndex i = 0; i < num_values; ++i) {
+ ModuleSpec curr_module_spec;
+ if (GetModuleSpecInfoFromUUIDDictionary(values[i],
+ curr_module_spec)) {
+ if (module_spec.GetArchitecture().IsCompatibleMatch(
+ curr_module_spec.GetArchitecture())) {
+ module_spec = curr_module_spec;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (log) {
+ if (!uuid_str.empty())
+ log->Printf("Called %s on %s, no matches",
+ g_dsym_for_uuid_exe_path, uuid_str.c_str());
+ else if (file_path[0] != '\0')
+ log->Printf("Called %s on %s, no matches",
+ g_dsym_for_uuid_exe_path, file_path);
+ }
+ }
+ }
+ }
+ }
+ return success;
+}
Index: source/Symbol/CMakeLists.txt
===================================================================
--- source/Symbol/CMakeLists.txt
+++ source/Symbol/CMakeLists.txt
@@ -1,3 +1,9 @@
+set(LLVM_OPTIONAL_SOURCES LocateSymbolFileMacOSX.cpp)
+
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ set(PLATFORM_SOURCES LocateSymbolFileMacOSX.cpp)
+endif()
+
add_lldb_library(lldbSymbol
ArmUnwindInfo.cpp
Block.cpp
@@ -18,6 +24,7 @@
FuncUnwinders.cpp
LineEntry.cpp
LineTable.cpp
+ LocateSymbolFile.cpp
ObjectFile.cpp
Symbol.cpp
SymbolContext.cpp
@@ -34,6 +41,8 @@
VariableList.cpp
VerifyDecl.cpp
+ ${PLATFORM_SOURCES}
+
LINK_LIBS
clangAST
clangBasic
Index: source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -21,9 +21,9 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
Index: source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
===================================================================
--- source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -15,8 +15,8 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Host/XML.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
Index: source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
===================================================================
--- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -15,7 +15,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
-#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
Index: source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
===================================================================
--- source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -18,7 +18,6 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -28,6 +27,7 @@
#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -41,7 +41,6 @@
#include "lldb/Host/PosixApi.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -54,6 +53,7 @@
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
Index: source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
===================================================================
--- source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -15,8 +15,8 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Target/RegisterContext.h"
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -29,7 +29,6 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -42,6 +41,7 @@
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TypeMap.h"
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -17,7 +17,6 @@
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
@@ -35,6 +34,7 @@
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
Index: source/Host/CMakeLists.txt
===================================================================
--- source/Host/CMakeLists.txt
+++ source/Host/CMakeLists.txt
@@ -44,7 +44,6 @@
common/SocketAddress.cpp
common/Socket.cpp
common/StringConvert.cpp
- common/Symbols.cpp
common/TaskPool.cpp
common/TCPSocket.cpp
common/Terminal.cpp
@@ -95,7 +94,6 @@
add_subdirectory(macosx/objcxx)
set(LLDBObjCLibs lldbHostMacOSXObjCXX)
add_host_subdirectory(macosx
- macosx/Symbols.cpp
macosx/cfcpp/CFCBundle.cpp
macosx/cfcpp/CFCData.cpp
macosx/cfcpp/CFCMutableArray.cpp
@@ -166,7 +164,6 @@
LINK_LIBS
lldbCore
- lldbSymbol
lldbTarget
lldbUtility
${EXTRA_LIBS}
Index: include/lldb/Host/Symbols.h
===================================================================
--- include/lldb/Host/Symbols.h
+++ include/lldb/Host/Symbols.h
@@ -1,61 +0,0 @@
-//===-- Symbols.h -----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_Symbols_h_
-#define liblldb_Symbols_h_
-
-#include <stdint.h>
-
-#include "lldb/Utility/FileSpec.h"
-
-namespace lldb_private {
-
-class ArchSpec;
-class ModuleSpec;
-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
- // current computers global settings.
- //----------------------------------------------------------------------
- static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec);
-
- static FileSpec FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
- const lldb_private::UUID *uuid,
- const ArchSpec *arch);
-
- //----------------------------------------------------------------------
- // 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,
- bool force_lookup = true);
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_Symbols_h_
Index: unittests/Host/SymbolsTest.cpp
===================================================================
--- unittests/Host/SymbolsTest.cpp
+++ unittests/Host/SymbolsTest.cpp
@@ -1,48 +0,0 @@
-//===-- SymbolsTest.cpp -----------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/Symbols.h"
-
-using namespace lldb_private;
-
-namespace {
-class SymbolsTest : public ::testing::Test {
-public:
- void SetUp() override {
- FileSystem::Initialize();
- HostInfo::Initialize();
- }
- void TearDown() override {
- HostInfo::Terminate();
- FileSystem::Terminate();
- }
-};
-} // namespace
-
-TEST_F(
- SymbolsTest,
- TerminateLocateExecutableSymbolFileForUnknownExecutableAndUnknownSymbolFile) {
- ModuleSpec module_spec;
- FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
- EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
-}
-
-TEST_F(SymbolsTest,
- LocateExecutableSymbolFileForUnknownExecutableAndMissingSymbolFile) {
- ModuleSpec module_spec;
- // using a GUID here because the symbol file shouldn't actually exist on disk
- module_spec.GetSymbolFileSpec().SetFile(
- "4A524676-B24B-4F4E-968A-551D465EBAF1.so", FileSpec::Style::native);
- FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
- EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
-}
Index: source/Host/macosx/Symbols.cpp
===================================================================
--- source/Host/macosx/Symbols.cpp
+++ source/Host/macosx/Symbols.cpp
@@ -1,654 +0,0 @@
-//===-- Symbols.cpp ---------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/Symbols.h"
-
-#include <dirent.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/ModuleList.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/CleanUp.h"
-#include "lldb/Utility/DataBuffer.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/Endian.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/Support/FileSystem.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-#if !defined(__arm__) && !defined(__arm64__) && \
- !defined(__aarch64__) // No DebugSymbols on the iOS devices
-extern "C" {
-
-CFURLRef DBGCopyFullDSYMURLForUUID(CFUUIDRef uuid, CFURLRef exec_url);
-CFDictionaryRef DBGCopyDSYMPropertyLists(CFURLRef dsym_url);
-}
-#endif
-
-int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
- ModuleSpec &return_module_spec) {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
- if (log)
- log->Printf("Spotlight lookup for .dSYM bundles is disabled.");
- return 0;
- }
-
- return_module_spec = module_spec;
- return_module_spec.GetFileSpec().Clear();
- return_module_spec.GetSymbolFileSpec().Clear();
-
- int items_found = 0;
-
-#if !defined(__arm__) && !defined(__arm64__) && \
- !defined(__aarch64__) // No DebugSymbols on the iOS devices
-
- const UUID *uuid = module_spec.GetUUIDPtr();
- const ArchSpec *arch = module_spec.GetArchitecturePtr();
-
- 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(
- ::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)) {
- if (log) {
- log->Printf("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)) {
- log->Printf("DebugSymbols framework returned dSYM path of %s for "
- "UUID %s -- looking for an exec file",
- path, uuid->GetAsString().c_str());
- }
- }
-
- CFCReleaser<CFDictionaryRef> dict(
- ::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()));
- }
- if (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))) {
- if (log) {
- log->Printf("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;
- }
- }
- }
-
- if (!success) {
- // No dictionary, check near the dSYM bundle for an executable that
- // matches...
- 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';
- if (log) {
- log->Printf("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;
- if (log) {
- log->Printf("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;
- if (log) {
- log->Printf("Executable binary %s next to dSYM is "
- "compatible; using",
- path);
- }
- }
- break;
- }
- }
- }
- }
- }
- }
- }
- }
-#endif // #if !defined (__arm__) && !defined (__arm64__) && !defined
- // (__aarch64__)
-
- return items_found;
-}
-
-FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
- const lldb_private::UUID *uuid,
- const ArchSpec *arch) {
- char path[PATH_MAX];
- if (dsym_bundle_fspec.GetPath(path, sizeof(path)) == 0)
- return {};
-
- ::strncat(path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
-
- DIR *dirp = opendir(path);
- if (!dirp)
- return {};
-
- // Make sure we close the directory before exiting this scope.
- CleanUp cleanup_dir(closedir, dirp);
-
- FileSpec dsym_fspec;
- dsym_fspec.GetDirectory().SetCString(path);
- struct dirent *dp;
- while ((dp = readdir(dirp)) != NULL) {
- // Only search directories
- if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) {
- if (dp->d_namlen == 1 && dp->d_name[0] == '.')
- continue;
-
- if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
- continue;
- }
-
- if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN) {
- dsym_fspec.GetFilename().SetCString(dp->d_name);
- ModuleSpecList module_specs;
- if (ObjectFile::GetModuleSpecifications(dsym_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 == NULL ||
- (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
- (arch == NULL ||
- (spec.GetArchitecturePtr() &&
- spec.GetArchitecture().IsCompatibleMatch(*arch)))) {
- return dsym_fspec;
- }
- }
- }
- }
- }
-
- return {};
-}
-
-static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
- ModuleSpec &module_spec) {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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("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());
- if (log) {
- log->Printf(
- "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;
- if (log) {
- log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str());
- }
- }
- }
-
- cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict,
- CFSTR("DBGArchitecture"));
- if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
- if (CFCString::FileSystemRepresentation(cf_str, str))
- module_spec.GetArchitecture().SetTriple(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(
- ConstString(DBGBuildSourcePath.c_str()),
- ConstString(DBGSourcePath.c_str()), 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(
- ConstString(build_path.GetPath().c_str()),
- ConstString(source_path.GetPath().c_str()), 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(
- ConstString(DBGBuildSourcePath.c_str()),
- ConstString(DBGSourcePath.c_str()), true);
- }
- }
- return success;
-}
-
-bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
- bool force_lookup) {
- bool success = false;
- const UUID *uuid_ptr = module_spec.GetUUIDPtr();
- const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
-
- // It's expensive to check for the DBGShellCommands defaults setting, only do
- // it once per lldb run and cache the result.
- static bool g_have_checked_for_dbgshell_command = false;
- static const char *g_dbgshell_command = NULL;
- if (!g_have_checked_for_dbgshell_command) {
- g_have_checked_for_dbgshell_command = true;
- CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
- CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
- if (defaults_setting &&
- CFGetTypeID(defaults_setting) == CFStringGetTypeID()) {
- char cstr_buf[PATH_MAX];
- if (CFStringGetCString((CFStringRef)defaults_setting, cstr_buf,
- sizeof(cstr_buf), kCFStringEncodingUTF8)) {
- g_dbgshell_command =
- strdup(cstr_buf); // this malloc'ed memory will never be freed
- }
- }
- if (defaults_setting) {
- CFRelease(defaults_setting);
- }
- }
-
- // When g_dbgshell_command is NULL, the user has not enabled the use of an
- // external program to find the symbols, don't run it for them.
- if (!force_lookup && g_dbgshell_command == NULL) {
- return false;
- }
-
- if (uuid_ptr ||
- (file_spec_ptr && FileSystem::Instance().Exists(*file_spec_ptr))) {
- static bool g_located_dsym_for_uuid_exe = false;
- static bool g_dsym_for_uuid_exe_exists = false;
- static char g_dsym_for_uuid_exe_path[PATH_MAX];
- if (!g_located_dsym_for_uuid_exe) {
- g_located_dsym_for_uuid_exe = true;
- const char *dsym_for_uuid_exe_path_cstr =
- getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
- FileSpec dsym_for_uuid_exe_spec;
- if (dsym_for_uuid_exe_path_cstr) {
- dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr,
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
- g_dsym_for_uuid_exe_exists =
- FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
- }
-
- if (!g_dsym_for_uuid_exe_exists) {
- dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID",
- FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists =
- FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
- if (!g_dsym_for_uuid_exe_exists) {
- long bufsize;
- if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) {
- char buffer[bufsize];
- struct passwd pwd;
- struct passwd *tilde_rc = NULL;
- // we are a library so we need to use the reentrant version of
- // getpwnam()
- if (getpwnam_r("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 &&
- tilde_rc && tilde_rc->pw_dir) {
- std::string dsymforuuid_path(tilde_rc->pw_dir);
- dsymforuuid_path += "/bin/dsymForUUID";
- dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(),
- FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists =
- FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
- }
- }
- }
- }
- if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) {
- dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command,
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
- g_dsym_for_uuid_exe_exists =
- FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
- }
-
- if (g_dsym_for_uuid_exe_exists)
- dsym_for_uuid_exe_spec.GetPath(g_dsym_for_uuid_exe_path,
- sizeof(g_dsym_for_uuid_exe_path));
- }
- if (g_dsym_for_uuid_exe_exists) {
- std::string uuid_str;
- char file_path[PATH_MAX];
- file_path[0] = '\0';
-
- if (uuid_ptr)
- uuid_str = uuid_ptr->GetAsString();
-
- if (file_spec_ptr)
- file_spec_ptr->GetPath(file_path, sizeof(file_path));
-
- StreamString command;
- if (!uuid_str.empty())
- command.Printf("%s --ignoreNegativeCache --copyExecutable %s",
- g_dsym_for_uuid_exe_path, uuid_str.c_str());
- else if (file_path[0] != '\0')
- command.Printf("%s --ignoreNegativeCache --copyExecutable %s",
- g_dsym_for_uuid_exe_path, file_path);
-
- if (!command.GetString().empty()) {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- int exit_status = -1;
- int signo = -1;
- std::string command_output;
- if (log) {
- if (!uuid_str.empty())
- log->Printf("Calling %s with UUID %s to find dSYM",
- g_dsym_for_uuid_exe_path, uuid_str.c_str());
- else if (file_path[0] != '\0')
- log->Printf("Calling %s with file %s to find dSYM",
- g_dsym_for_uuid_exe_path, file_path);
- }
- Status error = Host::RunShellCommand(
- command.GetData(),
- NULL, // current working directory
- &exit_status, // Exit status
- &signo, // Signal int *
- &command_output, // Command output
- std::chrono::seconds(
- 30), // Large timeout to allow for long dsym download times
- false); // Don't run in a shell (we don't need shell expansion)
- if (error.Success() && exit_status == 0 && !command_output.empty()) {
- CFCData data(CFDataCreateWithBytesNoCopy(
- NULL, (const UInt8 *)command_output.data(), command_output.size(),
- kCFAllocatorNull));
-
- CFCReleaser<CFDictionaryRef> plist(
- (CFDictionaryRef)::CFPropertyListCreateFromXMLData(
- NULL, data.get(), kCFPropertyListImmutable, NULL));
-
- if (plist.get() &&
- CFGetTypeID(plist.get()) == CFDictionaryGetTypeID()) {
- if (!uuid_str.empty()) {
- CFCString uuid_cfstr(uuid_str.c_str());
- CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue(
- plist.get(), uuid_cfstr.get());
- success =
- GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec);
- } else {
- const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
- if (num_values > 0) {
- 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);
- } else {
- for (CFIndex i = 0; i < num_values; ++i) {
- ModuleSpec curr_module_spec;
- if (GetModuleSpecInfoFromUUIDDictionary(values[i],
- curr_module_spec)) {
- if (module_spec.GetArchitecture().IsCompatibleMatch(
- curr_module_spec.GetArchitecture())) {
- module_spec = curr_module_spec;
- return true;
- }
- }
- }
- }
- }
- }
- }
- } else {
- if (log) {
- if (!uuid_str.empty())
- log->Printf("Called %s on %s, no matches",
- g_dsym_for_uuid_exe_path, uuid_str.c_str());
- else if (file_path[0] != '\0')
- log->Printf("Called %s on %s, no matches",
- g_dsym_for_uuid_exe_path, file_path);
- }
- }
- }
- }
- }
- return success;
-}
Index: source/Host/common/Symbols.cpp
===================================================================
--- source/Host/common/Symbols.cpp
+++ source/Host/common/Symbols.cpp
@@ -1,383 +0,0 @@
-//===-- Symbols.cpp ---------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/Symbols.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Host/FileSystem.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/Log.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/Timer.h"
-#include "lldb/Utility/UUID.h"
-
-#include "llvm/Support/FileSystem.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;
-
-#if defined(__APPLE__)
-
-// Forward declaration of method defined in source/Host/macosx/Symbols.cpp
-int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
- ModuleSpec &return_module_spec);
-
-#else
-
-int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
- ModuleSpec &return_module_spec) {
- // Cannot find MacOSX files using debug symbols on non MacOSX.
- return 0;
-}
-
-#endif
-
-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 == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
- (arch == NULL || (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;
- if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, 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 = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- const FileSpec &exec_fspec = module_spec.GetFileSpec();
- if (exec_fspec) {
- if (::LookForDsymNextToExecutablePath (module_spec, exec_fspec, dsym_fspec)) {
- if (log) {
- log->Printf("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) {
- log->Printf("dSYM with matching UUID & arch found at %s",
- dsym_fspec.GetPath().c_str());
- }
- return true;
- }
- }
- parent_dirs.RemoveLastPathComponent();
- }
- }
- }
- dsym_fspec.Clear();
- return false;
-}
-
-static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
- const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
- const ArchSpec *arch = module_spec.GetArchitecturePtr();
- const UUID *uuid = module_spec.GetUUIDPtr();
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat,
- "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
- exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
- arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
-
- FileSpec symbol_fspec;
- ModuleSpec dsym_module_spec;
- // First try and find the dSYM in the same directory as the executable or in
- // an appropriate parent directory
- if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) {
- // We failed to easily find the dSYM above, so use DebugSymbols
- LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec);
- } else {
- dsym_module_spec.GetSymbolFileSpec() = symbol_fspec;
- }
- return dsym_module_spec.GetSymbolFileSpec();
-}
-
-ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
- ModuleSpec result;
- const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
- const ArchSpec *arch = module_spec.GetArchitecturePtr();
- const UUID *uuid = module_spec.GetUUIDPtr();
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
- exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
- arch ? arch->GetArchitectureName() : "<NULL>", (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 Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
- FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
- if (symbol_file_spec.IsAbsolute() &&
- FileSystem::Instance().Exists(symbol_file_spec))
- return symbol_file_spec;
-
- const char *symbol_filename = symbol_file_spec.GetFilename().AsCString();
- if (symbol_filename && symbol_filename[0]) {
- FileSpecList debug_file_search_paths(
- Target::GetDefaultDebugFileSearchPaths());
-
- // Add module directory.
- FileSpec module_file_spec = module_spec.GetFileSpec();
- // We keep the unresolved pathname if it fails.
- FileSystem::Instance().ResolveSymbolicLink(module_file_spec, module_file_spec);
-
- const ConstString &file_dir = module_file_spec.GetDirectory();
- {
- FileSpec file_spec(file_dir.AsCString("."));
- FileSystem::Instance().Resolve(file_spec);
- debug_file_search_paths.AppendIfUnique(file_spec);
- }
-
- if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
-
- // Add current working directory.
- {
- FileSpec file_spec(".");
- FileSystem::Instance().Resolve(file_spec);
- debug_file_search_paths.AppendIfUnique(file_spec);
- }
-
-#ifndef _WIN32
-#if defined(__NetBSD__)
- // Add /usr/libdata/debug directory.
- {
- FileSpec file_spec("/usr/libdata/debug");
- FileSystem::Instance().Resolve(file_spec);
- debug_file_search_paths.AppendIfUnique(file_spec);
- }
-#else
- // Add /usr/lib/debug directory.
- {
- FileSpec file_spec("/usr/lib/debug");
- FileSystem::Instance().Resolve(file_spec);
- debug_file_search_paths.AppendIfUnique(file_spec);
- }
-#endif
-#endif // _WIN32
- }
-
- std::string uuid_str;
- const UUID &module_uuid = module_spec.GetUUID();
- if (module_uuid.IsValid()) {
- // Some debug files are stored in the .build-id directory like this:
- // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
- uuid_str = module_uuid.GetAsString("");
- std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
- ::tolower);
- uuid_str.insert(2, 1, '/');
- uuid_str = uuid_str + ".debug";
- }
-
- size_t num_directories = debug_file_search_paths.GetSize();
- for (size_t idx = 0; idx < num_directories; ++idx) {
- FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
- FileSystem::Instance().Resolve(dirspec);
- if (!FileSystem::Instance().IsDirectory(dirspec))
- continue;
-
- std::vector<std::string> files;
- std::string dirname = dirspec.GetPath();
-
- files.push_back(dirname + "/" + symbol_filename);
- files.push_back(dirname + "/.debug/" + symbol_filename);
- files.push_back(dirname + "/.build-id/" + uuid_str);
-
- // Some debug files may stored in the module directory like this:
- // /usr/lib/debug/usr/lib/library.so.debug
- if (!file_dir.IsEmpty())
- files.push_back(dirname + file_dir.AsCString() + "/" + symbol_filename);
-
- const uint32_t num_files = files.size();
- for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
- const std::string &filename = files[idx_file];
- FileSpec file_spec(filename);
- FileSystem::Instance().Resolve(file_spec);
-
- if (llvm::sys::fs::equivalent(file_spec.GetPath(),
- module_file_spec.GetPath()))
- continue;
-
- if (FileSystem::Instance().Exists(file_spec)) {
- lldb_private::ModuleSpecList specs;
- const size_t num_specs =
- ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);
- assert(num_specs <= 1 &&
- "Symbol Vendor supports only a single architecture");
- if (num_specs == 1) {
- ModuleSpec mspec;
- if (specs.GetModuleSpecAtIndex(0, mspec)) {
- // Skip the uuids check if module_uuid is invalid. For example,
- // this happens for *.dwp files since at the moment llvm-dwp
- // doesn't output build ids, nor does binutils dwp.
- if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
- return file_spec;
- }
- }
- }
- }
- }
- }
-
- return LocateExecutableSymbolFileDsym(module_spec);
-}
-
-#if !defined(__APPLE__)
-
-FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle,
- const lldb_private::UUID *uuid,
- const ArchSpec *arch) {
- // FIXME
- return FileSpec();
-}
-
-bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
- bool force_lookup) {
- // Fill in the module_spec.GetFileSpec() for the object file and/or the
- // module_spec.GetSymbolFileSpec() for the debug symbols file.
- return false;
-}
-
-#endif
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits