brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · 919f26b Raw
262 lines · cpp
1//===-- SymbolLocatorDefault.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SymbolLocatorDefault.h"10 11#include <cstring>12#include <optional>13 14#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"15#include "lldb/Core/Debugger.h"16#include "lldb/Core/Module.h"17#include "lldb/Core/ModuleList.h"18#include "lldb/Core/ModuleSpec.h"19#include "lldb/Core/PluginManager.h"20#include "lldb/Core/Progress.h"21#include "lldb/Core/Section.h"22#include "lldb/Host/FileSystem.h"23#include "lldb/Host/Host.h"24#include "lldb/Symbol/ObjectFile.h"25#include "lldb/Target/Target.h"26#include "lldb/Utility/ArchSpec.h"27#include "lldb/Utility/DataBuffer.h"28#include "lldb/Utility/DataExtractor.h"29#include "lldb/Utility/LLDBLog.h"30#include "lldb/Utility/Log.h"31#include "lldb/Utility/StreamString.h"32#include "lldb/Utility/Timer.h"33#include "lldb/Utility/UUID.h"34 35#include "llvm/ADT/SmallSet.h"36#include "llvm/Support/FileSystem.h"37#include "llvm/Support/ThreadPool.h"38 39#if defined(__FreeBSD__)40#include <sys/sysctl.h>41#endif42 43// From MacOSX system header "mach/machine.h"44typedef int cpu_type_t;45typedef int cpu_subtype_t;46 47using namespace lldb;48using namespace lldb_private;49 50LLDB_PLUGIN_DEFINE(SymbolLocatorDefault)51 52SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {}53 54void SymbolLocatorDefault::Initialize() {55  PluginManager::RegisterPlugin(56      GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,57      LocateExecutableObjectFile, LocateExecutableSymbolFile,58      DownloadObjectAndSymbolFile);59}60 61void SymbolLocatorDefault::Terminate() {62  PluginManager::UnregisterPlugin(CreateInstance);63}64 65llvm::StringRef SymbolLocatorDefault::GetPluginDescriptionStatic() {66  return "Default symbol locator.";67}68 69SymbolLocator *SymbolLocatorDefault::CreateInstance() {70  return new SymbolLocatorDefault();71}72 73std::optional<ModuleSpec> SymbolLocatorDefault::LocateExecutableObjectFile(74    const ModuleSpec &module_spec) {75  const FileSpec &exec_fspec = module_spec.GetFileSpec();76  const ArchSpec *arch = module_spec.GetArchitecturePtr();77  const UUID *uuid = module_spec.GetUUIDPtr();78  LLDB_SCOPED_TIMERF(79      "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",80      exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>",81      arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);82 83  ModuleSpecList module_specs;84  ModuleSpec matched_module_spec;85  if (exec_fspec &&86      ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) &&87      module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) {88    ModuleSpec result;89    result.GetFileSpec() = exec_fspec;90    return result;91  }92 93  return {};94}95 96// Keep "symbols.enable-external-lookup" description in sync with this function.97std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile(98    const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {99 100  FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();101  if (symbol_file_spec.IsAbsolute() &&102      FileSystem::Instance().Exists(symbol_file_spec))103    return symbol_file_spec;104 105  Progress progress(106      "Locating external symbol file",107      module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"));108 109  FileSpecList debug_file_search_paths = default_search_paths;110 111  // Add module directory.112  FileSpec module_file_spec = module_spec.GetFileSpec();113  // We keep the unresolved pathname if it fails.114  FileSystem::Instance().ResolveSymbolicLink(module_file_spec,115                                             module_file_spec);116 117  ConstString file_dir = module_file_spec.GetDirectory();118  {119    FileSpec file_spec(file_dir.AsCString("."));120    FileSystem::Instance().Resolve(file_spec);121    debug_file_search_paths.AppendIfUnique(file_spec);122  }123 124  if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {125 126    // Add current working directory.127    {128      FileSpec file_spec(".");129      FileSystem::Instance().Resolve(file_spec);130      debug_file_search_paths.AppendIfUnique(file_spec);131    }132 133#ifndef _WIN32134#if defined(__NetBSD__)135    // Add /usr/libdata/debug directory.136    {137      FileSpec file_spec("/usr/libdata/debug");138      FileSystem::Instance().Resolve(file_spec);139      debug_file_search_paths.AppendIfUnique(file_spec);140    }141#else142    // Add /usr/lib/debug directory.143    {144      FileSpec file_spec("/usr/lib/debug");145      FileSystem::Instance().Resolve(file_spec);146      debug_file_search_paths.AppendIfUnique(file_spec);147    }148#if defined(__FreeBSD__)149    // Add $LOCALBASE/lib/debug directory, where LOCALBASE is150    // usually /usr/local, but may be adjusted by the end user.151    {152      int mib[2];153      char buf[PATH_MAX];154      size_t len = PATH_MAX;155 156      mib[0] = CTL_USER;157      mib[1] = USER_LOCALBASE;158      if (::sysctl(mib, 2, buf, &len, NULL, 0) == 0) {159        FileSpec file_spec("/lib/debug");160        file_spec.PrependPathComponent(llvm::StringRef(buf));161        FileSystem::Instance().Resolve(file_spec);162        debug_file_search_paths.AppendIfUnique(file_spec);163      }164    }165#endif // __FreeBSD__166#endif167#endif // _WIN32168  }169 170  std::string uuid_str;171  const UUID &module_uuid = module_spec.GetUUID();172  if (module_uuid.IsValid()) {173    // Some debug files are stored in the .build-id directory like this:174    //   /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug175    uuid_str = module_uuid.GetAsString("");176    std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),177                   ::tolower);178    uuid_str.insert(2, 1, '/');179    uuid_str = uuid_str + ".debug";180  }181 182  size_t num_directories = debug_file_search_paths.GetSize();183  for (size_t idx = 0; idx < num_directories; ++idx) {184    FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);185    FileSystem::Instance().Resolve(dirspec);186    if (!FileSystem::Instance().IsDirectory(dirspec))187      continue;188 189    std::vector<std::string> files;190    std::string dirname = dirspec.GetPath();191 192    if (!uuid_str.empty())193      files.push_back(dirname + "/.build-id/" + uuid_str);194    if (symbol_file_spec.GetFilename()) {195      files.push_back(dirname + "/" +196                      symbol_file_spec.GetFilename().GetCString());197      files.push_back(dirname + "/.debug/" +198                      symbol_file_spec.GetFilename().GetCString());199 200      // Some debug files may stored in the module directory like this:201      //   /usr/lib/debug/usr/lib/library.so.debug202      if (!file_dir.IsEmpty())203        files.push_back(dirname + file_dir.AsCString() + "/" +204                        symbol_file_spec.GetFilename().GetCString());205    }206 207    const uint32_t num_files = files.size();208    for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {209      const std::string &filename = files[idx_file];210      FileSpec file_spec(filename);211      FileSystem::Instance().Resolve(file_spec);212 213      if (llvm::sys::fs::equivalent(file_spec.GetPath(),214                                    module_file_spec.GetPath()))215        continue;216 217      if (FileSystem::Instance().Exists(file_spec)) {218        lldb_private::ModuleSpecList specs;219        const size_t num_specs =220            ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);221        ModuleSpec mspec;222        bool valid_mspec = false;223        if (num_specs == 2) {224          // Special case to handle both i386 and i686 from ObjectFilePECOFF225          ModuleSpec mspec2;226          if (specs.GetModuleSpecAtIndex(0, mspec) &&227              specs.GetModuleSpecAtIndex(1, mspec2) &&228              mspec.GetArchitecture().GetTriple().isCompatibleWith(229                  mspec2.GetArchitecture().GetTriple())) {230            valid_mspec = true;231          }232        }233        if (!valid_mspec) {234          assert(num_specs <= 1 &&235                 "Symbol Vendor supports only a single architecture");236          if (num_specs == 1) {237            if (specs.GetModuleSpecAtIndex(0, mspec)) {238              valid_mspec = true;239            }240          }241        }242        if (valid_mspec) {243          // Skip the uuids check if module_uuid is invalid. For example,244          // this happens for *.dwp files since at the moment llvm-dwp245          // doesn't output build ids, nor does binutils dwp.246          if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())247            return file_spec;248        }249      }250    }251  }252 253  return {};254}255 256bool SymbolLocatorDefault::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,257                                                       Status &error,258                                                       bool force_lookup,259                                                       bool copy_executable) {260  return false;261}262