diff options
Diffstat (limited to 'source/Host/common')
-rw-r--r-- | source/Host/common/Condition.cpp | 27 | ||||
-rw-r--r-- | source/Host/common/File.cpp | 126 | ||||
-rw-r--r-- | source/Host/common/FileSpec.cpp | 246 | ||||
-rw-r--r-- | source/Host/common/Host.cpp | 599 | ||||
-rw-r--r-- | source/Host/common/Mutex.cpp | 26 | ||||
-rw-r--r-- | source/Host/common/OptionParser.cpp | 61 | ||||
-rw-r--r-- | source/Host/common/ProcessRunLock.cpp | 71 | ||||
-rw-r--r-- | source/Host/common/SocketAddress.cpp | 3 | ||||
-rw-r--r-- | source/Host/common/Terminal.cpp | 21 | ||||
-rw-r--r-- | source/Host/common/TimeValue.cpp | 36 |
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 |