diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp new file mode 100644 index 000000000000..919f26ba7012 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp @@ -0,0 +1,261 @@ +//===-- SymbolLocatorDefault.cpp ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SymbolLocatorDefault.h" + +#include <cstring> +#include <optional> + +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timer.h" +#include "lldb/Utility/UUID.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" + +#if defined(__FreeBSD__) +#include <sys/sysctl.h> +#endif + +// From MacOSX system header "mach/machine.h" +typedef int cpu_type_t; +typedef int cpu_subtype_t; + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(SymbolLocatorDefault) + +SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {} + +void SymbolLocatorDefault::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile, LocateExecutableSymbolFile, + DownloadObjectAndSymbolFile); +} + +void SymbolLocatorDefault::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef SymbolLocatorDefault::GetPluginDescriptionStatic() { + return "Default symbol locator."; +} + +SymbolLocator *SymbolLocatorDefault::CreateInstance() { + return new SymbolLocatorDefault(); +} + +std::optional<ModuleSpec> SymbolLocatorDefault::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { + const FileSpec &exec_fspec = module_spec.GetFileSpec(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + LLDB_SCOPED_TIMERF( + "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec.GetFilename().AsCString("<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)) { + ModuleSpec result; + result.GetFileSpec() = exec_fspec; + return result; + } + + return {}; +} + +// Keep "symbols.enable-external-lookup" description in sync with this function. +std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + + FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); + if (symbol_file_spec.IsAbsolute() && + FileSystem::Instance().Exists(symbol_file_spec)) + return symbol_file_spec; + + Progress progress( + "Locating external symbol file", + module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")); + + FileSpecList debug_file_search_paths = default_search_paths; + + // 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); + + 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); + } +#if defined(__FreeBSD__) + // Add $LOCALBASE/lib/debug directory, where LOCALBASE is + // usually /usr/local, but may be adjusted by the end user. + { + int mib[2]; + char buf[PATH_MAX]; + size_t len = PATH_MAX; + + mib[0] = CTL_USER; + mib[1] = USER_LOCALBASE; + if (::sysctl(mib, 2, buf, &len, NULL, 0) == 0) { + FileSpec file_spec("/lib/debug"); + file_spec.PrependPathComponent(llvm::StringRef(buf)); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } + } +#endif // __FreeBSD__ +#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(); + + if (!uuid_str.empty()) + files.push_back(dirname + "/.build-id/" + uuid_str); + if (symbol_file_spec.GetFilename()) { + files.push_back(dirname + "/" + + symbol_file_spec.GetFilename().GetCString()); + files.push_back(dirname + "/.debug/" + + symbol_file_spec.GetFilename().GetCString()); + + // 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_file_spec.GetFilename().GetCString()); + } + + 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); + ModuleSpec mspec; + bool valid_mspec = false; + if (num_specs == 2) { + // Special case to handle both i386 and i686 from ObjectFilePECOFF + ModuleSpec mspec2; + if (specs.GetModuleSpecAtIndex(0, mspec) && + specs.GetModuleSpecAtIndex(1, mspec2) && + mspec.GetArchitecture().GetTriple().isCompatibleWith( + mspec2.GetArchitecture().GetTriple())) { + valid_mspec = true; + } + } + if (!valid_mspec) { + assert(num_specs <= 1 && + "Symbol Vendor supports only a single architecture"); + if (num_specs == 1) { + if (specs.GetModuleSpecAtIndex(0, mspec)) { + valid_mspec = true; + } + } + } + if (valid_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 {}; +} + +bool SymbolLocatorDefault::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, + bool force_lookup, + bool copy_executable) { + return false; +} |