This is a resubmit of r223548, which was reverted due to breaking tests on Linux and Mac. This resubmit fixes the reason for the revert by adding back some accidentally removed code which appends -c to the command line when running /bin/sh. This resubmit also differs from the original patch in that it sets the architecture on the ProcessLaunchInfo. A follow-up patch will refactor this to separate the logic for different platforms. Differential Revision: http://reviews.llvm.org/D6553 Reviewed By: Greg Clayton llvm-svn: 223695
343 lines
12 KiB
C++
343 lines
12 KiB
C++
//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Host/Config.h"
|
|
|
|
#include "lldb/Core/ArchSpec.h"
|
|
#include "lldb/Core/Log.h"
|
|
#include "lldb/Core/StreamString.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/Host/Host.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "lldb/Host/HostInfoBase.h"
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <thread>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
namespace
|
|
{
|
|
void
|
|
CleanupProcessSpecificLLDBTempDir()
|
|
{
|
|
// Get the process specific LLDB temporary directory and delete it.
|
|
FileSpec tmpdir_file_spec;
|
|
if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
|
|
return;
|
|
|
|
// Remove the LLDB temporary directory if we have one. Set "recurse" to
|
|
// true to all files that were created for the LLDB process can be cleaned up.
|
|
FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
|
|
}
|
|
|
|
struct HostInfoBaseFields
|
|
{
|
|
uint32_t m_number_cpus;
|
|
std::string m_vendor_string;
|
|
std::string m_os_string;
|
|
std::string m_host_triple;
|
|
|
|
ArchSpec m_host_arch_32;
|
|
ArchSpec m_host_arch_64;
|
|
|
|
FileSpec m_lldb_so_dir;
|
|
FileSpec m_lldb_support_exe_dir;
|
|
FileSpec m_lldb_headers_dir;
|
|
FileSpec m_lldb_python_dir;
|
|
FileSpec m_lldb_clang_resource_dir;
|
|
FileSpec m_lldb_system_plugin_dir;
|
|
FileSpec m_lldb_user_plugin_dir;
|
|
FileSpec m_lldb_tmp_dir;
|
|
};
|
|
|
|
HostInfoBaseFields *g_fields = nullptr;
|
|
}
|
|
|
|
#define COMPUTE_LLDB_PATH(compute_function, member_var) \
|
|
{ \
|
|
static bool is_initialized = false; \
|
|
static bool success = false; \
|
|
if (!is_initialized) \
|
|
{ \
|
|
is_initialized = true; \
|
|
success = HostInfo::compute_function(member_var); \
|
|
} \
|
|
if (success) \
|
|
result = &member_var; \
|
|
}
|
|
|
|
void
|
|
HostInfoBase::Initialize()
|
|
{
|
|
g_fields = new HostInfoBaseFields();
|
|
}
|
|
|
|
uint32_t
|
|
HostInfoBase::GetNumberCPUS()
|
|
{
|
|
static bool is_initialized = false;
|
|
if (!is_initialized)
|
|
{
|
|
g_fields->m_number_cpus = std::thread::hardware_concurrency();
|
|
is_initialized = true;
|
|
}
|
|
|
|
return g_fields->m_number_cpus;
|
|
}
|
|
|
|
uint32_t
|
|
HostInfoBase::GetMaxThreadNameLength()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
llvm::StringRef
|
|
HostInfoBase::GetVendorString()
|
|
{
|
|
static bool is_initialized = false;
|
|
if (!is_initialized)
|
|
{
|
|
const ArchSpec &host_arch = HostInfo::GetArchitecture();
|
|
const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
|
|
g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
|
|
is_initialized = true;
|
|
}
|
|
return g_fields->m_vendor_string;
|
|
}
|
|
|
|
llvm::StringRef
|
|
HostInfoBase::GetOSString()
|
|
{
|
|
static bool is_initialized = false;
|
|
if (!is_initialized)
|
|
{
|
|
const ArchSpec &host_arch = HostInfo::GetArchitecture();
|
|
const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
|
|
g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
|
|
is_initialized = true;
|
|
}
|
|
return g_fields->m_os_string;
|
|
}
|
|
|
|
llvm::StringRef
|
|
HostInfoBase::GetTargetTriple()
|
|
{
|
|
static bool is_initialized = false;
|
|
if (!is_initialized)
|
|
{
|
|
const ArchSpec &host_arch = HostInfo::GetArchitecture();
|
|
g_fields->m_host_triple = host_arch.GetTriple().getTriple();
|
|
is_initialized = true;
|
|
}
|
|
return g_fields->m_host_triple;
|
|
}
|
|
|
|
const ArchSpec &
|
|
HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
|
|
{
|
|
static bool is_initialized = false;
|
|
if (!is_initialized)
|
|
{
|
|
HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
|
|
is_initialized = true;
|
|
}
|
|
|
|
// If an explicit 32 or 64-bit architecture was requested, return that.
|
|
if (arch_kind == eArchKind32)
|
|
return g_fields->m_host_arch_32;
|
|
if (arch_kind == eArchKind64)
|
|
return g_fields->m_host_arch_64;
|
|
|
|
// Otherwise prefer the 64-bit architecture if it is valid.
|
|
return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
|
|
{
|
|
file_spec.Clear();
|
|
|
|
#if defined(LLDB_DISABLE_PYTHON)
|
|
if (type == lldb::ePathTypePythonDir)
|
|
return false;
|
|
#endif
|
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
|
|
FileSpec *result = nullptr;
|
|
switch (type)
|
|
{
|
|
case lldb::ePathTypeLLDBShlibDir:
|
|
COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeSupportExecutableDir:
|
|
COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
|
|
g_fields->m_lldb_support_exe_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeHeaderDir:
|
|
COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypePythonDir:
|
|
COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeClangDir:
|
|
COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeLLDBSystemPlugins:
|
|
COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
|
|
g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeLLDBUserPlugins:
|
|
COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
|
|
g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
|
|
break;
|
|
case lldb::ePathTypeLLDBTempSystemDir:
|
|
COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
|
|
if (log)
|
|
log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
|
|
break;
|
|
}
|
|
|
|
if (!result)
|
|
return false;
|
|
file_spec = *result;
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
|
|
{
|
|
// To get paths related to LLDB we get the path to the executable that
|
|
// contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
|
|
// on linux this is assumed to be the "lldb" main executable. If LLDB on
|
|
// linux is actually in a shared library (liblldb.so) then this function will
|
|
// need to be modified to "do the right thing".
|
|
|
|
FileSpec lldb_file_spec(
|
|
Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
|
|
|
|
// Remove the filename so that this FileSpec only represents the directory.
|
|
file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
|
|
|
|
return (bool)file_spec.GetDirectory();
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
|
|
{
|
|
return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
|
|
{
|
|
const char *tmpdir_cstr = getenv("TMPDIR");
|
|
if (tmpdir_cstr == NULL)
|
|
{
|
|
tmpdir_cstr = getenv("TMP");
|
|
if (tmpdir_cstr == NULL)
|
|
tmpdir_cstr = getenv("TEMP");
|
|
}
|
|
if (!tmpdir_cstr)
|
|
return false;
|
|
|
|
FileSpec temp_file_spec(tmpdir_cstr, false);
|
|
temp_file_spec.AppendPathComponent("lldb");
|
|
if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success())
|
|
return false;
|
|
|
|
std::string pid_str;
|
|
llvm::raw_string_ostream pid_stream(pid_str);
|
|
pid_stream << Host::GetCurrentProcessID();
|
|
temp_file_spec.AppendPathComponent(pid_stream.str().c_str());
|
|
std::string final_path = temp_file_spec.GetPath();
|
|
if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success())
|
|
return false;
|
|
|
|
// Make an atexit handler to clean up the process specify LLDB temp dir
|
|
// and all of its contents.
|
|
::atexit(CleanupProcessSpecificLLDBTempDir);
|
|
file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size());
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
|
|
{
|
|
// TODO(zturner): Figure out how to compute the header directory for all platforms.
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
|
|
{
|
|
// TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
|
|
{
|
|
// TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
|
|
return false;
|
|
}
|
|
|
|
void
|
|
HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
|
|
{
|
|
llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
|
|
|
|
arch_32.Clear();
|
|
arch_64.Clear();
|
|
|
|
switch (triple.getArch())
|
|
{
|
|
default:
|
|
arch_32.SetTriple(triple);
|
|
break;
|
|
|
|
case llvm::Triple::x86_64:
|
|
arch_64.SetTriple(triple);
|
|
arch_32.SetTriple(triple.get32BitArchVariant());
|
|
break;
|
|
|
|
case llvm::Triple::aarch64:
|
|
case llvm::Triple::mips64:
|
|
case llvm::Triple::sparcv9:
|
|
case llvm::Triple::ppc64:
|
|
arch_64.SetTriple(triple);
|
|
break;
|
|
}
|
|
}
|