aboutsummaryrefslogtreecommitdiff
path: root/source/Host/common
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/common')
-rw-r--r--source/Host/common/Condition.cpp27
-rw-r--r--source/Host/common/File.cpp126
-rw-r--r--source/Host/common/FileSpec.cpp246
-rw-r--r--source/Host/common/Host.cpp599
-rw-r--r--source/Host/common/Mutex.cpp26
-rw-r--r--source/Host/common/OptionParser.cpp61
-rw-r--r--source/Host/common/ProcessRunLock.cpp71
-rw-r--r--source/Host/common/SocketAddress.cpp3
-rw-r--r--source/Host/common/Terminal.cpp21
-rw-r--r--source/Host/common/TimeValue.cpp36
10 files changed, 1090 insertions, 126 deletions
diff --git a/source/Host/common/Condition.cpp b/source/Host/common/Condition.cpp
index daa729cadca5..7bc6b6554648 100644
--- a/source/Host/common/Condition.cpp
+++ b/source/Host/common/Condition.cpp
@@ -15,6 +15,8 @@
using namespace lldb_private;
+#ifndef _WIN32
+
//----------------------------------------------------------------------
// Default constructor
//
@@ -47,15 +49,6 @@ Condition::Broadcast ()
}
//----------------------------------------------------------------------
-// Get accessor to the pthread condition object
-//----------------------------------------------------------------------
-pthread_cond_t *
-Condition::GetCondition ()
-{
- return &m_condition;
-}
-
-//----------------------------------------------------------------------
// Unblocks one thread waiting for the condition variable
//----------------------------------------------------------------------
int
@@ -64,6 +57,11 @@ Condition::Signal ()
return ::pthread_cond_signal (&m_condition);
}
+/* convert struct timeval to ms(milliseconds) */
+static unsigned long int tv2ms(struct timeval a) {
+ return ((a.tv_sec * 1000) + (a.tv_usec / 1000));
+}
+
//----------------------------------------------------------------------
// The Wait() function atomically blocks the current thread
// waiting on the owned condition variable, and unblocks the mutex
@@ -100,7 +98,16 @@ Condition::Wait (Mutex &mutex, const TimeValue *abstime, bool *timed_out)
*timed_out = false;
}
-
return err;
}
+#endif
+
+//----------------------------------------------------------------------
+// Get accessor to the pthread condition object
+//----------------------------------------------------------------------
+lldb::condition_t *
+Condition::GetCondition()
+{
+ return &m_condition;
+}
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index c0d3c290f4c7..addd43515405 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -16,6 +16,10 @@
#include <stdarg.h>
#include <sys/stat.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#endif
+
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/Config.h"
@@ -79,6 +83,20 @@ File::File(const char *path, uint32_t options, uint32_t permissions) :
Open (path, options, permissions);
}
+File::File (const FileSpec& filespec,
+ uint32_t options,
+ uint32_t permissions) :
+ m_descriptor (kInvalidDescriptor),
+ m_stream (kInvalidStream),
+ m_options (0),
+ m_owned (false)
+{
+ if (filespec)
+ {
+ Open (filespec.GetPath().c_str(), options, permissions);
+ }
+}
+
File::File (const File &rhs) :
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
@@ -167,7 +185,11 @@ File::Duplicate (const File &rhs)
if (rhs.DescriptorIsValid())
{
+#ifdef _WIN32
+ m_descriptor = ::_dup(rhs.GetDescriptor());
+#else
m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
+#endif
if (!DescriptorIsValid())
error.SetErrorToErrno();
else
@@ -217,8 +239,12 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
oflag |= O_RDONLY;
}
+#ifndef _WIN32
if (options & eOpenOptionNonBlocking)
oflag |= O_NONBLOCK;
+#else
+ oflag |= O_BINARY;
+#endif
mode_t mode = 0;
if (oflag & O_CREAT)
@@ -247,6 +273,53 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
return error;
}
+uint32_t
+File::GetPermissions (const char *path, Error &error)
+{
+ if (path && path[0])
+ {
+ struct stat file_stats;
+ if (::stat (path, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ if (path)
+ error.SetErrorString ("invalid path");
+ else
+ error.SetErrorString ("empty path");
+ }
+ return 0;
+}
+
+uint32_t
+File::GetPermissions(Error &error) const
+{
+ int fd = GetDescriptor();
+ if (fd != kInvalidDescriptor)
+ {
+ struct stat file_stats;
+ if (::fstat (fd, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ error.SetErrorString ("invalid file descriptor");
+ }
+ return 0;
+}
+
+
Error
File::Close ()
{
@@ -452,6 +525,11 @@ File::Sync ()
Error error;
if (DescriptorIsValid())
{
+#ifdef _WIN32
+ int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
+ if (err == 0)
+ error.SetErrorToGenericError();
+#else
int err = 0;
do
{
@@ -460,6 +538,7 @@ File::Sync ()
if (err == -1)
error.SetErrorToErrno();
+#endif
}
else
{
@@ -559,6 +638,7 @@ File::Write (const void *buf, size_t &num_bytes)
Error
File::Read (void *buf, size_t &num_bytes, off_t &offset)
{
+#ifndef _WIN32
Error error;
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
@@ -586,6 +666,14 @@ File::Read (void *buf, size_t &num_bytes, off_t &offset)
error.SetErrorString("invalid file handle");
}
return error;
+#else
+ long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
+ SeekFromStart(offset);
+ Error error = Read(buf, num_bytes);
+ if (!error.Fail())
+ SeekFromStart(cur);
+ return error;
+#endif
}
Error
@@ -648,6 +736,7 @@ File::Write (const void *buf, size_t &num_bytes, off_t &offset)
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
{
+#ifndef _WIN32
ssize_t bytes_written = -1;
do
{
@@ -664,6 +753,17 @@ File::Write (const void *buf, size_t &num_bytes, off_t &offset)
offset += bytes_written;
num_bytes = bytes_written;
}
+#else
+ long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
+ error = Write(buf, num_bytes);
+ long after = ::lseek(m_descriptor, 0, SEEK_CUR);
+
+ if (!error.Fail())
+ SeekFromStart(cur);
+
+ ssize_t bytes_written = after - cur;
+ offset = after;
+#endif
}
else
{
@@ -714,3 +814,29 @@ File::PrintfVarArg (const char *format, va_list args)
}
return result;
}
+
+mode_t
+File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
+{
+ mode_t mode = 0;
+ if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
+ mode |= O_RDWR;
+ else if (open_options & eOpenOptionWrite)
+ mode |= O_WRONLY;
+
+ if (open_options & eOpenOptionAppend)
+ mode |= O_APPEND;
+
+ if (open_options & eOpenOptionTruncate)
+ mode |= O_TRUNC;
+
+ if (open_options & eOpenOptionNonBlocking)
+ mode |= O_NONBLOCK;
+
+ if (open_options & eOpenOptionCanCreateNewOnly)
+ mode |= O_CREAT | O_EXCL;
+ else if (open_options & eOpenOptionCanCreate)
+ mode |= O_CREAT;
+
+ return mode;
+}
diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp
index 08d626e836a1..33de198072dc 100644
--- a/source/Host/common/FileSpec.cpp
+++ b/source/Host/common/FileSpec.cpp
@@ -8,9 +8,15 @@
//===----------------------------------------------------------------------===//
+#ifndef _WIN32
#include <dirent.h>
+#else
+#include "lldb/Host/windows/windows.h"
+#endif
#include <fcntl.h>
+#ifndef _MSC_VER
#include <libgen.h>
+#endif
#include <sys/stat.h>
#include <set>
#include <string.h>
@@ -25,6 +31,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/DataBufferHeap.h"
@@ -323,7 +330,11 @@ FileSpec::SetFile (const char *pathname, bool resolve)
// Truncate the basename off the end of the resolved path
// Only attempt to get the dirname if it looks like we have a path
- if (strchr(resolved_path, '/'))
+ if (strchr(resolved_path, '/')
+#ifdef _WIN32
+ || strchr(resolved_path, '\\')
+#endif
+ )
{
char *directory = ::dirname (resolved_path);
@@ -334,6 +345,11 @@ FileSpec::SetFile (const char *pathname, bool resolve)
else
{
char *last_resolved_path_slash = strrchr(resolved_path, '/');
+#ifdef _WIN32
+ char* last_resolved_path_slash_windows = strrchr(resolved_path, '\\');
+ if (last_resolved_path_slash_windows > last_resolved_path_slash)
+ last_resolved_path_slash = last_resolved_path_slash_windows;
+#endif
if (last_resolved_path_slash)
{
*last_resolved_path_slash = '\0';
@@ -616,10 +632,12 @@ FileSpec::GetFileType () const
switch (file_type)
{
case S_IFDIR: return eFileTypeDirectory;
- case S_IFIFO: return eFileTypePipe;
case S_IFREG: return eFileTypeRegular;
+#ifndef _WIN32
+ case S_IFIFO: return eFileTypePipe;
case S_IFSOCK: return eFileTypeSocket;
case S_IFLNK: return eFileTypeSymbolicLink;
+#endif
default:
break;
}
@@ -907,7 +925,94 @@ FileSpec::EnumerateDirectory
{
if (dir_path && dir_path[0])
{
- lldb_utility::CleanUp <DIR *, int> dir_path_dir (opendir(dir_path), NULL, closedir);
+#if _WIN32
+ char szDir[MAX_PATH];
+ strcpy_s(szDir, MAX_PATH, dir_path);
+ strcat_s(szDir, MAX_PATH, "\\*");
+
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = FindFirstFile(szDir, &ffd);
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ return eEnumerateDirectoryResultNext;
+ }
+
+ do
+ {
+ bool call_callback = false;
+ FileSpec::FileType file_type = eFileTypeUnknown;
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ size_t len = strlen(ffd.cFileName);
+
+ if (len == 1 && ffd.cFileName[0] == '.')
+ continue;
+
+ if (len == 2 && ffd.cFileName[0] == '.' && ffd.cFileName[1] == '.')
+ continue;
+
+ file_type = eFileTypeDirectory;
+ call_callback = find_directories;
+ }
+ else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
+ {
+ file_type = eFileTypeOther;
+ call_callback = find_other;
+ }
+ else
+ {
+ file_type = eFileTypeRegular;
+ call_callback = find_files;
+ }
+ if (call_callback)
+ {
+ char child_path[MAX_PATH];
+ const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, ffd.cFileName);
+ if (child_path_len < (int)(sizeof(child_path) - 1))
+ {
+ // Don't resolve the file type or path
+ FileSpec child_path_spec (child_path, false);
+
+ EnumerateDirectoryResult result = callback (callback_baton, file_type, child_path_spec);
+
+ switch (result)
+ {
+ case eEnumerateDirectoryResultNext:
+ // Enumerate next entry in the current directory. We just
+ // exit this switch and will continue enumerating the
+ // current directory as we currently are...
+ break;
+
+ case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not
+ if (FileSpec::EnumerateDirectory(child_path,
+ find_directories,
+ find_files,
+ find_other,
+ callback,
+ callback_baton) == eEnumerateDirectoryResultQuit)
+ {
+ // The subdirectory returned Quit, which means to
+ // stop all directory enumerations at all levels.
+ return eEnumerateDirectoryResultQuit;
+ }
+ break;
+
+ case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level.
+ // Exit from this directory level and tell parent to
+ // keep enumerating.
+ return eEnumerateDirectoryResultNext;
+
+ case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level
+ return eEnumerateDirectoryResultQuit;
+ }
+ }
+ }
+ } while (FindNextFile(hFind, &ffd) != 0);
+
+ FindClose(hFind);
+#else
+ lldb_utility::CleanUp <DIR *, int> dir_path_dir(opendir(dir_path), NULL, closedir);
if (dir_path_dir.is_valid())
{
long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX);
@@ -1006,12 +1111,147 @@ FileSpec::EnumerateDirectory
free (buf);
}
}
+#endif
}
// By default when exiting a directory, we tell the parent enumeration
// to continue enumerating.
return eEnumerateDirectoryResultNext;
}
+FileSpec
+FileSpec::CopyByAppendingPathComponent (const char *new_path) const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec(new_path,resolve);
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ return FileSpec(stream.GetData(),resolve);
+}
+
+FileSpec
+FileSpec::CopyByRemovingLastPathComponent () const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ return FileSpec("",resolve);
+ if (last_slash_ptr == dir_cstr)
+ return FileSpec("/",resolve);
+
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ return FileSpec(new_path.GetCString(),resolve);
+ }
+ else
+ return FileSpec(m_directory.GetCString(),resolve);
+}
+
+const char*
+FileSpec::GetLastPathComponent () const
+{
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return NULL;
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+ if (last_slash_ptr == NULL)
+ return m_directory.GetCString();
+ if (last_slash_ptr == dir_cstr)
+ {
+ if (last_slash_ptr[1] == 0)
+ return last_slash_ptr;
+ else
+ return last_slash_ptr+1;
+ }
+ if (last_slash_ptr[1] != 0)
+ return last_slash_ptr+1;
+ const char* penultimate_slash_ptr = last_slash_ptr;
+ while (*penultimate_slash_ptr)
+ {
+ --penultimate_slash_ptr;
+ if (penultimate_slash_ptr == dir_cstr)
+ break;
+ if (*penultimate_slash_ptr == '/')
+ break;
+ }
+ ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+ return new_path.AsCString();
+ }
+ return m_filename.GetCString();
+}
+
+void
+FileSpec::AppendPathComponent (const char *new_path)
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile(new_path,resolve);
+ return;
+ }
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ SetFile(stream.GetData(), resolve);
+}
+
+void
+FileSpec::RemoveLastPathComponent ()
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (last_slash_ptr == dir_cstr)
+ {
+ SetFile("/",resolve);
+ return;
+ }
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ SetFile(new_path.GetCString(),resolve);
+ }
+ else
+ SetFile(m_directory.GetCString(),resolve);
+}
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index a7bad0063efd..296e4b40bf01 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -10,26 +10,33 @@
#include "lldb/lldb-python.h"
// C includes
-#include <dlfcn.h>
#include <errno.h>
-#include <grp.h>
#include <limits.h>
+#include <sys/types.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#include <winsock2.h>
+#include <WS2tcpip.h>
+#else
+#include <dlfcn.h>
+#include <grp.h>
#include <netdb.h>
#include <pwd.h>
-#include <sys/types.h>
+#endif
+
+#if !defined (__GNU__) && !defined (_WIN32)
+// Does not exist under GNU/HURD or Windows
#include <sys/sysctl.h>
-#include <unistd.h>
+#endif
#if defined (__APPLE__)
-
-#include <dispatch/dispatch.h>
-#include <libproc.h>
-#include <mach-o/dyld.h>
#include <mach/mach_port.h>
-
+#include <mach/mach_init.h>
+#include <mach-o/dyld.h>
#endif
#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
+#include <spawn.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#endif
@@ -44,6 +51,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ThreadSafeSTLMap.h"
#include "lldb/Host/Config.h"
@@ -52,21 +60,18 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Utility/CleanUp.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h"
#include "llvm/Support/raw_ostream.h"
-
-
-
using namespace lldb;
using namespace lldb_private;
-#if !defined (__APPLE__)
+#if !defined (__APPLE__) && !defined (_WIN32)
struct MonitorInfo
{
lldb::pid_t pid; // The process ID to monitor
@@ -75,7 +80,7 @@ struct MonitorInfo
bool monitor_signals; // If true, call the callback when "pid" gets signaled.
};
-static void *
+static thread_result_t
MonitorChildProcessThreadFunction (void *arg);
lldb::thread_t
@@ -89,7 +94,7 @@ Host::StartMonitoringChildProcess
{
lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
MonitorInfo * info_ptr = new MonitorInfo();
-
+
info_ptr->pid = pid;
info_ptr->callback = callback;
info_ptr->callback_baton = callback_baton;
@@ -133,7 +138,7 @@ private:
int m_old_state; // Save the old cancelability state.
};
-static void *
+static thread_result_t
MonitorChildProcessThreadFunction (void *arg)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -145,9 +150,11 @@ MonitorChildProcessThreadFunction (void *arg)
const Host::MonitorChildProcessCallback callback = info->callback;
void * const callback_baton = info->callback_baton;
- const lldb::pid_t pid = info->pid;
const bool monitor_signals = info->monitor_signals;
+ assert (info->pid <= UINT32_MAX);
+ const ::pid_t pid = monitor_signals ? -1 * info->pid : info->pid;
+
delete info;
int status = -1;
@@ -160,12 +167,12 @@ MonitorChildProcessThreadFunction (void *arg)
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf("%s ::wait_pid (pid = %" PRIu64 ", &status, options = %i)...", function, pid, options);
+ log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options);
// Wait for all child processes
::pthread_testcancel ();
// Get signals from all children with same process group of pid
- const lldb::pid_t wait_pid = ::waitpid (-1*pid, &status, options);
+ const ::pid_t wait_pid = ::waitpid (pid, &status, options);
::pthread_testcancel ();
if (wait_pid == -1)
@@ -200,7 +207,7 @@ MonitorChildProcessThreadFunction (void *arg)
{
signal = WTERMSIG(status);
status_cstr = "SIGNALED";
- if (wait_pid == pid) {
+ if (wait_pid == abs(pid)) {
exited = true;
exit_status = -1;
}
@@ -216,7 +223,7 @@ MonitorChildProcessThreadFunction (void *arg)
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf ("%s ::waitpid (pid = %" PRIu64 ", &status, options = %i) => pid = %" PRIu64 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
+ log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
function,
wait_pid,
options,
@@ -233,7 +240,7 @@ MonitorChildProcessThreadFunction (void *arg)
callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status);
// If our process exited, then this thread should exit
- if (exited && wait_pid == pid)
+ if (exited && wait_pid == abs(pid))
{
if (log)
log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg);
@@ -259,6 +266,9 @@ MonitorChildProcessThreadFunction (void *arg)
return NULL;
}
+#endif // #if !defined (__APPLE__) && !defined (_WIN32)
+
+#if !defined (__APPLE__)
void
Host::SystemLog (SystemLogType type, const char *format, va_list args)
@@ -266,7 +276,7 @@ Host::SystemLog (SystemLogType type, const char *format, va_list args)
vfprintf (stderr, format, args);
}
-#endif // #if !defined (__APPLE__)
+#endif
void
Host::SystemLog (SystemLogType type, const char *format, ...)
@@ -277,12 +287,6 @@ Host::SystemLog (SystemLogType type, const char *format, ...)
va_end (args);
}
-size_t
-Host::GetPageSize()
-{
- return ::getpagesize();
-}
-
const ArchSpec &
Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
{
@@ -445,6 +449,8 @@ Host::GetCurrentProcessID()
return ::getpid();
}
+#ifndef _WIN32
+
lldb::tid_t
Host::GetCurrentThreadID()
{
@@ -521,6 +527,8 @@ Host::GetSignalAsCString (int signo)
return NULL;
}
+#endif
+
void
Host::WillTerminate ()
{
@@ -563,6 +571,9 @@ struct HostThreadCreateInfo
};
static thread_result_t
+#ifdef _WIN32
+__stdcall
+#endif
ThreadCreateTrampoline (thread_arg_t arg)
{
HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
@@ -592,7 +603,12 @@ Host::ThreadCreate
// Host::ThreadCreateTrampoline will delete this pointer for us.
HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
+#ifdef _WIN32
+ thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL);
+ int err = thread <= 0 ? GetLastError() : 0;
+#else
int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
+#endif
if (err == 0)
{
if (error)
@@ -606,6 +622,8 @@ Host::ThreadCreate
return LLDB_INVALID_HOST_THREAD;
}
+#ifndef _WIN32
+
bool
Host::ThreadCancel (lldb::thread_t thread, Error *error)
{
@@ -633,6 +651,26 @@ Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Err
return err == 0;
}
+lldb::thread_key_t
+Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
+{
+ pthread_key_t key;
+ ::pthread_key_create (&key, callback);
+ return key;
+}
+
+void*
+Host::ThreadLocalStorageGet(lldb::thread_key_t key)
+{
+ return ::pthread_getspecific (key);
+}
+
+void
+Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
+{
+ ::pthread_setspecific (key, value);
+}
+
bool
Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
{
@@ -723,9 +761,13 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,
}
return Host::SetThreadName (pid, tid, namebuf);
}
+
+ ::free(namebuf);
return false;
}
+#endif
+
FileSpec
Host::GetProgramFileSpec ()
{
@@ -771,19 +813,6 @@ Host::GetProgramFileSpec ()
return g_program_filespec;
}
-FileSpec
-Host::GetModuleFileSpecForHostAddress (const void *host_addr)
-{
- FileSpec module_filespec;
- Dl_info info;
- if (::dladdr (host_addr, &info))
- {
- if (info.dli_fname)
- module_filespec.SetFile(info.dli_fname, true);
- }
- return module_filespec;
-}
-
#if !defined (__APPLE__) // see Host.mm
bool
@@ -800,6 +829,8 @@ Host::ResolveExecutableInBundle (FileSpec &file)
}
#endif
+#ifndef _WIN32
+
// Opaque info that tracks a dynamic library that was loaded
struct DynamicLibraryInfo
{
@@ -924,6 +955,21 @@ Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &err
return NULL;
}
+FileSpec
+Host::GetModuleFileSpecForHostAddress (const void *host_addr)
+{
+ FileSpec module_filespec;
+ Dl_info info;
+ if (::dladdr (host_addr, &info))
+ {
+ if (info.dli_fname)
+ module_filespec.SetFile(info.dli_fname, true);
+ }
+ return module_filespec;
+}
+
+#endif
+
bool
Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
{
@@ -944,7 +990,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
g_lldb_so_dir = lldb_file_spec.GetDirectory();
}
file_spec.GetDirectory() = g_lldb_so_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
@@ -975,7 +1021,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_support_exe_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
@@ -1007,12 +1053,15 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
#endif
}
file_spec.GetDirectory() = g_lldb_headers_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
-#ifndef LLDB_DISABLE_PYTHON
- case ePathTypePythonDir:
+#ifdef LLDB_DISABLE_PYTHON
+ case ePathTypePythonDir:
+ return false;
+#else
+ case ePathTypePythonDir:
{
static ConstString g_lldb_python_dir;
if (!g_lldb_python_dir)
@@ -1049,7 +1098,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_python_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
#endif
@@ -1116,7 +1165,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
#elif defined (__linux__)
static ConstString g_lldb_user_plugin_dir;
if (!g_lldb_user_plugin_dir)
@@ -1147,7 +1196,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
}
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
#endif
// TODO: where would user LLDB plug-ins be located on other systems?
return false;
@@ -1175,6 +1224,8 @@ Host::GetHostname (std::string &s)
return false;
}
+#ifndef _WIN32
+
const char *
Host::GetUserName (uint32_t uid, std::string &user_name)
{
@@ -1234,22 +1285,6 @@ Host::GetGroupName (uint32_t gid, std::string &group_name)
return NULL;
}
-#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
-
uint32_t
Host::GetUserID ()
{
@@ -1274,16 +1309,32 @@ Host::GetEffectiveGroupID ()
return getegid();
}
-#if !defined (__APPLE__) && !defined(__linux__)
+#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();
}
-#endif // #if !defined (__APPLE__) && !defined(__linux__)
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__)
bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
@@ -1386,7 +1437,8 @@ Host::RunShellCommand (const char *command,
launch_info.ConvertArgumentsForLaunchingInShell (error,
localhost,
will_debug,
- first_arg_is_full_shell_command);
+ first_arg_is_full_shell_command,
+ 0);
}
else
{
@@ -1425,23 +1477,31 @@ Host::RunShellCommand (const char *command,
error = LaunchProcess (launch_info);
const lldb::pid_t pid = launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
+
+ if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
+ error.SetErrorString("failed to get process ID");
+
+ if (error.Success())
{
// The process successfully launched, so we can defer ownership of
// "shell_info" to the MonitorShellCommand callback function that will
// get called when the process dies. We release the unique pointer as it
// doesn't need to delete the ShellInfo anymore.
ShellInfo *shell_info = shell_info_ap.release();
+ TimeValue *timeout_ptr = nullptr;
TimeValue timeout_time(TimeValue::Now());
- timeout_time.OffsetWithSeconds(timeout_sec);
+ if (timeout_sec > 0) {
+ timeout_time.OffsetWithSeconds(timeout_sec);
+ timeout_ptr = &timeout_time;
+ }
bool timed_out = false;
- shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out);
+ shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out);
if (timed_out)
{
error.SetErrorString("timed out waiting for shell command to complete");
-
+
// Kill the process since it didn't complete withint the timeout specified
- ::kill (pid, SIGKILL);
+ Kill (pid, SIGKILL);
// Wait for the monitor callback to get the message
timeout_time = TimeValue::Now();
timeout_time.OffsetWithSeconds(1);
@@ -1477,10 +1537,6 @@ Host::RunShellCommand (const char *command,
}
shell_info->can_delete.SetValue(true, eBroadcastAlways);
}
- else
- {
- error.SetErrorString("failed to get process ID");
- }
if (output_file_path)
::unlink (output_file_path);
@@ -1490,6 +1546,212 @@ Host::RunShellCommand (const char *command,
return error;
}
+#if defined(__linux__) or defined(__FreeBSD__)
+// The functions below implement process launching via posix_spawn() for Linux
+// and FreeBSD.
+
+// The posix_spawn() and posix_spawnp() functions first appeared in FreeBSD 8.0,
+static Error
+LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
+{
+ Error error;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+
+ assert(exe_path);
+ assert(!launch_info.GetFlags().Test (eLaunchFlagDebug));
+
+ posix_spawnattr_t attr;
+
+ error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawnattr_init ( &attr )");
+ if (error.Fail())
+ return error;
+
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
+
+ sigset_t no_signals;
+ sigset_t all_signals;
+ sigemptyset (&no_signals);
+ sigfillset (&all_signals);
+ ::posix_spawnattr_setsigmask(&attr, &all_signals);
+ ::posix_spawnattr_setsigdefault(&attr, &no_signals);
+
+ short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
+
+ error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
+ if (error.Fail())
+ return error;
+
+ const size_t num_file_actions = launch_info.GetNumFileActions ();
+ posix_spawn_file_actions_t file_actions, *file_action_ptr = NULL;
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawn_file_actions_t *, int>
+ posix_spawn_file_actions_cleanup (file_action_ptr, NULL, posix_spawn_file_actions_destroy);
+
+ if (num_file_actions > 0)
+ {
+ error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawn_file_actions_init ( &file_actions )");
+ if (error.Fail())
+ return error;
+
+ file_action_ptr = &file_actions;
+ posix_spawn_file_actions_cleanup.set(file_action_ptr);
+
+ for (size_t i = 0; i < num_file_actions; ++i)
+ {
+ const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+ if (launch_file_action &&
+ !ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
+ launch_file_action,
+ log,
+ error))
+ return error;
+ }
+ }
+
+ // Change working directory if neccessary.
+ char current_dir[PATH_MAX];
+ current_dir[0] = '\0';
+
+ const char *working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir != NULL)
+ {
+ if (::getcwd(current_dir, sizeof(current_dir)) == NULL)
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to save the current directory");
+ return error;
+ }
+
+ if (::chdir(working_dir) == -1)
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to change working directory to %s", working_dir);
+ return error;
+ }
+ }
+
+ const char *tmp_argv[2];
+ char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
+ char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+
+ // Prepare minimal argument list if we didn't get it from the launch_info structure.
+ // We must pass argv into posix_spawnp and it must contain at least two items -
+ // pointer to an executable and NULL.
+ if (argv == NULL)
+ {
+ tmp_argv[0] = exe_path;
+ tmp_argv[1] = NULL;
+ argv = (char * const*)tmp_argv;
+ }
+
+ error.SetError (::posix_spawnp (&pid,
+ exe_path,
+ (num_file_actions > 0) ? &file_actions : NULL,
+ &attr,
+ argv,
+ envp),
+ eErrorTypePOSIX);
+
+ error.LogIfError(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
+ pid, exe_path, file_action_ptr, &attr, argv, envp);
+
+ // Change back the current directory.
+ // NOTE: do not override previously established error from posix_spawnp.
+ if (working_dir != NULL && ::chdir(current_dir) == -1 && error.Success())
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to change current directory back to %s",
+ current_dir);
+ }
+
+ return error;
+}
+
+
+Error
+Host::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ char exe_path[PATH_MAX];
+
+ PlatformSP host_platform_sp (Platform::GetDefaultPlatform ());
+
+ const ArchSpec &arch_spec = launch_info.GetArchitecture();
+
+ FileSpec exe_spec(launch_info.GetExecutableFile());
+
+ FileSpec::FileType file_type = exe_spec.GetFileType();
+ if (file_type != FileSpec::eFileTypeRegular)
+ {
+ lldb::ModuleSP exe_module_sp;
+ error = host_platform_sp->ResolveExecutable (exe_spec,
+ arch_spec,
+ exe_module_sp,
+ NULL);
+
+ if (error.Fail())
+ return error;
+
+ if (exe_module_sp)
+ exe_spec = exe_module_sp->GetFileSpec();
+ }
+
+ if (exe_spec.Exists())
+ {
+ exe_spec.GetPath (exe_path, sizeof(exe_path));
+ }
+ else
+ {
+ launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
+ return error;
+ }
+
+ assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY));
+
+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ error = LaunchProcessPosixSpawn(exe_path, launch_info, pid);
+
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ // If all went well, then set the process ID into the launch info
+ launch_info.SetProcessID(pid);
+
+ // Make sure we reap any processes we spawn or we will have zombies.
+ if (!launch_info.MonitorProcess())
+ {
+ const bool monitor_signals = false;
+ StartMonitoringChildProcess (Process::SetProcessExitStatus,
+ NULL,
+ pid,
+ monitor_signals);
+ }
+ }
+ else
+ {
+ // Invalid process ID, something didn't go well
+ if (error.Success())
+ error.SetErrorString ("process launch failed for unknown reasons");
+ }
+ return error;
+}
+
+#endif // defined(__linux__) or defined(__FreeBSD__)
+
+#ifndef _WIN32
+
+size_t
+Host::GetPageSize()
+{
+ return ::getpagesize();
+}
uint32_t
Host::GetNumberCPUS ()
@@ -1500,14 +1762,7 @@ Host::GetNumberCPUS ()
#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) or defined (__FreeBSD_kernel__)
g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN);
-
-#elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-
- // Header file for this might need to be included at the top of this file
- SYSTEM_INFO system_info;
- ::GetSystemInfo (&system_info);
- g_num_cores = system_info.dwNumberOfProcessors;
-
+
#else
// Assume POSIX support if a host specific case has not been supplied above
@@ -1540,7 +1795,13 @@ Host::GetNumberCPUS ()
return g_num_cores;
}
+void
+Host::Kill(lldb::pid_t pid, int signo)
+{
+ ::kill(pid, signo);
+}
+#endif
#if !defined (__APPLE__)
bool
@@ -1560,9 +1821,169 @@ Host::SetCrashDescription (const char *description)
}
lldb::pid_t
-LaunchApplication (const FileSpec &app_file_spec)
+Host::LaunchApplication (const FileSpec &app_file_spec)
{
return LLDB_INVALID_PROCESS_ID;
}
+uint32_t
+Host::MakeDirectory (const char* path, mode_t mode)
+{
+ return UINT32_MAX;
+}
+#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,
+ mode_t mode,
+ Error &error)
+{
+ 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;
+}
+
+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
+}
diff --git a/source/Host/common/Mutex.cpp b/source/Host/common/Mutex.cpp
index 39cd8c6adb4e..4e0135535628 100644
--- a/source/Host/common/Mutex.cpp
+++ b/source/Host/common/Mutex.cpp
@@ -10,9 +10,11 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Host.h"
+#ifndef _WIN32
+#include <pthread.h>
+#endif
#include <string.h>
#include <stdio.h>
-#include <unistd.h>
#if 0
// This logging is way too verbose to enable even for a log channel.
@@ -177,6 +179,8 @@ Mutex::Locker::TryLock (Mutex &mutex, const char *failure_message)
return m_mutex_ptr != NULL;
}
+#ifndef _WIN32
+
//----------------------------------------------------------------------
// Default constructor.
//
@@ -253,15 +257,6 @@ Mutex::~Mutex()
}
//----------------------------------------------------------------------
-// Mutex get accessor.
-//----------------------------------------------------------------------
-pthread_mutex_t *
-Mutex::GetMutex()
-{
- return &m_mutex;
-}
-
-//----------------------------------------------------------------------
// Locks the mutex owned by this object, if the mutex is already
// locked, the calling thread will block until the mutex becomes
// available.
@@ -341,6 +336,17 @@ Mutex::Unlock()
return err;
}
+#endif
+
+//----------------------------------------------------------------------
+// Mutex get accessor.
+//----------------------------------------------------------------------
+lldb::mutex_t *
+Mutex::GetMutex()
+{
+ return &m_mutex;
+}
+
#ifdef LLDB_CONFIGURATION_DEBUG
int
TrackingMutex::Unlock ()
diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp
new file mode 100644
index 000000000000..287292ee74af
--- /dev/null
+++ b/source/Host/common/OptionParser.cpp
@@ -0,0 +1,61 @@
+//===-- source/Host/common/OptionParser.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/OptionParser.h"
+
+#ifdef _MSC_VER
+#include "../windows/msvc/getopt.inc"
+#else
+#ifdef _WIN32
+#define _BSD_SOURCE // Required so that getopt.h defines optreset
+#endif
+#include <getopt.h>
+#endif
+
+using namespace lldb_private;
+
+void
+OptionParser::Prepare()
+{
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+}
+
+void
+OptionParser::EnableError(bool error)
+{
+ opterr = error ? 1 : 0;
+}
+
+int
+OptionParser::Parse(int argc, char * const argv [],
+ const char *optstring,
+ const Option *longopts, int *longindex)
+{
+ return getopt_long_only(argc, argv, optstring, (const option*)longopts, longindex);
+}
+
+char* OptionParser::GetOptionArgument()
+{
+ return optarg;
+}
+
+int OptionParser::GetOptionIndex()
+{
+ return optind;
+}
+
+int OptionParser::GetOptionErrorCause()
+{
+ return optopt;
+}
diff --git a/source/Host/common/ProcessRunLock.cpp b/source/Host/common/ProcessRunLock.cpp
new file mode 100644
index 000000000000..669a96ddd70c
--- /dev/null
+++ b/source/Host/common/ProcessRunLock.cpp
@@ -0,0 +1,71 @@
+#ifndef _WIN32
+
+#include "lldb/Host/ProcessRunLock.h"
+
+namespace lldb_private {
+
+ ProcessRunLock::ProcessRunLock()
+ : m_running(false)
+ {
+ int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void) err;
+ //#if LLDB_CONFIGURATION_DEBUG
+ // assert(err == 0);
+ //#endif
+ }
+
+ ProcessRunLock::~ProcessRunLock()
+ {
+ int err = ::pthread_rwlock_destroy(&m_rwlock); (void) err;
+ //#if LLDB_CONFIGURATION_DEBUG
+ // assert(err == 0);
+ //#endif
+ }
+
+ bool ProcessRunLock::ReadTryLock()
+ {
+ ::pthread_rwlock_rdlock(&m_rwlock);
+ if (m_running == false)
+ {
+ return true;
+ }
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return false;
+ }
+
+ bool ProcessRunLock::ReadUnlock()
+ {
+ return ::pthread_rwlock_unlock(&m_rwlock) == 0;
+ }
+
+ bool ProcessRunLock::SetRunning()
+ {
+ ::pthread_rwlock_wrlock(&m_rwlock);
+ m_running = true;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return true;
+ }
+
+ bool ProcessRunLock::TrySetRunning()
+ {
+ bool r;
+
+ if (::pthread_rwlock_trywrlock(&m_rwlock) == 0)
+ {
+ r = !m_running;
+ m_running = true;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return r;
+ }
+ return false;
+ }
+
+ bool ProcessRunLock::SetStopped()
+ {
+ ::pthread_rwlock_wrlock(&m_rwlock);
+ m_running = false;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return true;
+ }
+}
+
+#endif
diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp
index a22dc7a01c15..1fa7531af9dc 100644
--- a/source/Host/common/SocketAddress.cpp
+++ b/source/Host/common/SocketAddress.cpp
@@ -11,6 +11,9 @@
#include <stddef.h>
// C Includes
+#if !defined(_MSC_VER)
+#include <arpa/inet.h>
+#endif
#include <assert.h>
#include <string.h>
diff --git a/source/Host/common/Terminal.cpp b/source/Host/common/Terminal.cpp
index 89d21cf0bf6c..f63c468bb92c 100644
--- a/source/Host/common/Terminal.cpp
+++ b/source/Host/common/Terminal.cpp
@@ -8,10 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Terminal.h"
-#include "lldb/Host/Config.h"
#include <fcntl.h>
-#include <unistd.h>
#include <signal.h>
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
@@ -24,6 +22,7 @@ using namespace lldb_private;
bool
Terminal::IsATerminal () const
{
+
return m_fd >= 0 && ::isatty (m_fd);
}
@@ -108,7 +107,9 @@ Terminal::SetCanonical (bool enabled)
TerminalState::TerminalState() :
m_tty(),
m_tflags(-1),
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap(),
+#endif
m_process_group(-1)
{
}
@@ -125,7 +126,9 @@ TerminalState::Clear ()
{
m_tty.Clear();
m_tflags = -1;
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap.reset();
+#endif
m_process_group = -1;
}
@@ -140,7 +143,9 @@ TerminalState::Save (int fd, bool save_process_group)
m_tty.SetFileDescriptor(fd);
if (m_tty.IsATerminal())
{
+#ifndef LLDB_DISABLE_POSIX
m_tflags = ::fcntl (fd, F_GETFL, 0);
+#endif
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
if (m_termios_ap.get() == NULL)
m_termios_ap.reset (new struct termios);
@@ -148,16 +153,20 @@ TerminalState::Save (int fd, bool save_process_group)
if (err != 0)
m_termios_ap.reset();
#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#ifndef LLDB_DISABLE_POSIX
if (save_process_group)
m_process_group = ::tcgetpgrp (0);
else
m_process_group = -1;
+#endif
}
else
{
m_tty.Clear();
m_tflags = -1;
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap.reset();
+#endif
m_process_group = -1;
}
return IsValid();
@@ -173,14 +182,17 @@ TerminalState::Restore () const
if (IsValid())
{
const int fd = m_tty.GetFileDescriptor();
+#ifndef LLDB_DISABLE_POSIX
if (TFlagsIsValid())
fcntl (fd, F_SETFL, m_tflags);
+#endif
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
if (TTYStateIsValid())
tcsetattr (fd, TCSANOW, m_termios_ap.get());
#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#ifndef LLDB_DISABLE_POSIX
if (ProcessGroupIsValid())
{
// Save the original signal handler.
@@ -191,6 +203,7 @@ TerminalState::Restore () const
// Restore the original signal handler.
signal (SIGTTOU, saved_sigttou_callback);
}
+#endif
return true;
}
return false;
@@ -224,7 +237,11 @@ TerminalState::TFlagsIsValid() const
bool
TerminalState::TTYStateIsValid() const
{
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
return m_termios_ap.get() != 0;
+#else
+ return false;
+#endif
}
//----------------------------------------------------------------------
diff --git a/source/Host/common/TimeValue.cpp b/source/Host/common/TimeValue.cpp
index 303ac94058b0..b471a3dd1f15 100644
--- a/source/Host/common/TimeValue.cpp
+++ b/source/Host/common/TimeValue.cpp
@@ -8,11 +8,17 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/TimeValue.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <stddef.h>
#include <time.h>
#include <cstring>
+
+#ifdef _MSC_VER
+#include "lldb/Host/windows/windows.h"
+#endif
+
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -42,8 +48,8 @@ TimeValue::TimeValue(const struct timespec& ts) :
{
}
-TimeValue::TimeValue(const struct timeval& tv) :
- m_nano_seconds ((uint64_t) tv.tv_sec * NanoSecPerSec + (uint64_t) tv.tv_usec * NanoSecPerMicroSec)
+TimeValue::TimeValue(uint32_t seconds, uint32_t nanos) :
+ m_nano_seconds((uint64_t) seconds * NanoSecPerSec + nanos)
{
}
@@ -84,15 +90,6 @@ TimeValue::GetAsTimeSpec () const
return ts;
}
-struct timeval
-TimeValue::GetAsTimeVal () const
-{
- struct timeval tv;
- tv.tv_sec = m_nano_seconds / NanoSecPerSec;
- tv.tv_usec = (m_nano_seconds % NanoSecPerSec) / NanoSecPerMicroSec;
- return tv;
-}
-
void
TimeValue::Clear ()
{
@@ -126,9 +123,22 @@ TimeValue::OffsetWithNanoSeconds (uint64_t nsec)
TimeValue
TimeValue::Now()
{
+ uint32_t seconds, nanoseconds;
+#if _MSC_VER
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ nanoseconds = st.wMilliseconds * 1000000;
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+
+ seconds = ((((uint64_t)ft.dwHighDateTime) << 32 | ft.dwLowDateTime) / 10000000) - 11644473600ULL;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
- TimeValue now(tv);
+ seconds = tv.tv_sec;
+ nanoseconds = tv.tv_usec * NanoSecPerMicroSec;
+#endif
+ TimeValue now(seconds, nanoseconds);
return now;
}
@@ -148,6 +158,7 @@ TimeValue::Dump (Stream *s, uint32_t width) const
if (s == NULL)
return;
+#ifndef LLDB_DISABLE_POSIX
char time_buf[32];
time_t time = GetAsSecondsSinceJan1_1970();
char *time_cstr = ::ctime_r(&time, time_buf);
@@ -163,6 +174,7 @@ TimeValue::Dump (Stream *s, uint32_t width) const
}
else if (width > 0)
s->Printf("%-*s", width, "");
+#endif
}
bool