Files
clang-p2996/lldb/source/Host/common/HostInfoBase.cpp
Zachary Turner 270e99ab0a Fix some posix assumptions related to running shell commands.
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
2014-12-08 21:36:42 +00:00

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;
}
}