brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 711d2ca Raw
156 lines · cpp
1//===-- HostInfoLinux.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 "lldb/Host/linux/HostInfoLinux.h"10#include "lldb/Host/Config.h"11#include "lldb/Host/FileSystem.h"12#include "lldb/Utility/LLDBLog.h"13#include "lldb/Utility/Log.h"14 15#include "llvm/Support/Threading.h"16 17#include <climits>18#include <cstdio>19#include <cstring>20#include <sys/utsname.h>21#include <unistd.h>22 23#include <algorithm>24#include <mutex>25#include <optional>26 27using namespace lldb_private;28 29namespace {30struct HostInfoLinuxFields {31  llvm::once_flag m_distribution_once_flag;32  std::string m_distribution_id;33};34} // namespace35 36static HostInfoLinuxFields *g_fields = nullptr;37 38void HostInfoLinux::Initialize(SharedLibraryDirectoryHelper *helper) {39  HostInfoPosix::Initialize(helper);40 41  g_fields = new HostInfoLinuxFields();42}43 44void HostInfoLinux::Terminate() {45  assert(g_fields && "Missing call to Initialize?");46  delete g_fields;47  g_fields = nullptr;48  HostInfoBase::Terminate();49}50 51llvm::StringRef HostInfoLinux::GetDistributionId() {52  assert(g_fields && "Missing call to Initialize?");53  // Try to run 'lbs_release -i', and use that response for the distribution54  // id.55  llvm::call_once(g_fields->m_distribution_once_flag, []() {56    Log *log = GetLog(LLDBLog::Host);57    LLDB_LOGF(log, "attempting to determine Linux distribution...");58 59    // check if the lsb_release command exists at one of the following paths60    const char *const exe_paths[] = {"/bin/lsb_release",61                                     "/usr/bin/lsb_release"};62 63    for (size_t exe_index = 0;64         exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) {65      const char *const get_distribution_info_exe = exe_paths[exe_index];66      if (access(get_distribution_info_exe, F_OK)) {67        // this exe doesn't exist, move on to next exe68        LLDB_LOGF(log, "executable doesn't exist: %s",69                  get_distribution_info_exe);70        continue;71      }72 73      // execute the distribution-retrieval command, read output74      std::string get_distribution_id_command(get_distribution_info_exe);75      get_distribution_id_command += " -i";76 77      FILE *file = popen(get_distribution_id_command.c_str(), "r");78      if (!file) {79        LLDB_LOGF(log,80                  "failed to run command: \"%s\", cannot retrieve "81                  "platform information",82                  get_distribution_id_command.c_str());83        break;84      }85 86      // retrieve the distribution id string.87      char distribution_id[256] = {'\0'};88      if (fgets(distribution_id, sizeof(distribution_id) - 1, file) !=89          nullptr) {90        LLDB_LOGF(log, "distribution id command returned \"%s\"",91                  distribution_id);92 93        const char *const distributor_id_key = "Distributor ID:\t";94        if (strstr(distribution_id, distributor_id_key)) {95          // strip newlines96          std::string id_string(distribution_id + strlen(distributor_id_key));97          llvm::erase(id_string, '\n');98 99          // lower case it and convert whitespace to underscores100          std::transform(101              id_string.begin(), id_string.end(), id_string.begin(),102              [](char ch) { return tolower(isspace(ch) ? '_' : ch); });103 104          g_fields->m_distribution_id = id_string;105          LLDB_LOGF(log, "distribution id set to \"%s\"",106                    g_fields->m_distribution_id.c_str());107        } else {108          LLDB_LOGF(log, "failed to find \"%s\" field in \"%s\"",109                    distributor_id_key, distribution_id);110        }111      } else {112        LLDB_LOGF(log,113                  "failed to retrieve distribution id, \"%s\" returned no"114                  " lines",115                  get_distribution_id_command.c_str());116      }117 118      // clean up the file119      pclose(file);120    }121  });122 123  return g_fields->m_distribution_id;124}125 126FileSpec HostInfoLinux::GetProgramFileSpec() {127  static FileSpec g_program_filespec;128 129  if (!g_program_filespec) {130    char exe_path[PATH_MAX];131    ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);132    if (len > 0) {133      exe_path[len] = 0;134      g_program_filespec.SetFile(exe_path, FileSpec::Style::native);135    }136  }137 138  return g_program_filespec;139}140 141void HostInfoLinux::ComputeHostArchitectureSupport(ArchSpec &arch_32,142                                                   ArchSpec &arch_64) {143  HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64);144 145  // On Linux, "unknown" in the vendor slot isn't what we want for the default146  // triple.  It's probably an artifact of config.guess.147  if (arch_32.IsValid()) {148    if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor)149      arch_32.GetTriple().setVendorName(llvm::StringRef());150  }151  if (arch_64.IsValid()) {152    if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor)153      arch_64.GetTriple().setVendorName(llvm::StringRef());154  }155}156