aboutsummaryrefslogtreecommitdiff
path: root/source/Host/common/Host.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/common/Host.cpp')
-rw-r--r--source/Host/common/Host.cpp1282
1 files changed, 125 insertions, 1157 deletions
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index d43221c0e136..00c2fa37b383 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -12,11 +12,12 @@
// C includes
#include <errno.h>
#include <limits.h>
+#include <stdlib.h>
#include <sys/types.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
-#include <WS2tcpip.h>
+#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <dlfcn.h>
@@ -35,10 +36,9 @@
#include <mach/mach_port.h>
#include <mach/mach_init.h>
#include <mach-o/dyld.h>
-#include <AvailabilityMacros.h>
#endif
-#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
+#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__)
#include <spawn.h>
#include <sys/wait.h>
#include <sys/syscall.h>
@@ -48,7 +48,11 @@
#include <pthread_np.h>
#endif
+// C++ includes
+#include <limits>
+
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Debugger.h"
@@ -60,13 +64,19 @@
#include "lldb/Host/Config.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Mutex.h"
+#include "lldb/lldb-private-forward.h"
+#include "lldb/Target/FileAction.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/CleanUp.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#if defined (__APPLE__)
@@ -85,6 +95,12 @@ extern "C"
using namespace lldb;
using namespace lldb_private;
+// Define maximum thread name length
+#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__NetBSD__)
+uint32_t const Host::MAX_THREAD_NAME_LENGTH = 16;
+#else
+uint32_t const Host::MAX_THREAD_NAME_LENGTH = std::numeric_limits<uint32_t>::max ();
+#endif
#if !defined (__APPLE__) && !defined (_WIN32)
struct MonitorInfo
@@ -116,7 +132,18 @@ Host::StartMonitoringChildProcess
info_ptr->monitor_signals = monitor_signals;
char thread_name[256];
- ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
+
+ if (Host::MAX_THREAD_NAME_LENGTH <= 16)
+ {
+ // On some platforms, the thread name is limited to 16 characters. We need to
+ // abbreviate there or the pid info would get truncated.
+ ::snprintf (thread_name, sizeof(thread_name), "wait4(%" PRIu64 ")", pid);
+ }
+ else
+ {
+ ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
+ }
+
thread = ThreadCreate (thread_name,
MonitorChildProcessThreadFunction,
info_ptr,
@@ -168,7 +195,7 @@ MonitorChildProcessThreadFunction (void *arg)
const bool monitor_signals = info->monitor_signals;
assert (info->pid <= UINT32_MAX);
- const ::pid_t pid = monitor_signals ? -1 * info->pid : info->pid;
+ const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid;
delete info;
@@ -302,181 +329,6 @@ Host::SystemLog (SystemLogType type, const char *format, ...)
va_end (args);
}
-const ArchSpec &
-Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
-{
- static bool g_supports_32 = false;
- static bool g_supports_64 = false;
- static ArchSpec g_host_arch_32;
- static ArchSpec g_host_arch_64;
-
-#if defined (__APPLE__)
-
- // Apple is different in that it can support both 32 and 64 bit executables
- // in the same operating system running concurrently. Here we detect the
- // correct host architectures for both 32 and 64 bit including if 64 bit
- // executables are supported on the system.
-
- if (g_supports_32 == false && g_supports_64 == false)
- {
- // All apple systems support 32 bit execution.
- g_supports_32 = true;
- uint32_t cputype, cpusubtype;
- uint32_t is_64_bit_capable = false;
- size_t len = sizeof(cputype);
- ArchSpec host_arch;
- // These will tell us about the kernel architecture, which even on a 64
- // bit machine can be 32 bit...
- if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
- {
- len = sizeof (cpusubtype);
- if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
- cpusubtype = CPU_TYPE_ANY;
-
- len = sizeof (is_64_bit_capable);
- if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
- {
- if (is_64_bit_capable)
- g_supports_64 = true;
- }
-
- if (is_64_bit_capable)
- {
-#if defined (__i386__) || defined (__x86_64__)
- if (cpusubtype == CPU_SUBTYPE_486)
- cpusubtype = CPU_SUBTYPE_I386_ALL;
-#endif
- if (cputype & CPU_ARCH_ABI64)
- {
- // We have a 64 bit kernel on a 64 bit system
- g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype);
- g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- }
- else
- {
- // We have a 32 bit kernel on a 64 bit system
- g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- cputype |= CPU_ARCH_ABI64;
- g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- }
- }
- else
- {
- g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- g_host_arch_64.Clear();
- }
- }
- }
-
-#else // #if defined (__APPLE__)
-
- if (g_supports_32 == false && g_supports_64 == false)
- {
- llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
-
- g_host_arch_32.Clear();
- g_host_arch_64.Clear();
-
- // If the OS is Linux, "unknown" in the vendor slot isn't what we want
- // for the default triple. It's probably an artifact of config.guess.
- if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor)
- triple.setVendorName ("");
-
- const char* distribution_id = GetDistributionId ().AsCString();
-
- switch (triple.getArch())
- {
- default:
- g_host_arch_32.SetTriple(triple);
- g_host_arch_32.SetDistributionId (distribution_id);
- g_supports_32 = true;
- break;
-
- case llvm::Triple::x86_64:
- g_host_arch_64.SetTriple(triple);
- g_host_arch_64.SetDistributionId (distribution_id);
- g_supports_64 = true;
- g_host_arch_32.SetTriple(triple.get32BitArchVariant());
- g_host_arch_32.SetDistributionId (distribution_id);
- g_supports_32 = true;
- break;
-
- case llvm::Triple::sparcv9:
- case llvm::Triple::ppc64:
- g_host_arch_64.SetTriple(triple);
- g_host_arch_64.SetDistributionId (distribution_id);
- g_supports_64 = true;
- break;
- }
-
- g_supports_32 = g_host_arch_32.IsValid();
- g_supports_64 = g_host_arch_64.IsValid();
- }
-
-#endif // #else for #if defined (__APPLE__)
-
- if (arch_kind == eSystemDefaultArchitecture32)
- return g_host_arch_32;
- else if (arch_kind == eSystemDefaultArchitecture64)
- return g_host_arch_64;
-
- if (g_supports_64)
- return g_host_arch_64;
-
- return g_host_arch_32;
-}
-
-const ConstString &
-Host::GetVendorString()
-{
- static ConstString g_vendor;
- if (!g_vendor)
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
- g_vendor.SetCStringWithLength(str_ref.data(), str_ref.size());
- }
- return g_vendor;
-}
-
-const ConstString &
-Host::GetOSString()
-{
- static ConstString g_os_string;
- if (!g_os_string)
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
- g_os_string.SetCStringWithLength(str_ref.data(), str_ref.size());
- }
- return g_os_string;
-}
-
-const ConstString &
-Host::GetTargetTriple()
-{
- static ConstString g_host_triple;
- if (!(g_host_triple))
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- g_host_triple.SetCString(host_arch.GetTriple().getTriple().c_str());
- }
- return g_host_triple;
-}
-
-// See linux/Host.cpp for Linux-based implementations of this.
-// Add your platform-specific implementation to the appropriate host file.
-#if !defined(__linux__)
-
-const ConstString &
- Host::GetDistributionId ()
-{
- static ConstString s_distribution_id;
- return s_distribution_id;
-}
-
-#endif // #if !defined(__linux__)
-
lldb::pid_t
Host::GetCurrentProcessID()
{
@@ -806,51 +658,6 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,
#endif
-FileSpec
-Host::GetProgramFileSpec ()
-{
- static FileSpec g_program_filespec;
- if (!g_program_filespec)
- {
-#if defined (__APPLE__)
- char program_fullpath[PATH_MAX];
- // If DST is NULL, then return the number of bytes needed.
- uint32_t len = sizeof(program_fullpath);
- int err = _NSGetExecutablePath (program_fullpath, &len);
- if (err == 0)
- g_program_filespec.SetFile (program_fullpath, false);
- else if (err == -1)
- {
- char *large_program_fullpath = (char *)::malloc (len + 1);
-
- err = _NSGetExecutablePath (large_program_fullpath, &len);
- if (err == 0)
- g_program_filespec.SetFile (large_program_fullpath, false);
-
- ::free (large_program_fullpath);
- }
-#elif defined (__linux__)
- char exe_path[PATH_MAX];
- ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
- if (len > 0) {
- exe_path[len] = 0;
- g_program_filespec.SetFile(exe_path, false);
- }
-#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
- int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
- size_t exe_path_size;
- if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
- {
- char *exe_path = new char[exe_path_size];
- if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec.SetFile(exe_path, false);
- delete[] exe_path;
- }
-#endif
- }
- return g_program_filespec;
-}
-
#if !defined (__APPLE__) // see Host.mm
bool
@@ -869,130 +676,6 @@ Host::ResolveExecutableInBundle (FileSpec &file)
#ifndef _WIN32
-// Opaque info that tracks a dynamic library that was loaded
-struct DynamicLibraryInfo
-{
- DynamicLibraryInfo (const FileSpec &fs, int o, void *h) :
- file_spec (fs),
- open_options (o),
- handle (h)
- {
- }
-
- const FileSpec file_spec;
- uint32_t open_options;
- void * handle;
-};
-
-void *
-Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error)
-{
- char path[PATH_MAX];
- if (file_spec.GetPath(path, sizeof(path)))
- {
- int mode = 0;
-
- if (options & eDynamicLibraryOpenOptionLazy)
- mode |= RTLD_LAZY;
- else
- mode |= RTLD_NOW;
-
-
- if (options & eDynamicLibraryOpenOptionLocal)
- mode |= RTLD_LOCAL;
- else
- mode |= RTLD_GLOBAL;
-
-#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
- if (options & eDynamicLibraryOpenOptionLimitGetSymbol)
- mode |= RTLD_FIRST;
-#endif
-
- void * opaque = ::dlopen (path, mode);
-
- if (opaque)
- {
- error.Clear();
- return new DynamicLibraryInfo (file_spec, options, opaque);
- }
- else
- {
- error.SetErrorString(::dlerror());
- }
- }
- else
- {
- error.SetErrorString("failed to extract path");
- }
- return NULL;
-}
-
-Error
-Host::DynamicLibraryClose (void *opaque)
-{
- Error error;
- if (opaque == NULL)
- {
- error.SetErrorString ("invalid dynamic library handle");
- }
- else
- {
- DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
- if (::dlclose (dylib_info->handle) != 0)
- {
- error.SetErrorString(::dlerror());
- }
-
- dylib_info->open_options = 0;
- dylib_info->handle = 0;
- delete dylib_info;
- }
- return error;
-}
-
-void *
-Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error)
-{
- if (opaque == NULL)
- {
- error.SetErrorString ("invalid dynamic library handle");
- }
- else
- {
- DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
-
- void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name);
- if (symbol_addr)
- {
-#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
- // This host doesn't support limiting searches to this shared library
- // so we need to verify that the match came from this shared library
- // if it was requested in the Host::DynamicLibraryOpen() function.
- if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol)
- {
- FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr));
- if (match_dylib_spec != dylib_info->file_spec)
- {
- char dylib_path[PATH_MAX];
- if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path)))
- error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path);
- else
- error.SetErrorString ("symbol not found");
- return NULL;
- }
- }
-#endif
- error.Clear();
- return symbol_addr;
- }
- else
- {
- error.SetErrorString(::dlerror());
- }
- }
- return NULL;
-}
-
FileSpec
Host::GetModuleFileSpecForHostAddress (const void *host_addr)
{
@@ -1008,427 +691,6 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
#endif
-bool
-Host::GetLLDBPath (PathType path_type, 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".
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST);
-
- switch (path_type)
- {
- case ePathTypeLLDBShlibDir:
- {
- static ConstString g_lldb_so_dir;
- if (!g_lldb_so_dir)
- {
- FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
- g_lldb_so_dir = lldb_file_spec.GetDirectory();
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_lldb_so_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_so_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
- case ePathTypeSupportExecutableDir:
- {
- static ConstString g_lldb_support_exe_dir;
- if (!g_lldb_support_exe_dir)
- {
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
-#if defined (__APPLE__)
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
-#if defined (__arm__)
- // Shallow bundle
- *framework_pos = '\0';
-#else
- // Normal bundle
- ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
-#endif
- }
-#endif
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_support_exe_dir.SetCString(resolved_path);
- }
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_lldb_support_exe_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_support_exe_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
- case ePathTypeHeaderDir:
- {
- static ConstString g_lldb_headers_dir;
- if (!g_lldb_headers_dir)
- {
-#if defined (__APPLE__)
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
- }
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_headers_dir.SetCString(resolved_path);
- }
-#else
- // TODO: Anyone know how we can determine this for linux? Other systems??
- g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
-#endif
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_lldb_headers_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_headers_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
-#ifdef LLDB_DISABLE_PYTHON
- case ePathTypePythonDir:
- return false;
-#else
- case ePathTypePythonDir:
- {
- static ConstString g_lldb_python_dir;
- if (!g_lldb_python_dir)
- {
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
-#if defined (__APPLE__)
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
- }
- else
- {
-#endif
- llvm::SmallString<256> python_version_dir;
- llvm::raw_svector_ostream os(python_version_dir);
- os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
- os.flush();
-
- // We may get our string truncated. Should we protect
- // this with an assert?
-
- ::strncat(raw_path, python_version_dir.c_str(),
- sizeof(raw_path) - strlen(raw_path) - 1);
-
-#if defined (__APPLE__)
- }
-#endif
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_python_dir.SetCString(resolved_path);
- }
-
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypePythonDir) => '%s'", g_lldb_python_dir.GetCString());
-
- }
- file_spec.GetDirectory() = g_lldb_python_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-#endif
-
- case ePathTypeLLDBSystemPlugins: // System plug-ins directory
- {
-#if defined (__APPLE__) || defined(__linux__)
- static ConstString g_lldb_system_plugin_dir;
- static bool g_lldb_system_plugin_dir_located = false;
- if (!g_lldb_system_plugin_dir_located)
- {
- g_lldb_system_plugin_dir_located = true;
-#if defined (__APPLE__)
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path));
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_system_plugin_dir.SetCString(resolved_path);
- }
- return false;
- }
-#elif defined (__linux__)
- FileSpec lldb_file_spec("/usr/lib/lldb", true);
- if (lldb_file_spec.Exists())
- {
- g_lldb_system_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
- }
-#endif // __APPLE__ || __linux__
-
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_lldb_system_plugin_dir.GetCString());
-
- }
-
- if (g_lldb_system_plugin_dir)
- {
- file_spec.GetDirectory() = g_lldb_system_plugin_dir;
- return true;
- }
-#else
- // TODO: where would system LLDB plug-ins be located on other systems?
- return false;
-#endif
- }
- break;
-
- case ePathTypeLLDBUserPlugins: // User plug-ins directory
- {
-#if defined (__APPLE__)
- static ConstString g_lldb_user_plugin_dir;
- if (!g_lldb_user_plugin_dir)
- {
- char user_plugin_path[PATH_MAX];
- if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns",
- user_plugin_path,
- sizeof(user_plugin_path)))
- {
- g_lldb_user_plugin_dir.SetCString(user_plugin_path);
- }
- }
- file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return (bool)file_spec.GetDirectory();
-#elif defined (__linux__)
- static ConstString g_lldb_user_plugin_dir;
- if (!g_lldb_user_plugin_dir)
- {
- // XDG Base Directory Specification
- // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
- // If XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb.
- FileSpec lldb_file_spec;
- const char *xdg_data_home = getenv("XDG_DATA_HOME");
- if (xdg_data_home && xdg_data_home[0])
- {
- std::string user_plugin_dir (xdg_data_home);
- user_plugin_dir += "/lldb";
- lldb_file_spec.SetFile (user_plugin_dir.c_str(), true);
- }
- else
- {
- const char *home_dir = getenv("HOME");
- if (home_dir && home_dir[0])
- {
- std::string user_plugin_dir (home_dir);
- user_plugin_dir += "/.local/share/lldb";
- lldb_file_spec.SetFile (user_plugin_dir.c_str(), true);
- }
- }
-
- if (lldb_file_spec.Exists())
- g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_lldb_user_plugin_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return (bool)file_spec.GetDirectory();
-#endif
- // TODO: where would user LLDB plug-ins be located on other systems?
- return false;
- }
-
- case ePathTypeLLDBTempSystemDir:
- {
- static ConstString g_lldb_tmp_dir;
- if (!g_lldb_tmp_dir)
- {
- 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)
- {
- g_lldb_tmp_dir.SetCString(tmpdir_cstr);
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_lldb_tmp_dir.GetCString());
- }
- }
- file_spec.GetDirectory() = g_lldb_tmp_dir;
- return (bool)file_spec.GetDirectory();
- }
- }
-
- return false;
-}
-
-
-bool
-Host::GetHostname (std::string &s)
-{
- char hostname[PATH_MAX];
- hostname[sizeof(hostname) - 1] = '\0';
- if (::gethostname (hostname, sizeof(hostname) - 1) == 0)
- {
- struct hostent* h = ::gethostbyname (hostname);
- if (h)
- s.assign (h->h_name);
- else
- s.assign (hostname);
- return true;
- }
- return false;
-}
-
-#ifndef _WIN32
-
-const char *
-Host::GetUserName (uint32_t uid, std::string &user_name)
-{
- struct passwd user_info;
- struct passwd *user_info_ptr = &user_info;
- char user_buffer[PATH_MAX];
- size_t user_buffer_size = sizeof(user_buffer);
- if (::getpwuid_r (uid,
- &user_info,
- user_buffer,
- user_buffer_size,
- &user_info_ptr) == 0)
- {
- if (user_info_ptr)
- {
- user_name.assign (user_info_ptr->pw_name);
- return user_name.c_str();
- }
- }
- user_name.clear();
- return NULL;
-}
-
-const char *
-Host::GetGroupName (uint32_t gid, std::string &group_name)
-{
- char group_buffer[PATH_MAX];
- size_t group_buffer_size = sizeof(group_buffer);
- struct group group_info;
- struct group *group_info_ptr = &group_info;
- // Try the threadsafe version first
- if (::getgrgid_r (gid,
- &group_info,
- group_buffer,
- group_buffer_size,
- &group_info_ptr) == 0)
- {
- if (group_info_ptr)
- {
- group_name.assign (group_info_ptr->gr_name);
- return group_name.c_str();
- }
- }
- else
- {
- // The threadsafe version isn't currently working
- // for me on darwin, but the non-threadsafe version
- // is, so I am calling it below.
- group_info_ptr = ::getgrgid (gid);
- if (group_info_ptr)
- {
- group_name.assign (group_info_ptr->gr_name);
- return group_name.c_str();
- }
- }
- group_name.clear();
- return NULL;
-}
-
-uint32_t
-Host::GetUserID ()
-{
- return getuid();
-}
-
-uint32_t
-Host::GetGroupID ()
-{
- return getgid();
-}
-
-uint32_t
-Host::GetEffectiveUserID ()
-{
- return geteuid();
-}
-
-uint32_t
-Host::GetEffectiveGroupID ()
-{
- return getegid();
-}
-
-#endif
-
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) // see macosx/Host.mm
-bool
-Host::GetOSBuildString (std::string &s)
-{
- s.clear();
- return false;
-}
-
-bool
-Host::GetOSKernelDescription (std::string &s)
-{
- s.clear();
- return false;
-}
-#endif
-
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__)
-uint32_t
-Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
-{
- process_infos.Clear();
- return process_infos.GetSize();
-}
-
-bool
-Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
- process_info.Clear();
- return false;
-}
-#endif
-
#if !defined(__linux__)
bool
Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
@@ -1447,7 +709,7 @@ Host::GetDummyTarget (lldb_private::Debugger &debugger)
{
ArchSpec arch(Target::GetDefaultArchitecture());
if (!arch.IsValid())
- arch = Host::GetArchitecture ();
+ arch = HostInfo::GetArchitecture();
Error err = debugger.GetTargetList().CreateTarget(debugger,
NULL,
arch.GetTriple().getTriple().c_str(),
@@ -1545,9 +807,9 @@ Host::RunShellCommand (const char *command,
// output of the command into this file. We will later read this file
// if all goes well and fill the data into "command_output_ptr"
FileSpec tmpdir_file_spec;
- if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
- tmpdir_file_spec.GetFilename().SetCString("lldb-shell-output.XXXXXX");
+ tmpdir_file_spec.AppendPathComponent("lldb-shell-output.XXXXXX");
strncpy(output_file_path_buffer, tmpdir_file_spec.GetPath().c_str(), sizeof(output_file_path_buffer));
}
else
@@ -1601,7 +863,7 @@ Host::RunShellCommand (const char *command,
{
error.SetErrorString("timed out waiting for shell command to complete");
- // Kill the process since it didn't complete withint the timeout specified
+ // Kill the process since it didn't complete within the timeout specified
Kill (pid, SIGKILL);
// Wait for the monitor callback to get the message
timeout_time = TimeValue::Now();
@@ -1651,7 +913,7 @@ Host::RunShellCommand (const char *command,
// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC
// systems
-#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__)
+#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
// this method needs to be visible to macosx/Host.cpp and
// common/Host.cpp.
@@ -1682,7 +944,7 @@ Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info)
g_use_close_on_exec_flag = eLazyBoolNo;
uint32_t major, minor, update;
- if (Host::GetOSVersion(major, minor, update))
+ if (HostInfo::GetOSVersion(major, minor, update))
{
// Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier
if (major > 10 || (major == 10 && minor > 7))
@@ -1757,8 +1019,8 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
cpu_type_t cpu = arch_spec.GetMachOCPUType();
cpu_type_t sub = arch_spec.GetMachOCPUSubType();
if (cpu != 0 &&
- cpu != UINT32_MAX &&
- cpu != LLDB_INVALID_CPUTYPE &&
+ cpu != static_cast<cpu_type_t>(UINT32_MAX) &&
+ cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) &&
!(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail
{
size_t ocount = 0;
@@ -1840,13 +1102,10 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
for (size_t i=0; i<num_file_actions; ++i)
{
- const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+ const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
if (launch_file_action)
{
- if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
- launch_file_action,
- log,
- error))
+ if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error))
return error;
}
}
@@ -1862,12 +1121,10 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
if (error.Fail() || log)
{
error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
- pid,
- exe_path,
- &file_actions,
- &attr,
- argv,
- envp);
+ pid, exe_path, static_cast<void*>(&file_actions),
+ static_cast<void*>(&attr),
+ reinterpret_cast<const void*>(argv),
+ reinterpret_cast<const void*>(envp));
if (log)
{
for (int ii=0; argv[ii]; ++ii)
@@ -1889,11 +1146,9 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
if (error.Fail() || log)
{
error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
- pid,
- exe_path,
- &attr,
- argv,
- envp);
+ pid, exe_path, static_cast<void*>(&attr),
+ reinterpret_cast<const void*>(argv),
+ reinterpret_cast<const void*>(envp));
if (log)
{
for (int ii=0; argv[ii]; ++ii)
@@ -1920,12 +1175,79 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
return error;
}
+bool
+Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error)
+{
+ if (info == NULL)
+ return false;
+
+ posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);
+
+ switch (info->GetAction())
+ {
+ case FileAction::eFileActionNone:
+ error.Clear();
+ break;
+
+ case FileAction::eFileActionClose:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)");
+ else
+ {
+ error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)",
+ static_cast<void *>(file_actions), info->GetFD());
+ }
+ break;
+
+ case FileAction::eFileActionDuplicate:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)");
+ else if (info->GetActionArgument() == -1)
+ error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
+ else
+ {
+ error.SetError(
+ ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()),
+ eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)",
+ static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument());
+ }
+ break;
+
+ case FileAction::eFileActionOpen:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)");
+ else
+ {
+ int oflag = info->GetActionArgument();
+
+ mode_t mode = 0;
+
+ if (oflag & O_CREAT)
+ mode = 0640;
+
+ error.SetError(
+ ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode),
+ eErrorTypePOSIX);
+ if (error.Fail() || log)
+ error.PutToLog(log,
+ "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)",
+ static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode);
+ }
+ break;
+ }
+ return error.Success();
+}
+
#endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
-// The functions below implement process launching via posix_spawn() for Linux
-// and FreeBSD.
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__)
+// The functions below implement process launching via posix_spawn() for Linux,
+// FreeBSD and NetBSD.
Error
Host::LaunchProcess (ProcessLaunchInfo &launch_info)
@@ -2005,58 +1327,10 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
return error;
}
-#endif // defined(__linux__) or defined(__FreeBSD__)
+#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#ifndef _WIN32
-size_t
-Host::GetPageSize()
-{
- return ::getpagesize();
-}
-
-uint32_t
-Host::GetNumberCPUS ()
-{
- static uint32_t g_num_cores = UINT32_MAX;
- if (g_num_cores == UINT32_MAX)
- {
-#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) or defined (__FreeBSD_kernel__)
-
- g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN);
-
-#else
-
- // Assume POSIX support if a host specific case has not been supplied above
- g_num_cores = 0;
- int num_cores = 0;
- size_t num_cores_len = sizeof(num_cores);
-#ifdef HW_AVAILCPU
- int mib[] = { CTL_HW, HW_AVAILCPU };
-#else
- int mib[] = { CTL_HW, HW_NCPU };
-#endif
-
- /* get the number of CPUs from the system */
- if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
- {
- g_num_cores = num_cores;
- }
- else
- {
- mib[1] = HW_NCPU;
- num_cores_len = sizeof(num_cores);
- if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
- {
- if (num_cores > 0)
- g_num_cores = num_cores;
- }
- }
-#endif
- }
- return g_num_cores;
-}
-
void
Host::Kill(lldb::pid_t pid, int signo)
{
@@ -2090,319 +1364,13 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
#endif
+#if !defined (__linux__) && !defined (__FreeBSD__) && !defined (__NetBSD__)
-#ifdef LLDB_DISABLE_POSIX
-
-Error
-Host::MakeDirectory (const char* path, uint32_t mode)
-{
- Error error;
- error.SetErrorStringWithFormat("%s in not implemented on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::SetFilePermissions (const char* path, uint32_t file_permissions)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Symlink (const char *src, const char *dst)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Readlink (const char *path, char *buf, size_t buf_len)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Unlink (const char *path)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-#else
-
-Error
-Host::MakeDirectory (const char* path, uint32_t file_permissions)
-{
- Error error;
- if (path && path[0])
- {
- if (::mkdir(path, file_permissions) != 0)
- {
- error.SetErrorToErrno();
- switch (error.GetError())
- {
- case ENOENT:
- {
- // Parent directory doesn't exist, so lets make it if we can
- FileSpec spec(path, false);
- if (spec.GetDirectory() && spec.GetFilename())
- {
- // Make the parent directory and try again
- Error error2 = Host::MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
- if (error2.Success())
- {
- // Try and make the directory again now that the parent directory was made successfully
- if (::mkdir(path, file_permissions) == 0)
- error.Clear();
- else
- error.SetErrorToErrno();
- }
- }
- }
- break;
- case EEXIST:
- {
- FileSpec path_spec(path, false);
- if (path_spec.IsDirectory())
- error.Clear(); // It is a directory and it already exists
- }
- break;
- }
- }
- }
- else
- {
- error.SetErrorString("empty path");
- }
- return error;
-}
-
-Error
-Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
-{
- Error error;
- struct stat file_stats;
- if (::stat (path, &file_stats) == 0)
- {
- // The bits in "st_mode" currently match the definitions
- // for the file mode bits in unix.
- file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- }
- else
- {
- error.SetErrorToErrno();
- }
- return error;
-}
-
-Error
-Host::SetFilePermissions (const char* path, uint32_t file_permissions)
-{
- Error error;
- if (::chmod(path, file_permissions) != 0)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Symlink (const char *src, const char *dst)
-{
- Error error;
- if (::symlink(dst, src) == -1)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Unlink (const char *path)
-{
- Error error;
- if (::unlink(path) == -1)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Readlink (const char *path, char *buf, size_t buf_len)
-{
- Error error;
- ssize_t count = ::readlink(path, buf, buf_len);
- if (count < 0)
- error.SetErrorToErrno();
- else if (count < (buf_len-1))
- buf[count] = '\0'; // Success
- else
- error.SetErrorString("'buf' buffer is too small to contain link contents");
- return error;
-}
-
-
-#endif
-
-typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
-FDToFileMap& GetFDToFileMap()
-{
- static FDToFileMap g_fd2filemap;
- return g_fd2filemap;
-}
-
-lldb::user_id_t
-Host::OpenFile (const FileSpec& file_spec,
- uint32_t flags,
- uint32_t mode,
- Error &error)
+const lldb_private::UnixSignalsSP&
+Host::GetUnixSignals ()
{
- std::string path (file_spec.GetPath());
- if (path.empty())
- {
- error.SetErrorString("empty path");
- return UINT64_MAX;
- }
- FileSP file_sp(new File());
- error = file_sp->Open(path.c_str(),flags,mode);
- if (file_sp->IsValid() == false)
- return UINT64_MAX;
- lldb::user_id_t fd = file_sp->GetDescriptor();
- GetFDToFileMap()[fd] = file_sp;
- return fd;
+ static UnixSignalsSP s_unix_signals_sp (new UnixSignals ());
+ return s_unix_signals_sp;
}
-bool
-Host::CloseFile (lldb::user_id_t fd, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return false;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return false;
- }
- error = file_sp->Close();
- file_map.erase(pos);
- return error.Success();
-}
-
-uint64_t
-Host::WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return UINT64_MAX;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64 , fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return UINT64_MAX;
- }
- if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
- return UINT64_MAX;
- size_t bytes_written = src_len;
- error = file_sp->Write(src, bytes_written);
- if (error.Fail())
- return UINT64_MAX;
- return bytes_written;
-}
-
-uint64_t
-Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* dst, uint64_t dst_len, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return UINT64_MAX;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return UINT64_MAX;
- }
- if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
- return UINT64_MAX;
- size_t bytes_read = dst_len;
- error = file_sp->Read(dst ,bytes_read);
- if (error.Fail())
- return UINT64_MAX;
- return bytes_read;
-}
-
-lldb::user_id_t
-Host::GetFileSize (const FileSpec& file_spec)
-{
- return file_spec.GetByteSize();
-}
-
-bool
-Host::GetFileExists (const FileSpec& file_spec)
-{
- return file_spec.Exists();
-}
-
-bool
-Host::CalculateMD5 (const FileSpec& file_spec,
- uint64_t &low,
- uint64_t &high)
-{
-#if defined (__APPLE__)
- StreamString md5_cmd_line;
- md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
- std::string hash_string;
- Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
- if (err.Fail())
- return false;
- // a correctly formed MD5 is 16-bytes, that is 32 hex digits
- // if the output is any other length it is probably wrong
- if (hash_string.size() != 32)
- return false;
- std::string part1(hash_string,0,16);
- std::string part2(hash_string,16);
- const char* part1_cstr = part1.c_str();
- const char* part2_cstr = part2.c_str();
- high = ::strtoull(part1_cstr, NULL, 16);
- low = ::strtoull(part2_cstr, NULL, 16);
- return true;
-#else
- // your own MD5 implementation here
- return false;
#endif
-}