diff options
Diffstat (limited to 'lldb/source/Host/windows')
-rw-r--r-- | lldb/source/Host/windows/ConnectionGenericFileWindows.cpp | 560 | ||||
-rw-r--r-- | lldb/source/Host/windows/EditLineWin.cpp | 621 | ||||
-rw-r--r-- | lldb/source/Host/windows/FileSystem.cpp | 418 | ||||
-rw-r--r-- | lldb/source/Host/windows/Host.cpp | 503 | ||||
-rw-r--r-- | lldb/source/Host/windows/HostInfoWindows.cpp | 171 | ||||
-rw-r--r-- | lldb/source/Host/windows/HostProcessWindows.cpp | 164 | ||||
-rw-r--r-- | lldb/source/Host/windows/HostThreadWindows.cpp | 103 | ||||
-rw-r--r-- | lldb/source/Host/windows/LockFileWindows.cpp | 91 | ||||
-rw-r--r-- | lldb/source/Host/windows/PipeWindows.cpp | 477 | ||||
-rw-r--r-- | lldb/source/Host/windows/ProcessLauncherWindows.cpp | 235 | ||||
-rw-r--r-- | lldb/source/Host/windows/ProcessRunLock.cpp | 115 | ||||
-rw-r--r-- | lldb/source/Host/windows/ThisThread.cpp | 57 | ||||
-rw-r--r-- | lldb/source/Host/windows/Windows.cpp | 401 |
13 files changed, 1784 insertions, 2132 deletions
diff --git a/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp b/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp index 9743ed48b8e..e89e1746302 100644 --- a/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp +++ b/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/TimeValue.h" -#include "lldb/Host/windows/ConnectionGenericFileWindows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -19,345 +19,319 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -// This is a simple helper class to package up the information needed to return from a Read/Write -// operation function. Since there is a lot of code to be run before exit regardless of whether the -// operation succeeded or failed, combined with many possible return paths, this is the cleanest +namespace { +// This is a simple helper class to package up the information needed to return +// from a Read/Write +// operation function. Since there is a lot of code to be run before exit +// regardless of whether the +// operation succeeded or failed, combined with many possible return paths, this +// is the cleanest // way to represent it. -class ReturnInfo -{ - public: - void - Set(size_t bytes, ConnectionStatus status, DWORD error_code) - { - m_error.SetError(error_code, eErrorTypeWin32); - m_bytes = bytes; - m_status = status; - } - - void - Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) - { - m_error.SetErrorString(error_msg.data()); - m_bytes = bytes; - m_status = status; - } - - size_t - GetBytes() const - { - return m_bytes; - } - ConnectionStatus - GetStatus() const - { - return m_status; - } - const Error & - GetError() const - { - return m_error; - } - - private: - Error m_error; - size_t m_bytes; - ConnectionStatus m_status; +class ReturnInfo { +public: + void Set(size_t bytes, ConnectionStatus status, DWORD error_code) { + m_error.SetError(error_code, eErrorTypeWin32); + m_bytes = bytes; + m_status = status; + } + + void Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) { + m_error.SetErrorString(error_msg.data()); + m_bytes = bytes; + m_status = status; + } + + size_t GetBytes() const { return m_bytes; } + ConnectionStatus GetStatus() const { return m_status; } + const Error &GetError() const { return m_error; } + +private: + Error m_error; + size_t m_bytes; + ConnectionStatus m_status; }; } ConnectionGenericFile::ConnectionGenericFile() - : m_file(INVALID_HANDLE_VALUE) - , m_owns_file(false) -{ - ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - InitializeEventHandles(); + : m_file(INVALID_HANDLE_VALUE), m_owns_file(false) { + ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + InitializeEventHandles(); } ConnectionGenericFile::ConnectionGenericFile(lldb::file_t file, bool owns_file) - : m_file(file) - , m_owns_file(owns_file) -{ - ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - InitializeEventHandles(); + : m_file(file), m_owns_file(owns_file) { + ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + InitializeEventHandles(); } -ConnectionGenericFile::~ConnectionGenericFile() -{ - if (m_owns_file && IsConnected()) - ::CloseHandle(m_file); +ConnectionGenericFile::~ConnectionGenericFile() { + if (m_owns_file && IsConnected()) + ::CloseHandle(m_file); - ::CloseHandle(m_event_handles[kBytesAvailableEvent]); - ::CloseHandle(m_event_handles[kInterruptEvent]); + ::CloseHandle(m_event_handles[kBytesAvailableEvent]); + ::CloseHandle(m_event_handles[kInterruptEvent]); } -void -ConnectionGenericFile::InitializeEventHandles() -{ - m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL); - - // Note, we should use a manual reset event for the hEvent argument of the OVERLAPPED. This - // is because both WaitForMultipleObjects and GetOverlappedResult (if you set the bWait - // argument to TRUE) will wait for the event to be signalled. If we use an auto-reset event, - // WaitForMultipleObjects will reset the event, return successfully, and then - // GetOverlappedResult will block since the event is no longer signalled. - m_event_handles[kBytesAvailableEvent] = ::CreateEvent(NULL, TRUE, FALSE, NULL); +void ConnectionGenericFile::InitializeEventHandles() { + m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL); + + // Note, we should use a manual reset event for the hEvent argument of the + // OVERLAPPED. This + // is because both WaitForMultipleObjects and GetOverlappedResult (if you set + // the bWait + // argument to TRUE) will wait for the event to be signalled. If we use an + // auto-reset event, + // WaitForMultipleObjects will reset the event, return successfully, and then + // GetOverlappedResult will block since the event is no longer signalled. + m_event_handles[kBytesAvailableEvent] = + ::CreateEvent(NULL, TRUE, FALSE, NULL); } -bool -ConnectionGenericFile::IsConnected() const -{ - return m_file && (m_file != INVALID_HANDLE_VALUE); +bool ConnectionGenericFile::IsConnected() const { + return m_file && (m_file != INVALID_HANDLE_VALUE); } -lldb::ConnectionStatus -ConnectionGenericFile::Connect(const char *s, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionGenericFile::Connect (url = '%s')", static_cast<void *>(this), s); - - if (strstr(s, "file://") != s) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); - return eConnectionStatusError; - } +lldb::ConnectionStatus ConnectionGenericFile::Connect(const char *s, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionGenericFile::Connect (url = '%s')", + static_cast<void *>(this), s); - if (IsConnected()) - { - ConnectionStatus status = Disconnect(error_ptr); - if (status != eConnectionStatusSuccess) - return status; - } - - // file://PATH - const char *path = s + strlen("file://"); - // Open the file for overlapped access. If it does not exist, create it. We open it overlapped - // so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read - // to be interrupted by an event object. - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - if (error_ptr) - error_ptr->SetError(1, eErrorTypeGeneric); - return eConnectionStatusError; - } - m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, - FILE_FLAG_OVERLAPPED, NULL); - if (m_file == INVALID_HANDLE_VALUE) - { - if (error_ptr) - error_ptr->SetError(::GetLastError(), eErrorTypeWin32); - return eConnectionStatusError; - } + if (strstr(s, "file://") != s) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", + s); + return eConnectionStatusError; + } + + if (IsConnected()) { + ConnectionStatus status = Disconnect(error_ptr); + if (status != eConnectionStatusSuccess) + return status; + } + + // file://PATH + const char *path = s + strlen("file://"); + // Open the file for overlapped access. If it does not exist, create it. We + // open it overlapped + // so that we can issue asynchronous reads and then use WaitForMultipleObjects + // to allow the read + // to be interrupted by an event object. + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + if (error_ptr) + error_ptr->SetError(1, eErrorTypeGeneric); + return eConnectionStatusError; + } + m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, + FILE_FLAG_OVERLAPPED, NULL); + if (m_file == INVALID_HANDLE_VALUE) { + if (error_ptr) + error_ptr->SetError(::GetLastError(), eErrorTypeWin32); + return eConnectionStatusError; + } - m_owns_file = true; - m_uri.assign(s); - return eConnectionStatusSuccess; + m_owns_file = true; + m_uri.assign(s); + return eConnectionStatusSuccess; } -lldb::ConnectionStatus -ConnectionGenericFile::Disconnect(Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionGenericFile::Disconnect ()", static_cast<void *>(this)); - - if (!IsConnected()) - return eConnectionStatusSuccess; - - // Reset the handle so that after we unblock any pending reads, subsequent calls to Read() will - // see a disconnected state. - HANDLE old_file = m_file; - m_file = INVALID_HANDLE_VALUE; +lldb::ConnectionStatus ConnectionGenericFile::Disconnect(Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionGenericFile::Disconnect ()", + static_cast<void *>(this)); - // Set the disconnect event so that any blocking reads unblock, then cancel any pending IO operations. - ::CancelIoEx(old_file, &m_overlapped); - - // Close the file handle if we owned it, but don't close the event handles. We could always - // reconnect with the same Connection instance. - if (m_owns_file) - ::CloseHandle(old_file); - - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - m_owns_file = false; - m_uri.clear(); + if (!IsConnected()) return eConnectionStatusSuccess; + + // Reset the handle so that after we unblock any pending reads, subsequent + // calls to Read() will + // see a disconnected state. + HANDLE old_file = m_file; + m_file = INVALID_HANDLE_VALUE; + + // Set the disconnect event so that any blocking reads unblock, then cancel + // any pending IO operations. + ::CancelIoEx(old_file, &m_overlapped); + + // Close the file handle if we owned it, but don't close the event handles. + // We could always + // reconnect with the same Connection instance. + if (m_owns_file) + ::CloseHandle(old_file); + + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + m_owns_file = false; + m_uri.clear(); + return eConnectionStatusSuccess; } -size_t -ConnectionGenericFile::Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr) -{ - ReturnInfo return_info; - BOOL result = 0; - DWORD bytes_read = 0; +size_t ConnectionGenericFile::Read(void *dst, size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr) { + ReturnInfo return_info; + BOOL result = 0; + DWORD bytes_read = 0; - if (error_ptr) - error_ptr->Clear(); + if (error_ptr) + error_ptr->Clear(); - if (!IsConnected()) - { - return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + if (!IsConnected()) { + return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + goto finish; + } + + m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent]; + + result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped); + if (result || ::GetLastError() == ERROR_IO_PENDING) { + if (!result) { + // The expected return path. The operation is pending. Wait for the + // operation to complete + // or be interrupted. + TimeValue time_value; + time_value.OffsetWithMicroSeconds(timeout_usec); + DWORD milliseconds = time_value.milliseconds(); + DWORD wait_result = + ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles), + m_event_handles, FALSE, milliseconds); + // All of the events are manual reset events, so make sure we reset them + // to non-signalled. + switch (wait_result) { + case WAIT_OBJECT_0 + kBytesAvailableEvent: + break; + case WAIT_OBJECT_0 + kInterruptEvent: + return_info.Set(0, eConnectionStatusInterrupted, 0); goto finish; - } - - m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent]; - - result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped); - if (result || ::GetLastError() == ERROR_IO_PENDING) - { - if (!result) - { - // The expected return path. The operation is pending. Wait for the operation to complete - // or be interrupted. - TimeValue time_value; - time_value.OffsetWithMicroSeconds(timeout_usec); - DWORD milliseconds = time_value.milliseconds(); - DWORD wait_result = ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles), m_event_handles, FALSE, milliseconds); - // All of the events are manual reset events, so make sure we reset them to non-signalled. - switch (wait_result) - { - case WAIT_OBJECT_0 + kBytesAvailableEvent: - break; - case WAIT_OBJECT_0 + kInterruptEvent: - return_info.Set(0, eConnectionStatusInterrupted, 0); - goto finish; - case WAIT_TIMEOUT: - return_info.Set(0, eConnectionStatusTimedOut, 0); - goto finish; - case WAIT_FAILED: - return_info.Set(0, eConnectionStatusError, ::GetLastError()); - goto finish; - } - } - // The data is ready. Figure out how much was read and return; - if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) - { - DWORD result_error = ::GetLastError(); - // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a blocking read. - // This triggers a call to CancelIoEx, which causes the operation to complete and the - // result to be ERROR_OPERATION_ABORTED. - if (result_error == ERROR_HANDLE_EOF || result_error == ERROR_OPERATION_ABORTED || result_error == ERROR_BROKEN_PIPE) - return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); - else - return_info.Set(bytes_read, eConnectionStatusError, result_error); - } - else if (bytes_read == 0) - return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); - else - return_info.Set(bytes_read, eConnectionStatusSuccess, 0); - + case WAIT_TIMEOUT: + return_info.Set(0, eConnectionStatusTimedOut, 0); goto finish; - } - else if (::GetLastError() == ERROR_BROKEN_PIPE) - { - // The write end of a pipe was closed. This is equivalent to EOF. - return_info.Set(0, eConnectionStatusEndOfFile, 0); - } - else - { - // An unknown error occurred. Fail out. + case WAIT_FAILED: return_info.Set(0, eConnectionStatusError, ::GetLastError()); + goto finish; + } } + // The data is ready. Figure out how much was read and return; + if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) { + DWORD result_error = ::GetLastError(); + // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a + // blocking read. + // This triggers a call to CancelIoEx, which causes the operation to + // complete and the + // result to be ERROR_OPERATION_ABORTED. + if (result_error == ERROR_HANDLE_EOF || + result_error == ERROR_OPERATION_ABORTED || + result_error == ERROR_BROKEN_PIPE) + return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); + else + return_info.Set(bytes_read, eConnectionStatusError, result_error); + } else if (bytes_read == 0) + return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); + else + return_info.Set(bytes_read, eConnectionStatusSuccess, 0); + goto finish; + } else if (::GetLastError() == ERROR_BROKEN_PIPE) { + // The write end of a pipe was closed. This is equivalent to EOF. + return_info.Set(0, eConnectionStatusEndOfFile, 0); + } else { + // An unknown error occurred. Fail out. + return_info.Set(0, eConnectionStatusError, ::GetLastError()); + } + goto finish; finish: - status = return_info.GetStatus(); - if (error_ptr) - *error_ptr = return_info.GetError(); - - // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here so that any - // subsequent operations don't immediately see bytes available. - ResetEvent(m_event_handles[kBytesAvailableEvent]); - - IncrementFilePointer(return_info.GetBytes()); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - { - log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR ", dst = %" PRIxPTR ", dst_len = %" PRIu64 - ") => %" PRIu64 ", error = %s", - this, m_file, dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(return_info.GetBytes()), - return_info.GetError().AsCString()); - } - - return return_info.GetBytes(); + status = return_info.GetStatus(); + if (error_ptr) + *error_ptr = return_info.GetError(); + + // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here + // so that any + // subsequent operations don't immediately see bytes available. + ResetEvent(m_event_handles[kBytesAvailableEvent]); + + IncrementFilePointer(return_info.GetBytes()); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) { + log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR + ", dst = %" PRIxPTR ", dst_len = %" PRIu64 ") => %" PRIu64 + ", error = %s", + this, m_file, dst, static_cast<uint64_t>(dst_len), + static_cast<uint64_t>(return_info.GetBytes()), + return_info.GetError().AsCString()); + } + + return return_info.GetBytes(); } -size_t -ConnectionGenericFile::Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr) -{ - ReturnInfo return_info; - DWORD bytes_written = 0; - BOOL result = 0; - - if (error_ptr) - error_ptr->Clear(); +size_t ConnectionGenericFile::Write(const void *src, size_t src_len, + lldb::ConnectionStatus &status, + Error *error_ptr) { + ReturnInfo return_info; + DWORD bytes_written = 0; + BOOL result = 0; - if (!IsConnected()) - { - return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); - goto finish; - } + if (error_ptr) + error_ptr->Clear(); - m_overlapped.hEvent = NULL; + if (!IsConnected()) { + return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + goto finish; + } - // Writes are not interruptible like reads are, so just block until it's done. - result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped); - if (!result && ::GetLastError() != ERROR_IO_PENDING) - { - return_info.Set(0, eConnectionStatusError, ::GetLastError()); - goto finish; - } + m_overlapped.hEvent = NULL; - if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE)) - { - return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError()); - goto finish; - } + // Writes are not interruptible like reads are, so just block until it's done. + result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped); + if (!result && ::GetLastError() != ERROR_IO_PENDING) { + return_info.Set(0, eConnectionStatusError, ::GetLastError()); + goto finish; + } - return_info.Set(bytes_written, eConnectionStatusSuccess, 0); + if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE)) { + return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError()); goto finish; + } + + return_info.Set(bytes_written, eConnectionStatusSuccess, 0); + goto finish; finish: - status = return_info.GetStatus(); - if (error_ptr) - *error_ptr = return_info.GetError(); - - IncrementFilePointer(return_info.GetBytes()); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - { - log->Printf("%" PRIxPTR " ConnectionGenericFile::Write() handle = %" PRIxPTR ", src = %" PRIxPTR ", src_len = %" PRIu64 - ") => %" PRIu64 ", error = %s", - this, m_file, src, static_cast<uint64_t>(src_len), static_cast<uint64_t>(return_info.GetBytes()), - return_info.GetError().AsCString()); - } - return return_info.GetBytes(); + status = return_info.GetStatus(); + if (error_ptr) + *error_ptr = return_info.GetError(); + + IncrementFilePointer(return_info.GetBytes()); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) { + log->Printf("%" PRIxPTR + " ConnectionGenericFile::Write() handle = %" PRIxPTR + ", src = %" PRIxPTR ", src_len = %" PRIu64 ") => %" PRIu64 + ", error = %s", + this, m_file, src, static_cast<uint64_t>(src_len), + static_cast<uint64_t>(return_info.GetBytes()), + return_info.GetError().AsCString()); + } + return return_info.GetBytes(); } -std::string -ConnectionGenericFile::GetURI() -{ - return m_uri; -} +std::string ConnectionGenericFile::GetURI() { return m_uri; } -bool -ConnectionGenericFile::InterruptRead() -{ - return ::SetEvent(m_event_handles[kInterruptEvent]); +bool ConnectionGenericFile::InterruptRead() { + return ::SetEvent(m_event_handles[kInterruptEvent]); } -void -ConnectionGenericFile::IncrementFilePointer(DWORD amount) -{ - LARGE_INTEGER old_pos; - old_pos.HighPart = m_overlapped.OffsetHigh; - old_pos.LowPart = m_overlapped.Offset; - old_pos.QuadPart += amount; - m_overlapped.Offset = old_pos.LowPart; - m_overlapped.OffsetHigh = old_pos.HighPart; +void ConnectionGenericFile::IncrementFilePointer(DWORD amount) { + LARGE_INTEGER old_pos; + old_pos.HighPart = m_overlapped.OffsetHigh; + old_pos.LowPart = m_overlapped.Offset; + old_pos.QuadPart += amount; + m_overlapped.Offset = old_pos.LowPart; + m_overlapped.OffsetHigh = old_pos.HighPart; } diff --git a/lldb/source/Host/windows/EditLineWin.cpp b/lldb/source/Host/windows/EditLineWin.cpp index 55fe52dc8cc..3e21ff47d56 100644 --- a/lldb/source/Host/windows/EditLineWin.cpp +++ b/lldb/source/Host/windows/EditLineWin.cpp @@ -8,428 +8,345 @@ //===----------------------------------------------------------------------===// // this file is only relevant for Visual C++ -#if defined( _WIN32 ) +#if defined(_WIN32) #include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/editlinewin.h" -#include <vector> #include <assert.h> +#include <vector> // edit line EL_ADDFN function pointer type -typedef unsigned char(*el_addfn_func)(EditLine *e, int ch); -typedef const char* (*el_prompt_func)(EditLine *); +typedef unsigned char (*el_addfn_func)(EditLine *e, int ch); +typedef const char *(*el_prompt_func)(EditLine *); // edit line wrapper binding container -struct el_binding -{ - // - const char *name; - const char *help; - // function pointer to callback routine - el_addfn_func func; - // ascii key this function is bound to - const char *key; +struct el_binding { + // + const char *name; + const char *help; + // function pointer to callback routine + el_addfn_func func; + // ascii key this function is bound to + const char *key; }; // stored key bindings -static std::vector<el_binding*> _bindings; +static std::vector<el_binding *> _bindings; -//TODO: this should in fact be related to the exact edit line context we create +// TODO: this should in fact be related to the exact edit line context we create static void *clientData = NULL; // store the current prompt string // default to what we expect to receive anyway static const char *_prompt = "(lldb) "; -#if !defined( _WIP_INPUT_METHOD ) +#if !defined(_WIP_INPUT_METHOD) -static char * -el_get_s (char *buffer, int chars) -{ - return gets_s(buffer, chars); -} +static char *el_get_s(char *buffer, int chars) { return gets_s(buffer, chars); } #else -static void -con_output (char _in) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get the cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // output this char - WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written ); - // advance cursor position - info.dwCursorPosition.X++; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); +static void con_output(char _in) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get the cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // output this char + WriteConsoleOutputCharacterA(hout, &_in, 1, info.dwCursorPosition, &written); + // advance cursor position + info.dwCursorPosition.X++; + SetConsoleCursorPosition(hout, info.dwCursorPosition); } -static void -con_backspace (void) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // nudge cursor backwards - info.dwCursorPosition.X--; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); - // blank out the last character - WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written ); +static void con_backspace(void) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // nudge cursor backwards + info.dwCursorPosition.X--; + SetConsoleCursorPosition(hout, info.dwCursorPosition); + // blank out the last character + WriteConsoleOutputCharacterA(hout, " ", 1, info.dwCursorPosition, &written); } -static void -con_return (void) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // move onto the new line - info.dwCursorPosition.X = 0; - info.dwCursorPosition.Y++; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); +static void con_return(void) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // move onto the new line + info.dwCursorPosition.X = 0; + info.dwCursorPosition.Y++; + SetConsoleCursorPosition(hout, info.dwCursorPosition); } -static bool -runBind (char _key) -{ - for ( int i=0; i<_bindings.size(); i++ ) - { - el_binding *bind = _bindings[i]; - if ( bind->key[0] == _key ) - { - bind->func( (EditLine*) -1, _key ); - return true; - } +static bool runBind(char _key) { + for (int i = 0; i < _bindings.size(); i++) { + el_binding *bind = _bindings[i]; + if (bind->key[0] == _key) { + bind->func((EditLine *)-1, _key); + return true; } - return false; + } + return false; } // replacement get_s which is EL_BIND aware -static char * -el_get_s (char *buffer, int chars) -{ +static char *el_get_s(char *buffer, int chars) { + // + char *head = buffer; + // + for (;; Sleep(10)) { // - char *head = buffer; + INPUT_RECORD _record; // - for ( ;; Sleep( 10 ) ) - { - // - INPUT_RECORD _record; - // - DWORD _read = 0; - if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE ) - break; - // if we didn't read a key - if ( _read == 0 ) - continue; - // only interested in key events - if ( _record.EventType != KEY_EVENT ) - continue; - // is the key down - if (! _record.Event.KeyEvent.bKeyDown ) - continue; - // read the ascii key character - char _key = _record.Event.KeyEvent.uChar.AsciiChar; - // non ascii conformant key press - if ( _key == 0 ) - { - // check the scan code - // if VK_UP scroll back through history - // if VK_DOWN scroll forward through history - continue; - } - // try to execute any bind this key may have - if ( runBind( _key ) ) - continue; - // if we read a return key - if ( _key == '\n' || _key == '\r' ) - { - con_return( ); - break; - } - // key is backspace - if ( _key == 0x8 ) - { - // avoid deleting past beginning - if ( head > buffer ) - { - con_backspace( ); - head--; - } - continue; - } - - // add this key to the input buffer - if ( (head-buffer) < (chars-1) ) - { - con_output( _key ); - *(head++) = _key; - } + DWORD _read = 0; + if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE), &_record, 1, + &_read) == FALSE) + break; + // if we didn't read a key + if (_read == 0) + continue; + // only interested in key events + if (_record.EventType != KEY_EVENT) + continue; + // is the key down + if (!_record.Event.KeyEvent.bKeyDown) + continue; + // read the ascii key character + char _key = _record.Event.KeyEvent.uChar.AsciiChar; + // non ascii conformant key press + if (_key == 0) { + // check the scan code + // if VK_UP scroll back through history + // if VK_DOWN scroll forward through history + continue; + } + // try to execute any bind this key may have + if (runBind(_key)) + continue; + // if we read a return key + if (_key == '\n' || _key == '\r') { + con_return(); + break; + } + // key is backspace + if (_key == 0x8) { + // avoid deleting past beginning + if (head > buffer) { + con_backspace(); + head--; + } + continue; } - // insert end of line character - *head = '\0'; - return buffer; + // add this key to the input buffer + if ((head - buffer) < (chars - 1)) { + con_output(_key); + *(head++) = _key; + } + } + // insert end of line character + *head = '\0'; + + return buffer; } #endif // edit line initialize -EditLine * -el_init (const char *, FILE *, FILE *, FILE *) -{ - // - SetConsoleTitleA( "lldb" ); - // return dummy handle - return (EditLine*) -1; +EditLine *el_init(const char *, FILE *, FILE *, FILE *) { + // + SetConsoleTitleA("lldb"); + // return dummy handle + return (EditLine *)-1; } -const char * -el_gets (EditLine *el, int *length) -{ - // print the prompt if we have one - if ( _prompt != NULL ) - printf("%s", _prompt); - // create a buffer for the user input - char *buffer = new char[ MAX_PATH ]; - // try to get user input string - if ( el_get_s( buffer, MAX_PATH ) ) - { - // get the string length in 'length' - while ( buffer[ *length ] != '\0' ) - (*length)++; - // return the input buffer - // remember that this memory has the be free'd somewhere - return buffer; - } - else - { - // on error - delete [] buffer; - return NULL; - } +const char *el_gets(EditLine *el, int *length) { + // print the prompt if we have one + if (_prompt != NULL) + printf("%s", _prompt); + // create a buffer for the user input + char *buffer = new char[MAX_PATH]; + // try to get user input string + if (el_get_s(buffer, MAX_PATH)) { + // get the string length in 'length' + while (buffer[*length] != '\0') + (*length)++; + // return the input buffer + // remember that this memory has the be free'd somewhere + return buffer; + } else { + // on error + delete[] buffer; + return NULL; + } } -int -el_set (EditLine *el, int code, ...) -{ - va_list vl; - va_start(vl, code); - // - switch ( code ) - { - // edit line set prompt message - case ( EL_PROMPT ): - { - // EL_PROMPT, char *(*f)( EditLine *) - // define a prompt printing function as 'f', which is to return a string that - // contains the prompt. - - // get the function pointer from the arg list - void *func_vp = (void*)va_arg(vl, el_prompt_func); - // cast to suitable prototype - el_prompt_func func_fp = (el_prompt_func)func_vp; - // call to get the prompt as a string - _prompt = func_fp( el ); - } - break; - - case (EL_PROMPT_ESC) : - { - // EL_PROMPT, char *(*f)( EditLine *) - // define a prompt printing function as 'f', which is to return a string that - // contains the prompt. - - // get the function pointer from the arg list - void *func_vp = (void*)va_arg(vl, el_prompt_func); - va_arg(vl, int); - // call to get the prompt as a string - el_prompt_func func_fp = (el_prompt_func)func_vp; - _prompt = func_fp(el); - } - break; - - case ( EL_EDITOR ): - { - // EL_EDITOR, const char *mode - // set editing mode to "emacs" or "vi" - } - break; - case ( EL_HIST ): - { - // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr - // defines which history function to use, which is usually history(). Ptr should be the - // value returned by history_init(). - } - break; - case ( EL_ADDFN ): - { - // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch) - // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is - // entered. 'help' is a description of 'name'. at invocation time, 'ch' is the key which caused the invocation. the - // return value of 'func()' should be one of: - // CC_NORM add a normal character - // CC_NEWLINE end of line was entered - // CC_EOF EOF was entered - // CC_ARGHACK expecting further command input as arguments, do nothing visually. - // CC_REFRESH refresh display. - // CC_REFRESH_BEEP refresh display and beep. - // CC_CURSOR cursor moved so update and perform CC_REFRESH - // CC_REDISPLAY redisplay entire input line. this is useful if a key binding outputs extra information. - // CC_ERROR an error occurred. beep and flush tty. - // CC_FATAL fatal error, reset tty to known state. - - el_binding *binding = new el_binding; - binding->name = va_arg( vl, const char *); - binding->help = va_arg( vl, const char *); - binding->func = va_arg( vl, el_addfn_func ); - binding->key = 0; - // add this to the bindings list - _bindings.push_back( binding ); - } - break; - case ( EL_BIND ): - { - // EL_BIND, const char *, ..., NULL - // perform the BIND built-in command. Refer to editrc(5) for more information. - - const char *name = va_arg( vl, const char* ); - - for ( int i=0; i<_bindings.size(); i++ ) - { - el_binding *bind = _bindings[i]; - if ( strcmp( bind->name, name ) == 0 ) - { - bind->key = va_arg( vl, const char * ); - break; - } - } - - } - break; - case ( EL_CLIENTDATA ): - { - clientData = va_arg(vl, void*); - } +int el_set(EditLine *el, int code, ...) { + va_list vl; + va_start(vl, code); + // + switch (code) { + // edit line set prompt message + case (EL_PROMPT): { + // EL_PROMPT, char *(*f)( EditLine *) + // define a prompt printing function as 'f', which is to return a + // string that + // contains the prompt. + + // get the function pointer from the arg list + void *func_vp = (void *)va_arg(vl, el_prompt_func); + // cast to suitable prototype + el_prompt_func func_fp = (el_prompt_func)func_vp; + // call to get the prompt as a string + _prompt = func_fp(el); + } break; + + case (EL_PROMPT_ESC): { + // EL_PROMPT, char *(*f)( EditLine *) + // define a prompt printing function as 'f', which is to return a + // string that + // contains the prompt. + + // get the function pointer from the arg list + void *func_vp = (void *)va_arg(vl, el_prompt_func); + va_arg(vl, int); + // call to get the prompt as a string + el_prompt_func func_fp = (el_prompt_func)func_vp; + _prompt = func_fp(el); + } break; + + case (EL_EDITOR): { + // EL_EDITOR, const char *mode + // set editing mode to "emacs" or "vi" + } break; + case (EL_HIST): { + // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr + // defines which history function to use, which is usually history(). + // Ptr should be the + // value returned by history_init(). + } break; + case (EL_ADDFN): { + // EL_ADDFN, const char *name, const char *help, unsigned char + // (*func)(EditLine *e, int ch) + // add a user defined function, func), referred to as 'name' which is + // invoked when a key which is bound to 'name' is + // entered. 'help' is a description of 'name'. at invocation time, 'ch' + // is the key which caused the invocation. the + // return value of 'func()' should be one of: + // CC_NORM add a normal character + // CC_NEWLINE end of line was entered + // CC_EOF EOF was entered + // CC_ARGHACK expecting further command input as arguments, do + // nothing visually. + // CC_REFRESH refresh display. + // CC_REFRESH_BEEP refresh display and beep. + // CC_CURSOR cursor moved so update and perform CC_REFRESH + // CC_REDISPLAY redisplay entire input line. this is useful + // if a key binding outputs extra information. + // CC_ERROR an error occurred. beep and flush tty. + // CC_FATAL fatal error, reset tty to known state. + + el_binding *binding = new el_binding; + binding->name = va_arg(vl, const char *); + binding->help = va_arg(vl, const char *); + binding->func = va_arg(vl, el_addfn_func); + binding->key = 0; + // add this to the bindings list + _bindings.push_back(binding); + } break; + case (EL_BIND): { + // EL_BIND, const char *, ..., NULL + // perform the BIND built-in command. Refer to editrc(5) for more + // information. + + const char *name = va_arg(vl, const char *); + + for (int i = 0; i < _bindings.size(); i++) { + el_binding *bind = _bindings[i]; + if (strcmp(bind->name, name) == 0) { + bind->key = va_arg(vl, const char *); break; + } } - return 0; -} -void -el_end (EditLine *el) -{ - //assert( !"Not implemented!" ); + } break; + case (EL_CLIENTDATA): { + clientData = va_arg(vl, void *); + } break; + } + return 0; } -void -el_reset (EditLine *) -{ - assert( !"Not implemented!" ); +void el_end(EditLine *el) { + // assert( !"Not implemented!" ); } -int -el_getc (EditLine *, char *) -{ - assert( !"Not implemented!" ); - return 0; -} +void el_reset(EditLine *) { assert(!"Not implemented!"); } -void -el_push (EditLine *, const char *) -{ +int el_getc(EditLine *, char *) { + assert(!"Not implemented!"); + return 0; } -void -el_beep (EditLine *) -{ - Beep( 1000, 500 ); -} +void el_push(EditLine *, const char *) {} -int -el_parse (EditLine *, int, const char **) -{ - assert( !"Not implemented!" ); - return 0; -} +void el_beep(EditLine *) { Beep(1000, 500); } -int -el_get (EditLine *el, int code, ...) -{ - va_list vl; - va_start( vl, code ); - - switch ( code ) - { - case ( EL_CLIENTDATA ): - { - void **dout = va_arg( vl, void** ); - *dout = clientData; - } - break; - default: - assert( !"Not implemented!" ); - } - return 0; +int el_parse(EditLine *, int, const char **) { + assert(!"Not implemented!"); + return 0; } -int -el_source (EditLine *el, const char *file) -{ - // init edit line by reading the contents of 'file' - // nothing to do here on windows... - return 0; +int el_get(EditLine *el, int code, ...) { + va_list vl; + va_start(vl, code); + + switch (code) { + case (EL_CLIENTDATA): { + void **dout = va_arg(vl, void **); + *dout = clientData; + } break; + default: + assert(!"Not implemented!"); + } + return 0; } -void -el_resize (EditLine *) -{ - assert( !"Not implemented!" ); +int el_source(EditLine *el, const char *file) { + // init edit line by reading the contents of 'file' + // nothing to do here on windows... + return 0; } -const LineInfo * -el_line (EditLine *el) -{ - return 0; -} +void el_resize(EditLine *) { assert(!"Not implemented!"); } -int -el_insertstr (EditLine *, const char *) -{ -// assert( !"Not implemented!" ); - return 0; -} +const LineInfo *el_line(EditLine *el) { return 0; } -void -el_deletestr (EditLine *, int) -{ - assert( !"Not implemented!" ); +int el_insertstr(EditLine *, const char *) { + // assert( !"Not implemented!" ); + return 0; } -History * -history_init (void) -{ - // return dummy handle - return (History*) -1; +void el_deletestr(EditLine *, int) { assert(!"Not implemented!"); } + +History *history_init(void) { + // return dummy handle + return (History *)-1; } -void -history_end (History *) -{ -// assert( !"Not implemented!" ); +void history_end(History *) { + // assert( !"Not implemented!" ); } -int -history (History *, HistEvent *, int op, ...) -{ - // perform operation 'op' on the history list with - // optional arguments as needed by the operation. - return 0; +int history(History *, HistEvent *, int op, ...) { + // perform operation 'op' on the history list with + // optional arguments as needed by the operation. + return 0; } #endif diff --git a/lldb/source/Host/windows/FileSystem.cpp b/lldb/source/Host/windows/FileSystem.cpp index a3e0e4f82d1..36e567f7ddf 100644 --- a/lldb/source/Host/windows/FileSystem.cpp +++ b/lldb/source/Host/windows/FileSystem.cpp @@ -21,273 +21,241 @@ using namespace lldb_private; -const char * -FileSystem::DEV_NULL = "nul"; +const char *FileSystem::DEV_NULL = "nul"; -const char *FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding"; +const char *FileSystem::PATH_CONVERSION_ERROR = + "Error converting path between UTF-8 and native encoding"; -FileSpec::PathSyntax -FileSystem::GetNativePathSyntax() -{ - return FileSpec::ePathSyntaxWindows; +FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { + return FileSpec::ePathSyntaxWindows; } -Error -FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) -{ - // On Win32, the mode parameter is ignored, as Windows files and directories support a - // different permission model than POSIX. - Error error; - const auto err_code = llvm::sys::fs::create_directories(file_spec.GetPath(), true); - if (err_code) - { - error.SetErrorString(err_code.message().c_str()); - } - - return error; +Error FileSystem::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { + // On Win32, the mode parameter is ignored, as Windows files and directories + // support a + // different permission model than POSIX. + Error error; + const auto err_code = + llvm::sys::fs::create_directories(file_spec.GetPath(), true); + if (err_code) { + error.SetErrorString(err_code.message().c_str()); + } + + return error; } -Error -FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) -{ - Error error; - std::wstring path_buffer; - if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - if (!recurse) - { - BOOL result = ::RemoveDirectoryW(path_buffer.c_str()); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - } - else - { - // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to - // indicate the end of the list. The first null terminator is there only in the backing - // store but not the actual vector contents, and so we need to push twice. - path_buffer.push_back(0); - path_buffer.push_back(0); - - SHFILEOPSTRUCTW shfos = {0}; - shfos.wFunc = FO_DELETE; - shfos.pFrom = (LPCWSTR)path_buffer.data(); - shfos.fFlags = FOF_NO_UI; - - int result = ::SHFileOperationW(&shfos); - // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values. - if (result != 0) - error.SetErrorStringWithFormat("SHFileOperation failed"); - } +Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { + Error error; + std::wstring path_buffer; + if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) { + error.SetErrorString(PATH_CONVERSION_ERROR); return error; + } + if (!recurse) { + BOOL result = ::RemoveDirectoryW(path_buffer.c_str()); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + } else { + // SHFileOperation() accepts a list of paths, and so must be + // double-null-terminated to + // indicate the end of the list. The first null terminator is there only in + // the backing + // store but not the actual vector contents, and so we need to push twice. + path_buffer.push_back(0); + path_buffer.push_back(0); + + SHFILEOPSTRUCTW shfos = {0}; + shfos.wFunc = FO_DELETE; + shfos.pFrom = (LPCWSTR)path_buffer.data(); + shfos.fFlags = FOF_NO_UI; + + int result = ::SHFileOperationW(&shfos); + // TODO(zturner): Correctly handle the intricacies of SHFileOperation return + // values. + if (result != 0) + error.SetErrorStringWithFormat("SHFileOperation failed"); + } + return error; } -Error -FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) -{ - Error error; - // Beware that Windows's permission model is different from Unix's, and it's - // not clear if this API is supposed to check ACLs. To match the caller's - // expectations as closely as possible, we'll use Microsoft's _stat, which - // attempts to emulate POSIX stat. This should be good enough for basic - // checks like FileSpec::Readable. - struct _stat file_stats; - if (::_stat(file_spec.GetCString(), &file_stats) == 0) - { - // The owner permission bits in "st_mode" currently match the definitions - // for the owner file mode bits. - file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC); - } - else - { - error.SetErrorToErrno(); - } - - return error; +Error FileSystem::GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions) { + Error error; + // Beware that Windows's permission model is different from Unix's, and it's + // not clear if this API is supposed to check ACLs. To match the caller's + // expectations as closely as possible, we'll use Microsoft's _stat, which + // attempts to emulate POSIX stat. This should be good enough for basic + // checks like FileSpec::Readable. + struct _stat file_stats; + if (::_stat(file_spec.GetCString(), &file_stats) == 0) { + // The owner permission bits in "st_mode" currently match the definitions + // for the owner file mode bits. + file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC); + } else { + error.SetErrorToErrno(); + } + + return error; } -Error -FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) -{ - Error error; - error.SetErrorStringWithFormat("%s is not supported on this host", LLVM_PRETTY_FUNCTION); - return error; +Error FileSystem::SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions) { + Error error; + error.SetErrorStringWithFormat("%s is not supported on this host", + LLVM_PRETTY_FUNCTION); + return error; } -lldb::user_id_t -FileSystem::GetFileSize(const FileSpec &file_spec) -{ - return file_spec.GetByteSize(); +lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { + return file_spec.GetByteSize(); } -bool -FileSystem::GetFileExists(const FileSpec &file_spec) -{ - return file_spec.Exists(); +bool FileSystem::GetFileExists(const FileSpec &file_spec) { + return file_spec.Exists(); } -Error -FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - std::wstring wsrc, wdst; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) - error.SetErrorString(PATH_CONVERSION_ERROR); - else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr)) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; +Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { + Error error; + std::wstring wsrc, wdst; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || + !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) + error.SetErrorString(PATH_CONVERSION_ERROR); + else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr)) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -int -FileSystem::GetHardlinkCount(const FileSpec &file_spec) -{ - std::wstring path; - if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) - return -1; +int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { + std::wstring path; + if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) + return -1; - HANDLE file_handle = ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, nullptr); + HANDLE file_handle = + ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file_handle == INVALID_HANDLE_VALUE) - return -1; + if (file_handle == INVALID_HANDLE_VALUE) + return -1; - AutoHandle auto_file_handle(file_handle); - BY_HANDLE_FILE_INFORMATION file_info; - if (::GetFileInformationByHandle(file_handle, &file_info)) - return file_info.nNumberOfLinks; + AutoHandle auto_file_handle(file_handle); + BY_HANDLE_FILE_INFORMATION file_info; + if (::GetFileInformationByHandle(file_handle, &file_info)) + return file_info.nNumberOfLinks; - return -1; + return -1; } -Error -FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - std::wstring wsrc, wdst; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) - error.SetErrorString(PATH_CONVERSION_ERROR); - if (error.Fail()) - return error; - DWORD attrib = ::GetFileAttributesW(wdst.c_str()); - if (attrib == INVALID_FILE_ATTRIBUTES) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); - DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; - BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); +Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { + Error error; + std::wstring wsrc, wdst; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || + !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) + error.SetErrorString(PATH_CONVERSION_ERROR); + if (error.Fail()) + return error; + DWORD attrib = ::GetFileAttributesW(wdst.c_str()); + if (attrib == INVALID_FILE_ATTRIBUTES) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; + } + bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); + DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; + BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -Error -FileSystem::Unlink(const FileSpec &file_spec) -{ - Error error; - std::wstring path; - if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - BOOL result = ::DeleteFileW(path.c_str()); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); +Error FileSystem::Unlink(const FileSpec &file_spec) { + Error error; + std::wstring path; + if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) { + error.SetErrorString(PATH_CONVERSION_ERROR); return error; + } + BOOL result = ::DeleteFileW(path.c_str()); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -Error -FileSystem::Readlink(const FileSpec &src, FileSpec &dst) -{ - Error error; - std::wstring wsrc; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - - HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (h == INVALID_HANDLE_VALUE) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - - std::vector<wchar_t> buf(PATH_MAX + 1); - // Subtract 1 from the path length since this function does not add a null terminator. - DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); - std::string path; - if (result == 0) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - else if (!llvm::convertWideToUTF8(buf.data(), path)) - error.SetErrorString(PATH_CONVERSION_ERROR); - else - dst.SetFile(path, false); - - ::CloseHandle(h); +Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { + Error error; + std::wstring wsrc; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) { + error.SetErrorString(PATH_CONVERSION_ERROR); + return error; + } + + HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (h == INVALID_HANDLE_VALUE) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; + } + + std::vector<wchar_t> buf(PATH_MAX + 1); + // Subtract 1 from the path length since this function does not add a null + // terminator. + DWORD result = ::GetFinalPathNameByHandleW( + h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + std::string path; + if (result == 0) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + else if (!llvm::convertWideToUTF8(buf.data(), path)) + error.SetErrorString(PATH_CONVERSION_ERROR); + else + dst.SetFile(path, false); + + ::CloseHandle(h); + return error; } -Error -FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) -{ - return Error("ResolveSymbolicLink() isn't implemented on Windows"); +Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { + return Error("ResolveSymbolicLink() isn't implemented on Windows"); } -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - if (spec) - { - // TODO: return true if the file is on a locally mounted file system - return true; - } +bool FileSystem::IsLocal(const FileSpec &spec) { + if (spec) { + // TODO: return true if the file is on a locally mounted file system + return true; + } - return false; + return false; } -FILE * -FileSystem::Fopen(const char *path, const char *mode) -{ - std::wstring wpath, wmode; - if (!llvm::ConvertUTF8toWide(path, wpath)) - return nullptr; - if (!llvm::ConvertUTF8toWide(mode, wmode)) - return nullptr; - FILE *file; - if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) - return nullptr; - return file; +FILE *FileSystem::Fopen(const char *path, const char *mode) { + std::wstring wpath, wmode; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return nullptr; + if (!llvm::ConvertUTF8toWide(mode, wmode)) + return nullptr; + FILE *file; + if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) + return nullptr; + return file; } -int -FileSystem::Stat(const char *path, struct stat *stats) -{ - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - errno = EINVAL; - return -EINVAL; - } - int stat_result; +int FileSystem::Stat(const char *path, struct stat *stats) { + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + errno = EINVAL; + return -EINVAL; + } + int stat_result; #ifdef _USE_32BIT_TIME_T - struct _stat32 file_stats; - stat_result = ::_wstat32(wpath.c_str(), &file_stats); + struct _stat32 file_stats; + stat_result = ::_wstat32(wpath.c_str(), &file_stats); #else - struct _stat64i32 file_stats; - stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); + struct _stat64i32 file_stats; + stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); #endif - if (stat_result == 0) - { - static_assert(sizeof(struct stat) == sizeof(file_stats), - "stat and _stat32/_stat64i32 must have the same layout"); - *stats = *reinterpret_cast<struct stat *>(&file_stats); - } - return stat_result; + if (stat_result == 0) { + static_assert(sizeof(struct stat) == sizeof(file_stats), + "stat and _stat32/_stat64i32 must have the same layout"); + *stats = *reinterpret_cast<struct stat *>(&file_stats); + } + return stat_result; } diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp index 1b4eeb8d4f6..9fbea89cb9e 100644 --- a/lldb/source/Host/windows/Host.cpp +++ b/lldb/source/Host/windows/Host.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// // C Includes -#include <stdio.h> -#include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/AutoHandle.h" +#include "lldb/Host/windows/windows.h" +#include <stdio.h> // C++ Includes // Other libraries and framework includes @@ -19,12 +19,12 @@ #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "llvm/Support/ConvertUTF.h" @@ -34,305 +34,270 @@ using namespace lldb; using namespace lldb_private; -namespace -{ - bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) - { - // Open the PE File as a binary file, and parse just enough information to determine the - // machine type. - File imageBinary( - executable.GetPath().c_str(), - File::eOpenOptionRead, - lldb::eFilePermissionsUserRead); - imageBinary.SeekFromStart(0x3c); - int32_t peOffset = 0; - uint32_t peHead = 0; - uint16_t machineType = 0; - size_t readSize = sizeof(peOffset); - imageBinary.Read(&peOffset, readSize); - imageBinary.SeekFromStart(peOffset); - imageBinary.Read(&peHead, readSize); - if (peHead != 0x00004550) // "PE\0\0", little-endian - return false; // Error: Can't find PE header - readSize = 2; - imageBinary.Read(&machineType, readSize); - triple.setVendor(llvm::Triple::PC); - triple.setOS(llvm::Triple::Win32); - triple.setArch(llvm::Triple::UnknownArch); - if (machineType == 0x8664) - triple.setArch(llvm::Triple::x86_64); - else if (machineType == 0x14c) - triple.setArch(llvm::Triple::x86); - - return true; - } +namespace { +bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) { + // Open the PE File as a binary file, and parse just enough information to + // determine the + // machine type. + File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead, + lldb::eFilePermissionsUserRead); + imageBinary.SeekFromStart(0x3c); + int32_t peOffset = 0; + uint32_t peHead = 0; + uint16_t machineType = 0; + size_t readSize = sizeof(peOffset); + imageBinary.Read(&peOffset, readSize); + imageBinary.SeekFromStart(peOffset); + imageBinary.Read(&peHead, readSize); + if (peHead != 0x00004550) // "PE\0\0", little-endian + return false; // Error: Can't find PE header + readSize = 2; + imageBinary.Read(&machineType, readSize); + triple.setVendor(llvm::Triple::PC); + triple.setOS(llvm::Triple::Win32); + triple.setArch(llvm::Triple::UnknownArch); + if (machineType == 0x8664) + triple.setArch(llvm::Triple::x86_64); + else if (machineType == 0x14c) + triple.setArch(llvm::Triple::x86); + + return true; +} - bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) - { - // Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB. - std::vector<wchar_t> buffer(PATH_MAX); - DWORD dwSize = buffer.size(); - if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize)) - return false; - return llvm::convertWideToUTF8(buffer.data(), path); - } +bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) { + // Get the process image path. MAX_PATH isn't long enough, paths can actually + // be up to 32KB. + std::vector<wchar_t> buffer(PATH_MAX); + DWORD dwSize = buffer.size(); + if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize)) + return false; + return llvm::convertWideToUTF8(buffer.data(), path); +} - void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process) - { - // We may not have permissions to read the path from the process. So start off by - // setting the executable file to whatever Toolhelp32 gives us, and then try to - // enhance this with more detailed information, but fail gracefully. - std::string executable; - llvm::Triple triple; - triple.setVendor(llvm::Triple::PC); - triple.setOS(llvm::Triple::Win32); - triple.setArch(llvm::Triple::UnknownArch); - if (GetExecutableForProcess(handle, executable)) - { - FileSpec executableFile(executable.c_str(), false); - process.SetExecutableFile(executableFile, true); - GetTripleForProcess(executableFile, triple); - } - process.SetArchitecture(ArchSpec(triple)); - - // TODO(zturner): Add the ability to get the process user name. - } +void GetProcessExecutableAndTriple(const AutoHandle &handle, + ProcessInstanceInfo &process) { + // We may not have permissions to read the path from the process. So start + // off by + // setting the executable file to whatever Toolhelp32 gives us, and then try + // to + // enhance this with more detailed information, but fail gracefully. + std::string executable; + llvm::Triple triple; + triple.setVendor(llvm::Triple::PC); + triple.setOS(llvm::Triple::Win32); + triple.setArch(llvm::Triple::UnknownArch); + if (GetExecutableForProcess(handle, executable)) { + FileSpec executableFile(executable.c_str(), false); + process.SetExecutableFile(executableFile, true); + GetTripleForProcess(executableFile, triple); + } + process.SetArchitecture(ArchSpec(triple)); + + // TODO(zturner): Add the ability to get the process user name. +} } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - return 0; +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + return 0; } -lldb::tid_t -Host::GetCurrentThreadID() -{ - return lldb::tid_t(::GetCurrentThreadId()); +lldb::tid_t Host::GetCurrentThreadID() { + return lldb::tid_t(::GetCurrentThreadId()); } -lldb::thread_t -Host::GetCurrentThread () -{ - return lldb::thread_t(::GetCurrentThread()); +lldb::thread_t Host::GetCurrentThread() { + return lldb::thread_t(::GetCurrentThread()); } lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) -{ - return TlsAlloc(); +Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { + return TlsAlloc(); } -void* -Host::ThreadLocalStorageGet(lldb::thread_key_t key) -{ - return ::TlsGetValue (key); +void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { + return ::TlsGetValue(key); } -void -Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) -{ - ::TlsSetValue (key, value); +void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { + ::TlsSetValue(key, value); } -void -Host::Kill(lldb::pid_t pid, int signo) -{ - TerminateProcess((HANDLE) pid, 1); +void Host::Kill(lldb::pid_t pid, int signo) { + TerminateProcess((HANDLE)pid, 1); } +const char *Host::GetSignalAsCString(int signo) { return NULL; } + +FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { + FileSpec module_filespec; + + HMODULE hmodule = NULL; + if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)host_addr, &hmodule)) + return module_filespec; -const char * -Host::GetSignalAsCString(int signo) -{ - return NULL; + std::vector<wchar_t> buffer(PATH_MAX); + DWORD chars_copied = 0; + do { + chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size()); + if (chars_copied == buffer.size() && + ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + buffer.resize(buffer.size() * 2); + } while (chars_copied >= buffer.size()); + std::string path; + if (!llvm::convertWideToUTF8(buffer.data(), path)) + return module_filespec; + module_filespec.SetFile(path, false); + return module_filespec; } -FileSpec -Host::GetModuleFileSpecForHostAddress (const void *host_addr) -{ - FileSpec module_filespec; +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + process_infos.Clear(); - HMODULE hmodule = NULL; - if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule)) - return module_filespec; + AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (!snapshot.IsValid()) + return 0; - std::vector<wchar_t> buffer(PATH_MAX); - DWORD chars_copied = 0; + PROCESSENTRY32W pe = {0}; + pe.dwSize = sizeof(PROCESSENTRY32W); + if (Process32FirstW(snapshot.get(), &pe)) { do { - chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size()); - if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) - buffer.resize(buffer.size() * 2); - } while (chars_copied >= buffer.size()); - std::string path; - if (!llvm::convertWideToUTF8(buffer.data(), path)) - return module_filespec; - module_filespec.SetFile(path, false); - return module_filespec; + AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, + pe.th32ProcessID), + nullptr); + + ProcessInstanceInfo process; + std::string exeFile; + llvm::convertWideToUTF8(pe.szExeFile, exeFile); + process.SetExecutableFile(FileSpec(exeFile, false), true); + process.SetProcessID(pe.th32ProcessID); + process.SetParentProcessID(pe.th32ParentProcessID); + GetProcessExecutableAndTriple(handle, process); + + if (match_info.MatchAllProcesses() || match_info.Matches(process)) + process_infos.Append(process); + } while (Process32NextW(snapshot.get(), &pe)); + } + return process_infos.GetSize(); } -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - process_infos.Clear(); - - AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); - if (!snapshot.IsValid()) - return 0; - - PROCESSENTRY32W pe = {0}; - pe.dwSize = sizeof(PROCESSENTRY32W); - if (Process32FirstW(snapshot.get(), &pe)) - { - do - { - AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr); - - ProcessInstanceInfo process; - std::string exeFile; - llvm::convertWideToUTF8(pe.szExeFile, exeFile); - process.SetExecutableFile(FileSpec(exeFile, false), true); - process.SetProcessID(pe.th32ProcessID); - process.SetParentProcessID(pe.th32ParentProcessID); - GetProcessExecutableAndTriple(handle, process); - - if (match_info.MatchAllProcesses() || match_info.Matches(process)) - process_infos.Append(process); - } while (Process32NextW(snapshot.get(), &pe)); - } - return process_infos.GetSize(); -} +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.Clear(); -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.Clear(); - - AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), - nullptr); - if (!handle.IsValid()) - return false; - - process_info.SetProcessID(pid); - GetProcessExecutableAndTriple(handle, process_info); - - // Need to read the PEB to get parent process and command line arguments. - return true; + AutoHandle handle( + ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), + nullptr); + if (!handle.IsValid()) + return false; + + process_info.SetProcessID(pid); + GetProcessExecutableAndTriple(handle, process_info); + + // Need to read the PEB to get parent process and command line arguments. + return true; } -HostThread -Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, - bool monitor_signals) -{ - return HostThread(); +HostThread Host::StartMonitoringChildProcess( + const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, + bool monitor_signals) { + return HostThread(); } -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - Error error; - if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) - { - FileSpec expand_tool_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec)) - { - error.SetErrorString("could not find support executable directory for the lldb-argdumper tool"); - return error; - } - expand_tool_spec.AppendPathComponent("lldb-argdumper.exe"); - if (!expand_tool_spec.Exists()) - { - error.SetErrorString("could not find the lldb-argdumper tool"); - return error; - } - - std::string quoted_cmd_string; - launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string); - std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/'); - StreamString expand_command; - - expand_command.Printf("\"%s\" %s", - expand_tool_spec.GetPath().c_str(), - quoted_cmd_string.c_str()); - - int status; - std::string output; - RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), &status, nullptr, &output, 10); - - if (status != 0) - { - error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", status); - return error; - } - - auto data_sp = StructuredData::ParseJSON(output); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto dict_sp = data_sp->GetAsDictionary(); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); - if (!args_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto args_array_sp = args_sp->GetAsArray(); - if (!args_array_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - launch_info.GetArguments().Clear(); - - for (size_t i = 0; - i < args_array_sp->GetSize(); - i++) - { - auto item_sp = args_array_sp->GetItemAtIndex(i); - if (!item_sp) - continue; - auto str_sp = item_sp->GetAsString(); - if (!str_sp) - continue; - - launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); - } +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + Error error; + if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { + FileSpec expand_tool_spec; + if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, + expand_tool_spec)) { + error.SetErrorString("could not find support executable directory for " + "the lldb-argdumper tool"); + return error; + } + expand_tool_spec.AppendPathComponent("lldb-argdumper.exe"); + if (!expand_tool_spec.Exists()) { + error.SetErrorString("could not find the lldb-argdumper tool"); + return error; + } + + std::string quoted_cmd_string; + launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string); + std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/'); + StreamString expand_command; + + expand_command.Printf("\"%s\" %s", expand_tool_spec.GetPath().c_str(), + quoted_cmd_string.c_str()); + + int status; + std::string output; + RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), + &status, nullptr, &output, 10); + + if (status != 0) { + error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", + status); + return error; + } + + auto data_sp = StructuredData::ParseJSON(output); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + auto dict_sp = data_sp->GetAsDictionary(); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); + if (!args_sp) { + error.SetErrorString("invalid JSON"); + return error; } - - return error; + + auto args_array_sp = args_sp->GetAsArray(); + if (!args_array_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + launch_info.GetArguments().Clear(); + + for (size_t i = 0; i < args_array_sp->GetSize(); i++) { + auto item_sp = args_array_sp->GetItemAtIndex(i); + if (!item_sp) + continue; + auto str_sp = item_sp->GetAsString(); + if (!str_sp) + continue; + + launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); + } + } + + return error; } -size_t -Host::GetEnvironment(StringList &env) -{ - // The environment block on Windows is a contiguous buffer of NULL terminated strings, - // where the end of the environment block is indicated by two consecutive NULLs. - LPWCH environment_block = ::GetEnvironmentStringsW(); - env.Clear(); - while (*environment_block != L'\0') - { - std::string current_var; - auto current_var_size = wcslen(environment_block) + 1; - if (!llvm::convertWideToUTF8(environment_block, current_var)) - { - environment_block += current_var_size; - continue; - } - if (current_var[0] != '=') - env.AppendString(current_var); - - environment_block += current_var_size; +size_t Host::GetEnvironment(StringList &env) { + // The environment block on Windows is a contiguous buffer of NULL terminated + // strings, + // where the end of the environment block is indicated by two consecutive + // NULLs. + LPWCH environment_block = ::GetEnvironmentStringsW(); + env.Clear(); + while (*environment_block != L'\0') { + std::string current_var; + auto current_var_size = wcslen(environment_block) + 1; + if (!llvm::convertWideToUTF8(environment_block, current_var)) { + environment_block += current_var_size; + continue; } - return env.GetSize(); + if (current_var[0] != '=') + env.AppendString(current_var); + + environment_block += current_var_size; + } + return env.GetSize(); } diff --git a/lldb/source/Host/windows/HostInfoWindows.cpp b/lldb/source/Host/windows/HostInfoWindows.cpp index 6b219029408..a965ec0ea4e 100644 --- a/lldb/source/Host/windows/HostInfoWindows.cpp +++ b/lldb/source/Host/windows/HostInfoWindows.cpp @@ -24,127 +24,108 @@ using namespace lldb_private; FileSpec HostInfoWindows::m_program_filespec; -void -HostInfoWindows::Initialize() -{ - ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); - HostInfoBase::Initialize(); +void HostInfoWindows::Initialize() { + ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); + HostInfoBase::Initialize(); } -void -HostInfoWindows::Terminate() -{ - HostInfoBase::Terminate(); - ::CoUninitialize(); +void HostInfoWindows::Terminate() { + HostInfoBase::Terminate(); + ::CoUninitialize(); } -size_t -HostInfoWindows::GetPageSize() -{ - SYSTEM_INFO systemInfo; - GetNativeSystemInfo(&systemInfo); - return systemInfo.dwPageSize; +size_t HostInfoWindows::GetPageSize() { + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&systemInfo); + return systemInfo.dwPageSize; } -bool -HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) -{ - OSVERSIONINFOEX info; +bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + OSVERSIONINFOEX info; - ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); #pragma warning(push) #pragma warning(disable : 4996) - // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in favor of the - // new Windows Version Helper APIs. Since we don't specify a minimum SDK version, it's easier - // to simply disable the warning rather than try to support both APIs. - if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) - { - return false; - } + // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in + // favor of the + // new Windows Version Helper APIs. Since we don't specify a minimum SDK + // version, it's easier + // to simply disable the warning rather than try to support both APIs. + if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) { + return false; + } #pragma warning(pop) - major = info.dwMajorVersion; - minor = info.dwMinorVersion; - update = info.wServicePackMajor; + major = info.dwMajorVersion; + minor = info.dwMinorVersion; + update = info.wServicePackMajor; - return true; + return true; } -bool -HostInfoWindows::GetOSBuildString(std::string &s) -{ - s.clear(); - uint32_t major, minor, update; - if (!GetOSVersion(major, minor, update)) - return false; - - llvm::raw_string_ostream stream(s); - stream << "Windows NT " << major << "." << minor << "." << update; - return true; +bool HostInfoWindows::GetOSBuildString(std::string &s) { + s.clear(); + uint32_t major, minor, update; + if (!GetOSVersion(major, minor, update)) + return false; + + llvm::raw_string_ostream stream(s); + stream << "Windows NT " << major << "." << minor << "." << update; + return true; } -bool -HostInfoWindows::GetOSKernelDescription(std::string &s) -{ - return GetOSBuildString(s); +bool HostInfoWindows::GetOSKernelDescription(std::string &s) { + return GetOSBuildString(s); } -bool -HostInfoWindows::GetHostname(std::string &s) -{ - wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; - if (!::GetComputerNameW(buffer, &dwSize)) - return false; +bool HostInfoWindows::GetHostname(std::string &s) { + wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; + if (!::GetComputerNameW(buffer, &dwSize)) + return false; - return llvm::convertWideToUTF8(buffer, s); + return llvm::convertWideToUTF8(buffer, s); } -FileSpec -HostInfoWindows::GetProgramFileSpec() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - std::vector<wchar_t> buffer(PATH_MAX); - ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); - std::string path; - llvm::convertWideToUTF8(buffer.data(), path); - m_program_filespec.SetFile(path, false); - }); - return m_program_filespec; +FileSpec HostInfoWindows::GetProgramFileSpec() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + std::vector<wchar_t> buffer(PATH_MAX); + ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); + std::string path; + llvm::convertWideToUTF8(buffer.data(), path); + m_program_filespec.SetFile(path, false); + }); + return m_program_filespec; } -FileSpec -HostInfoWindows::GetDefaultShell() -{ - std::string shell; - GetEnvironmentVar("ComSpec", shell); - return FileSpec(shell, false); +FileSpec HostInfoWindows::GetDefaultShell() { + std::string shell; + GetEnvironmentVar("ComSpec", shell); + return FileSpec(shell, false); } -bool -HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) -{ - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString()); - llvm::sys::path::remove_filename(path); - llvm::sys::path::append(path, "lib", "site-packages"); - std::replace(path.begin(), path.end(), '\\', '/'); - file_spec.GetDirectory().SetString(path.c_str()); - return true; +bool HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) { + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; + llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString()); + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, "lib", "site-packages"); + std::replace(path.begin(), path.end(), '\\', '/'); + file_spec.GetDirectory().SetString(path.c_str()); + return true; } -bool -HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var) -{ - std::wstring wvar_name; - if (!llvm::ConvertUTF8toWide(var_name, wvar_name)) - return false; - - if (const wchar_t *wvar = _wgetenv(wvar_name.c_str())) - return llvm::convertWideToUTF8(wvar, var); +bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name, + std::string &var) { + std::wstring wvar_name; + if (!llvm::ConvertUTF8toWide(var_name, wvar_name)) return false; + + if (const wchar_t *wvar = _wgetenv(wvar_name.c_str())) + return llvm::convertWideToUTF8(wvar, var); + return false; } diff --git a/lldb/source/Host/windows/HostProcessWindows.cpp b/lldb/source/Host/windows/HostProcessWindows.cpp index 2878171cbe7..81c81a775df 100644 --- a/lldb/source/Host/windows/HostProcessWindows.cpp +++ b/lldb/source/Host/windows/HostProcessWindows.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/windows.h" -#include "lldb/Host/windows/HostProcessWindows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" @@ -20,123 +20,101 @@ using namespace lldb_private; -namespace -{ -struct MonitorInfo -{ - Host::MonitorChildProcessCallback callback; - HANDLE process_handle; +namespace { +struct MonitorInfo { + Host::MonitorChildProcessCallback callback; + HANDLE process_handle; }; } HostProcessWindows::HostProcessWindows() - : HostNativeProcessBase() - , m_owns_handle(true) -{ -} + : HostNativeProcessBase(), m_owns_handle(true) {} HostProcessWindows::HostProcessWindows(lldb::process_t process) - : HostNativeProcessBase(process) - , m_owns_handle(true) -{ -} + : HostNativeProcessBase(process), m_owns_handle(true) {} -HostProcessWindows::~HostProcessWindows() -{ - Close(); -} +HostProcessWindows::~HostProcessWindows() { Close(); } -void -HostProcessWindows::SetOwnsHandle(bool owns) -{ - m_owns_handle = owns; -} +void HostProcessWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; } -Error HostProcessWindows::Terminate() -{ - Error error; - if (m_process == nullptr) - error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); +Error HostProcessWindows::Terminate() { + Error error; + if (m_process == nullptr) + error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); - if (!::TerminateProcess(m_process, 0)) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + if (!::TerminateProcess(m_process, 0)) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + return error; } -Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const -{ - Error error; - if (m_process == nullptr) - error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); - - std::vector<wchar_t> wpath(PATH_MAX); - if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) - { - std::string path; - if (llvm::convertWideToUTF8(wpath.data(), path)) - file_spec.SetFile(path, false); - else - error.SetErrorString("Error converting path to UTF-8"); - } +Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const { + Error error; + if (m_process == nullptr) + error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); + + std::vector<wchar_t> wpath(PATH_MAX); + if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) { + std::string path; + if (llvm::convertWideToUTF8(wpath.data(), path)) + file_spec.SetFile(path, false); else - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + error.SetErrorString("Error converting path to UTF-8"); + } else + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + return error; } -lldb::pid_t HostProcessWindows::GetProcessId() const -{ - return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); +lldb::pid_t HostProcessWindows::GetProcessId() const { + return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); } -bool HostProcessWindows::IsRunning() const -{ - if (m_process == nullptr) - return false; +bool HostProcessWindows::IsRunning() const { + if (m_process == nullptr) + return false; - DWORD code = 0; - if (!::GetExitCodeProcess(m_process, &code)) - return false; + DWORD code = 0; + if (!::GetExitCodeProcess(m_process, &code)) + return false; - return (code == STILL_ACTIVE); + return (code == STILL_ACTIVE); } -HostThread -HostProcessWindows::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - HostThread monitor_thread; - MonitorInfo *info = new MonitorInfo; - info->callback = callback; - - // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that - // the monitor thread can have ownership over its own copy of the handle. - HostThread result; - if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) - result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); - return result; +HostThread HostProcessWindows::StartMonitoring( + const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { + HostThread monitor_thread; + MonitorInfo *info = new MonitorInfo; + info->callback = callback; + + // Since the life of this HostProcessWindows instance and the life of the + // process may be different, duplicate the handle so that + // the monitor thread can have ownership over its own copy of the handle. + HostThread result; + if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), + &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + result = ThreadLauncher::LaunchThread("ChildProcessMonitor", + HostProcessWindows::MonitorThread, + info, nullptr); + return result; } -lldb::thread_result_t -HostProcessWindows::MonitorThread(void *thread_arg) -{ - DWORD exit_code; - - MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); - if (info) - { - ::WaitForSingleObject(info->process_handle, INFINITE); - ::GetExitCodeProcess(info->process_handle, &exit_code); - info->callback(::GetProcessId(info->process_handle), true, 0, exit_code); - ::CloseHandle(info->process_handle); - delete (info); - } - return 0; +lldb::thread_result_t HostProcessWindows::MonitorThread(void *thread_arg) { + DWORD exit_code; + + MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); + if (info) { + ::WaitForSingleObject(info->process_handle, INFINITE); + ::GetExitCodeProcess(info->process_handle, &exit_code); + info->callback(::GetProcessId(info->process_handle), true, 0, exit_code); + ::CloseHandle(info->process_handle); + delete (info); + } + return 0; } -void HostProcessWindows::Close() -{ - if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) - ::CloseHandle(m_process); - m_process = nullptr; +void HostProcessWindows::Close() { + if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) + ::CloseHandle(m_process); + m_process = nullptr; } diff --git a/lldb/source/Host/windows/HostThreadWindows.cpp b/lldb/source/Host/windows/HostThreadWindows.cpp index d59064fb1c1..41be21bfa30 100644 --- a/lldb/source/Host/windows/HostThreadWindows.cpp +++ b/lldb/source/Host/windows/HostThreadWindows.cpp @@ -9,90 +9,63 @@ #include "lldb/Core/Error.h" -#include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/HostThreadWindows.h" +#include "lldb/Host/windows/windows.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; using namespace lldb_private; -namespace -{ -void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode) -{ - ::ExitThread(dwExitCode); +namespace { +void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode) { + ::ExitThread(dwExitCode); } } HostThreadWindows::HostThreadWindows() - : HostNativeThreadBase() - , m_owns_handle(true) -{ -} + : HostNativeThreadBase(), m_owns_handle(true) {} HostThreadWindows::HostThreadWindows(lldb::thread_t thread) - : HostNativeThreadBase(thread) - , m_owns_handle(true) -{ -} - -HostThreadWindows::~HostThreadWindows() -{ - Reset(); -} - -void -HostThreadWindows::SetOwnsHandle(bool owns) -{ - m_owns_handle = owns; -} - -Error -HostThreadWindows::Join(lldb::thread_result_t *result) -{ - Error error; - if (IsJoinable()) - { - DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE); - if (WAIT_OBJECT_0 == wait_result && result) - { - DWORD exit_code = 0; - if (!::GetExitCodeThread(m_thread, &exit_code)) - *result = 0; - *result = exit_code; - } - else if (WAIT_OBJECT_0 != wait_result) - error.SetError(::GetLastError(), eErrorTypeWin32); - } - else - error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - Reset (); - return error; + : HostNativeThreadBase(thread), m_owns_handle(true) {} + +HostThreadWindows::~HostThreadWindows() { Reset(); } + +void HostThreadWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; } + +Error HostThreadWindows::Join(lldb::thread_result_t *result) { + Error error; + if (IsJoinable()) { + DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE); + if (WAIT_OBJECT_0 == wait_result && result) { + DWORD exit_code = 0; + if (!::GetExitCodeThread(m_thread, &exit_code)) + *result = 0; + *result = exit_code; + } else if (WAIT_OBJECT_0 != wait_result) + error.SetError(::GetLastError(), eErrorTypeWin32); + } else + error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + Reset(); + return error; } -Error -HostThreadWindows::Cancel() -{ - Error error; +Error HostThreadWindows::Cancel() { + Error error; - DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0); - error.SetError(result, eErrorTypeWin32); - return error; + DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0); + error.SetError(result, eErrorTypeWin32); + return error; } -lldb::tid_t -HostThreadWindows::GetThreadId() const -{ - return ::GetThreadId(m_thread); +lldb::tid_t HostThreadWindows::GetThreadId() const { + return ::GetThreadId(m_thread); } -void -HostThreadWindows::Reset() -{ - if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD) - ::CloseHandle(m_thread); +void HostThreadWindows::Reset() { + if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD) + ::CloseHandle(m_thread); - HostNativeThreadBase::Reset(); + HostNativeThreadBase::Reset(); } diff --git a/lldb/source/Host/windows/LockFileWindows.cpp b/lldb/source/Host/windows/LockFileWindows.cpp index 161d3dbd826..e951c1bea1e 100644 --- a/lldb/source/Host/windows/LockFileWindows.cpp +++ b/lldb/source/Host/windows/LockFileWindows.cpp @@ -14,80 +14,65 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error fileLock (HANDLE file_handle, DWORD flags, const uint64_t start, const uint64_t len) -{ - if (start != 0) - return Error ("Non-zero start lock regions are not supported"); +Error fileLock(HANDLE file_handle, DWORD flags, const uint64_t start, + const uint64_t len) { + if (start != 0) + return Error("Non-zero start lock regions are not supported"); - OVERLAPPED overlapped = {0}; + OVERLAPPED overlapped = {0}; - if (!::LockFileEx (file_handle, flags, 0, len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) - return Error (::GetLastError (), eErrorTypeWin32); + if (!::LockFileEx(file_handle, flags, 0, len, 0, &overlapped) && + ::GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); - DWORD bytes; - if (!::GetOverlappedResult (file_handle, &overlapped, &bytes, TRUE)) - return Error (::GetLastError (), eErrorTypeWin32); + DWORD bytes; + if (!::GetOverlappedResult(file_handle, &overlapped, &bytes, TRUE)) + return Error(::GetLastError(), eErrorTypeWin32); - return Error (); + return Error(); } -} // namespace +} // namespace -LockFileWindows::LockFileWindows (int fd) - : LockFileBase (fd), - m_file (reinterpret_cast<HANDLE> (_get_osfhandle (fd))) -{ -} +LockFileWindows::LockFileWindows(int fd) + : LockFileBase(fd), m_file(reinterpret_cast<HANDLE>(_get_osfhandle(fd))) {} -LockFileWindows::~LockFileWindows () -{ - Unlock (); -} +LockFileWindows::~LockFileWindows() { Unlock(); } -bool -LockFileWindows::IsValidFile () const -{ - return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE; +bool LockFileWindows::IsValidFile() const { + return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE; } -Error -LockFileWindows::DoWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len); +Error LockFileWindows::DoWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len); } -Error -LockFileWindows::DoTryWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, start, len); +Error LockFileWindows::DoTryWriteLock(const uint64_t start, + const uint64_t len) { + return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, + start, len); } -Error -LockFileWindows::DoReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, 0, start, len); +Error LockFileWindows::DoReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, 0, start, len); } -Error -LockFileWindows::DoTryReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len); +Error LockFileWindows::DoTryReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len); } -Error -LockFileWindows::DoUnlock () -{ - OVERLAPPED overlapped = {0}; +Error LockFileWindows::DoUnlock() { + OVERLAPPED overlapped = {0}; - if (!::UnlockFileEx (m_file, 0, m_len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) - return Error (::GetLastError (), eErrorTypeWin32); + if (!::UnlockFileEx(m_file, 0, m_len, 0, &overlapped) && + ::GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); - DWORD bytes; - if (!::GetOverlappedResult (m_file, &overlapped, &bytes, TRUE)) - return Error (::GetLastError (), eErrorTypeWin32); + DWORD bytes; + if (!::GetOverlappedResult(m_file, &overlapped, &bytes, TRUE)) + return Error(::GetLastError(), eErrorTypeWin32); - return Error (); + return Error(); } diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp index 6ed8d0e83f3..b63f3bc4eed 100644 --- a/lldb/source/Host/windows/PipeWindows.cpp +++ b/lldb/source/Host/windows/PipeWindows.cpp @@ -23,316 +23,273 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { std::atomic<uint32_t> g_pipe_serial(0); } -PipeWindows::PipeWindows() -{ - m_read = INVALID_HANDLE_VALUE; - m_write = INVALID_HANDLE_VALUE; +PipeWindows::PipeWindows() { + m_read = INVALID_HANDLE_VALUE; + m_write = INVALID_HANDLE_VALUE; - m_read_fd = -1; - m_write_fd = -1; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); -} - -PipeWindows::~PipeWindows() -{ - Close(); + m_read_fd = -1; + m_write_fd = -1; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } -Error -PipeWindows::CreateNew(bool child_process_inherit) -{ - // Even for anonymous pipes, we open a named pipe. This is because you cannot get - // overlapped i/o on Windows without using a named pipe. So we synthesize a unique - // name. - uint32_t serial = g_pipe_serial.fetch_add(1); - std::string pipe_name; - llvm::raw_string_ostream pipe_name_stream(pipe_name); - pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial; - pipe_name_stream.flush(); - - return CreateNew(pipe_name.c_str(), child_process_inherit); +PipeWindows::~PipeWindows() { Close(); } + +Error PipeWindows::CreateNew(bool child_process_inherit) { + // Even for anonymous pipes, we open a named pipe. This is because you cannot + // get + // overlapped i/o on Windows without using a named pipe. So we synthesize a + // unique + // name. + uint32_t serial = g_pipe_serial.fetch_add(1); + std::string pipe_name; + llvm::raw_string_ostream pipe_name_stream(pipe_name); + pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial; + pipe_name_stream.flush(); + + return CreateNew(pipe_name.c_str(), child_process_inherit); } -Error -PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) -{ - if (name.empty()) - return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); - - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - - std::string pipe_path = "\\\\.\\Pipe\\"; - pipe_path.append(name); - - // Always open for overlapped i/o. We implement blocking manually in Read and Write. - DWORD read_mode = FILE_FLAG_OVERLAPPED; - m_read = ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, - 1024, 120 * 1000, NULL); - if (INVALID_HANDLE_VALUE == m_read) - return Error(::GetLastError(), eErrorTypeWin32); - m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - - // Open the write end of the pipe. - Error result = OpenNamedPipe(name, child_process_inherit, false); - if (!result.Success()) - { - CloseReadFileDescriptor(); - return result; - } - +Error PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) { + if (name.empty()) + return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); + + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); + + std::string pipe_path = "\\\\.\\Pipe\\"; + pipe_path.append(name); + + // Always open for overlapped i/o. We implement blocking manually in Read and + // Write. + DWORD read_mode = FILE_FLAG_OVERLAPPED; + m_read = ::CreateNamedPipeA( + pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, + PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL); + if (INVALID_HANDLE_VALUE == m_read) + return Error(::GetLastError(), eErrorTypeWin32); + m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + + // Open the write end of the pipe. + Error result = OpenNamedPipe(name, child_process_inherit, false); + if (!result.Success()) { + CloseReadFileDescriptor(); return result; + } + + return result; } -Error -PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name) -{ - llvm::SmallString<128> pipe_name; - Error error; - ::UUID unique_id; - RPC_CSTR unique_string; - RPC_STATUS status = ::UuidCreate(&unique_id); - if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) - status = ::UuidToStringA(&unique_id, &unique_string); - if (status == RPC_S_OK) - { - pipe_name = prefix; - pipe_name += "-"; - pipe_name += reinterpret_cast<char *>(unique_string); - ::RpcStringFreeA(&unique_string); - error = CreateNew(pipe_name, child_process_inherit); - } - else - { - error.SetError(status, eErrorTypeWin32); - } - if (error.Success()) - name = pipe_name; - return error; +Error PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, + bool child_process_inherit, + llvm::SmallVectorImpl<char> &name) { + llvm::SmallString<128> pipe_name; + Error error; + ::UUID unique_id; + RPC_CSTR unique_string; + RPC_STATUS status = ::UuidCreate(&unique_id); + if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) + status = ::UuidToStringA(&unique_id, &unique_string); + if (status == RPC_S_OK) { + pipe_name = prefix; + pipe_name += "-"; + pipe_name += reinterpret_cast<char *>(unique_string); + ::RpcStringFreeA(&unique_string); + error = CreateNew(pipe_name, child_process_inherit); + } else { + error.SetError(status, eErrorTypeWin32); + } + if (error.Success()) + name = pipe_name; + return error; } -Error -PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); +Error PipeWindows::OpenAsReader(llvm::StringRef name, + bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - return OpenNamedPipe(name, child_process_inherit, true); + return OpenNamedPipe(name, child_process_inherit, true); } -Error -PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) -{ - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); +Error PipeWindows::OpenAsWriterWithTimeout( + llvm::StringRef name, bool child_process_inherit, + const std::chrono::microseconds &timeout) { + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - return OpenNamedPipe(name, child_process_inherit, false); + return OpenNamedPipe(name, child_process_inherit, false); } -Error -PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, bool is_read) -{ - if (name.empty()) - return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); +Error PipeWindows::OpenNamedPipe(llvm::StringRef name, + bool child_process_inherit, bool is_read) { + if (name.empty()) + return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); - assert(is_read ? !CanRead() : !CanWrite()); + assert(is_read ? !CanRead() : !CanWrite()); - SECURITY_ATTRIBUTES attributes = {0}; - attributes.bInheritHandle = child_process_inherit; + SECURITY_ATTRIBUTES attributes = {0}; + attributes.bInheritHandle = child_process_inherit; - std::string pipe_path = "\\\\.\\Pipe\\"; - pipe_path.append(name); + std::string pipe_path = "\\\\.\\Pipe\\"; + pipe_path.append(name); - if (is_read) - { - m_read = - ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == m_read) - return Error(::GetLastError(), eErrorTypeWin32); + if (is_read) { + m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == m_read) + return Error(::GetLastError(), eErrorTypeWin32); - m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); + m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - else - { - m_write = - ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == m_write) - return Error(::GetLastError(), eErrorTypeWin32); + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + } else { + m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == m_write) + return Error(::GetLastError(), eErrorTypeWin32); - m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); + m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); - } + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + } - return Error(); + return Error(); } -int -PipeWindows::GetReadFileDescriptor() const -{ - return m_read_fd; -} +int PipeWindows::GetReadFileDescriptor() const { return m_read_fd; } -int -PipeWindows::GetWriteFileDescriptor() const -{ - return m_write_fd; -} +int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; } -int -PipeWindows::ReleaseReadFileDescriptor() -{ - if (!CanRead()) - return -1; - int result = m_read_fd; - m_read_fd = -1; - if (m_read_overlapped.hEvent) - ::CloseHandle(m_read_overlapped.hEvent); - m_read = INVALID_HANDLE_VALUE; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - return result; +int PipeWindows::ReleaseReadFileDescriptor() { + if (!CanRead()) + return -1; + int result = m_read_fd; + m_read_fd = -1; + if (m_read_overlapped.hEvent) + ::CloseHandle(m_read_overlapped.hEvent); + m_read = INVALID_HANDLE_VALUE; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + return result; } -int -PipeWindows::ReleaseWriteFileDescriptor() -{ - if (!CanWrite()) - return -1; - int result = m_write_fd; - m_write_fd = -1; - m_write = INVALID_HANDLE_VALUE; - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); - return result; +int PipeWindows::ReleaseWriteFileDescriptor() { + if (!CanWrite()) + return -1; + int result = m_write_fd; + m_write_fd = -1; + m_write = INVALID_HANDLE_VALUE; + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + return result; } -void -PipeWindows::CloseReadFileDescriptor() -{ - if (!CanRead()) - return; - - if (m_read_overlapped.hEvent) - ::CloseHandle(m_read_overlapped.hEvent); - _close(m_read_fd); - m_read = INVALID_HANDLE_VALUE; - m_read_fd = -1; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); +void PipeWindows::CloseReadFileDescriptor() { + if (!CanRead()) + return; + + if (m_read_overlapped.hEvent) + ::CloseHandle(m_read_overlapped.hEvent); + _close(m_read_fd); + m_read = INVALID_HANDLE_VALUE; + m_read_fd = -1; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); } -void -PipeWindows::CloseWriteFileDescriptor() -{ - if (!CanWrite()) - return; +void PipeWindows::CloseWriteFileDescriptor() { + if (!CanWrite()) + return; - _close(m_write_fd); - m_write = INVALID_HANDLE_VALUE; - m_write_fd = -1; - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + _close(m_write_fd); + m_write = INVALID_HANDLE_VALUE; + m_write_fd = -1; + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } -void -PipeWindows::Close() -{ - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); +void PipeWindows::Close() { + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); } -Error -PipeWindows::Delete(llvm::StringRef name) -{ - return Error(); -} +Error PipeWindows::Delete(llvm::StringRef name) { return Error(); } -bool -PipeWindows::CanRead() const -{ - return (m_read != INVALID_HANDLE_VALUE); -} +bool PipeWindows::CanRead() const { return (m_read != INVALID_HANDLE_VALUE); } -bool -PipeWindows::CanWrite() const -{ - return (m_write != INVALID_HANDLE_VALUE); -} +bool PipeWindows::CanWrite() const { return (m_write != INVALID_HANDLE_VALUE); } HANDLE -PipeWindows::GetReadNativeHandle() -{ - return m_read; -} +PipeWindows::GetReadNativeHandle() { return m_read; } HANDLE -PipeWindows::GetWriteNativeHandle() -{ - return m_write; -} - -Error -PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read) -{ - if (!CanRead()) - return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - bytes_read = 0; - DWORD sys_bytes_read = size; - BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, &m_read_overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) - return Error(::GetLastError(), eErrorTypeWin32); - - DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; - DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); - if (wait_result != WAIT_OBJECT_0) - { - // The operation probably failed. However, if it timed out, we need to cancel the I/O. - // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx, - // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. - // If that happens, the original operation should be considered to have been successful. - bool failed = true; - DWORD failure_error = ::GetLastError(); - if (wait_result == WAIT_TIMEOUT) - { - BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); - if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) - failed = false; - } - if (failed) - return Error(failure_error, eErrorTypeWin32); +PipeWindows::GetWriteNativeHandle() { return m_write; } + +Error PipeWindows::ReadWithTimeout(void *buf, size_t size, + const std::chrono::microseconds &duration, + size_t &bytes_read) { + if (!CanRead()) + return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + bytes_read = 0; + DWORD sys_bytes_read = size; + BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, + &m_read_overlapped); + if (!result && GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); + + DWORD timeout = (duration == std::chrono::microseconds::zero()) + ? INFINITE + : duration.count() * 1000; + DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); + if (wait_result != WAIT_OBJECT_0) { + // The operation probably failed. However, if it timed out, we need to + // cancel the I/O. + // Between the time we returned from WaitForSingleObject and the time we + // call CancelIoEx, + // the operation may complete. If that hapens, CancelIoEx will fail and + // return ERROR_NOT_FOUND. + // If that happens, the original operation should be considered to have been + // successful. + bool failed = true; + DWORD failure_error = ::GetLastError(); + if (wait_result == WAIT_TIMEOUT) { + BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); + if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) + failed = false; } - - // Now we call GetOverlappedResult setting bWait to false, since we've already waited - // as long as we're willing to. - if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) - return Error(::GetLastError(), eErrorTypeWin32); - - bytes_read = sys_bytes_read; - return Error(); + if (failed) + return Error(failure_error, eErrorTypeWin32); + } + + // Now we call GetOverlappedResult setting bWait to false, since we've already + // waited + // as long as we're willing to. + if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) + return Error(::GetLastError(), eErrorTypeWin32); + + bytes_read = sys_bytes_read; + return Error(); } -Error -PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) -{ - if (!CanWrite()) - return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - DWORD sys_bytes_written = 0; - BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, &m_write_overlapped); - if (!write_result && GetLastError() != ERROR_IO_PENDING) - return Error(::GetLastError(), eErrorTypeWin32); - - BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE); - if (!result) - return Error(::GetLastError(), eErrorTypeWin32); - return Error(); +Error PipeWindows::Write(const void *buf, size_t num_bytes, + size_t &bytes_written) { + if (!CanWrite()) + return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + DWORD sys_bytes_written = 0; + BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, + &m_write_overlapped); + if (!write_result && GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); + + BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, + &sys_bytes_written, TRUE); + if (!result) + return Error(::GetLastError(), eErrorTypeWin32); + return Error(); } diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp index caf0fc71e12..ef3656af41f 100644 --- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp +++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostProcess.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" +#include "lldb/Host/HostProcess.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "llvm/ADT/SmallVector.h" @@ -20,127 +20,130 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -void -CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) -{ - if (env.GetArgumentCount() == 0) - return; - - // Environment buffer is a null terminated list of null terminated strings - for (int i = 0; i < env.GetArgumentCount(); ++i) - { - std::wstring warg; - if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) - { - buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1)); - } +namespace { +void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) { + if (env.GetArgumentCount() == 0) + return; + + // Environment buffer is a null terminated list of null terminated strings + for (int i = 0; i < env.GetArgumentCount(); ++i) { + std::wstring warg; + if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) { + buffer.insert(buffer.end(), (char *)warg.c_str(), + (char *)(warg.c_str() + warg.size() + 1)); } - // One null wchar_t (to end the block) is two null bytes - buffer.push_back(0); - buffer.push_back(0); + } + // One null wchar_t (to end the block) is two null bytes + buffer.push_back(0); + buffer.push_back(0); } } HostProcess -ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - error.Clear(); - - std::string executable; - std::string commandLine; - std::vector<char> environment; - STARTUPINFO startupinfo = {0}; - PROCESS_INFORMATION pi = {0}; - - HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); - HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); - HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); - - startupinfo.cb = sizeof(startupinfo); - startupinfo.dwFlags |= STARTF_USESTDHANDLES; - startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); - startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); - startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); - - const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); - if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true")) - { - startupinfo.dwFlags |= STARTF_USESHOWWINDOW; - startupinfo.wShowWindow = SW_HIDE; - } - - DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; - if (launch_info.GetFlags().Test(eLaunchFlagDebug)) - flags |= DEBUG_ONLY_THIS_PROCESS; - - auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); - LPVOID env_block = nullptr; - ::CreateEnvironmentBuffer(env, environment); - if (!environment.empty()) - env_block = environment.data(); - - executable = launch_info.GetExecutableFile().GetPath(); - launch_info.GetArguments().GetQuotedCommandString(commandLine); - - std::wstring wexecutable, wcommandLine, wworkingDirectory; - llvm::ConvertUTF8toWide(executable, wexecutable); - llvm::ConvertUTF8toWide(commandLine, wcommandLine); - llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory); - - wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it - BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, - wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi); - if (result) - { - // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. - ::CloseHandle(pi.hThread); - } - - if (stdin_handle) - ::CloseHandle(stdin_handle); - if (stdout_handle) - ::CloseHandle(stdout_handle); - if (stderr_handle) - ::CloseHandle(stderr_handle); - - if (!result) - error.SetError(::GetLastError(), eErrorTypeWin32); - return HostProcess(pi.hProcess); +ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + error.Clear(); + + std::string executable; + std::string commandLine; + std::vector<char> environment; + STARTUPINFO startupinfo = {0}; + PROCESS_INFORMATION pi = {0}; + + HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); + HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); + HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); + + startupinfo.cb = sizeof(startupinfo); + startupinfo.dwFlags |= STARTF_USESTDHANDLES; + startupinfo.hStdError = + stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); + startupinfo.hStdInput = + stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); + startupinfo.hStdOutput = + stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); + + const char *hide_console_var = + getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); + if (hide_console_var && + llvm::StringRef(hide_console_var).equals_lower("true")) { + startupinfo.dwFlags |= STARTF_USESHOWWINDOW; + startupinfo.wShowWindow = SW_HIDE; + } + + DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= DEBUG_ONLY_THIS_PROCESS; + + auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); + LPVOID env_block = nullptr; + ::CreateEnvironmentBuffer(env, environment); + if (!environment.empty()) + env_block = environment.data(); + + executable = launch_info.GetExecutableFile().GetPath(); + launch_info.GetArguments().GetQuotedCommandString(commandLine); + + std::wstring wexecutable, wcommandLine, wworkingDirectory; + llvm::ConvertUTF8toWide(executable, wexecutable); + llvm::ConvertUTF8toWide(commandLine, wcommandLine); + llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), + wworkingDirectory); + + wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because + // CreateProcessW can modify it + BOOL result = ::CreateProcessW( + wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, + wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), + &startupinfo, &pi); + if (result) { + // Do not call CloseHandle on pi.hProcess, since we want to pass that back + // through the HostProcess. + ::CloseHandle(pi.hThread); + } + + if (stdin_handle) + ::CloseHandle(stdin_handle); + if (stdout_handle) + ::CloseHandle(stdout_handle); + if (stderr_handle) + ::CloseHandle(stderr_handle); + + if (!result) + error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(pi.hProcess); } HANDLE -ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) -{ - const FileAction *action = launch_info.GetFileActionForFD(fd); - if (action == nullptr) - return NULL; - SECURITY_ATTRIBUTES secattr = {0}; - secattr.nLength = sizeof(SECURITY_ATTRIBUTES); - secattr.bInheritHandle = TRUE; - - const char *path = action->GetPath(); - DWORD access = 0; - DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - DWORD create = 0; - DWORD flags = 0; - if (fd == STDIN_FILENO) - { - access = GENERIC_READ; - create = OPEN_EXISTING; - flags = FILE_ATTRIBUTE_READONLY; - } - if (fd == STDOUT_FILENO || fd == STDERR_FILENO) - { - access = GENERIC_WRITE; - create = CREATE_ALWAYS; - if (fd == STDERR_FILENO) - flags = FILE_FLAG_WRITE_THROUGH; - } - - std::wstring wpath; - llvm::ConvertUTF8toWide(path, wpath); - HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL); - return (result == INVALID_HANDLE_VALUE) ? NULL : result; +ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, + int fd) { + const FileAction *action = launch_info.GetFileActionForFD(fd); + if (action == nullptr) + return NULL; + SECURITY_ATTRIBUTES secattr = {0}; + secattr.nLength = sizeof(SECURITY_ATTRIBUTES); + secattr.bInheritHandle = TRUE; + + const char *path = action->GetPath(); + DWORD access = 0; + DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + DWORD create = 0; + DWORD flags = 0; + if (fd == STDIN_FILENO) { + access = GENERIC_READ; + create = OPEN_EXISTING; + flags = FILE_ATTRIBUTE_READONLY; + } + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + access = GENERIC_WRITE; + create = CREATE_ALWAYS; + if (fd == STDERR_FILENO) + flags = FILE_FLAG_WRITE_THROUGH; + } + + std::wstring wpath; + llvm::ConvertUTF8toWide(path, wpath); + HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, + flags, NULL); + return (result == INVALID_HANDLE_VALUE) ? NULL : result; } diff --git a/lldb/source/Host/windows/ProcessRunLock.cpp b/lldb/source/Host/windows/ProcessRunLock.cpp index 1f21552a306..590007b3479 100644 --- a/lldb/source/Host/windows/ProcessRunLock.cpp +++ b/lldb/source/Host/windows/ProcessRunLock.cpp @@ -1,106 +1,83 @@ #include "lldb/Host/ProcessRunLock.h" #include "lldb/Host/windows/windows.h" -namespace -{ +namespace { #if defined(__MINGW32__) // Taken from WinNT.h -typedef struct _RTL_SRWLOCK { - PVOID Ptr; -} RTL_SRWLOCK, *PRTL_SRWLOCK; +typedef struct _RTL_SRWLOCK { PVOID Ptr; } RTL_SRWLOCK, *PRTL_SRWLOCK; // Taken from WinBase.h typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; #endif } - -static PSRWLOCK GetLock(lldb::rwlock_t lock) -{ - return static_cast<PSRWLOCK>(lock); +static PSRWLOCK GetLock(lldb::rwlock_t lock) { + return static_cast<PSRWLOCK>(lock); } -static bool ReadLock(lldb::rwlock_t rwlock) -{ - ::AcquireSRWLockShared(GetLock(rwlock)); - return true; +static bool ReadLock(lldb::rwlock_t rwlock) { + ::AcquireSRWLockShared(GetLock(rwlock)); + return true; } -static bool ReadUnlock(lldb::rwlock_t rwlock) -{ - ::ReleaseSRWLockShared(GetLock(rwlock)); - return true; +static bool ReadUnlock(lldb::rwlock_t rwlock) { + ::ReleaseSRWLockShared(GetLock(rwlock)); + return true; } -static bool WriteLock(lldb::rwlock_t rwlock) -{ - ::AcquireSRWLockExclusive(GetLock(rwlock)); - return true; +static bool WriteLock(lldb::rwlock_t rwlock) { + ::AcquireSRWLockExclusive(GetLock(rwlock)); + return true; } -static bool WriteTryLock(lldb::rwlock_t rwlock) -{ - return !!::TryAcquireSRWLockExclusive(GetLock(rwlock)); +static bool WriteTryLock(lldb::rwlock_t rwlock) { + return !!::TryAcquireSRWLockExclusive(GetLock(rwlock)); } -static bool WriteUnlock(lldb::rwlock_t rwlock) -{ - ::ReleaseSRWLockExclusive(GetLock(rwlock)); - return true; +static bool WriteUnlock(lldb::rwlock_t rwlock) { + ::ReleaseSRWLockExclusive(GetLock(rwlock)); + return true; } using namespace lldb_private; -ProcessRunLock::ProcessRunLock() - : m_running(false) -{ - m_rwlock = new SRWLOCK; - InitializeSRWLock(GetLock(m_rwlock)); +ProcessRunLock::ProcessRunLock() : m_running(false) { + m_rwlock = new SRWLOCK; + InitializeSRWLock(GetLock(m_rwlock)); } -ProcessRunLock::~ProcessRunLock() -{ - delete m_rwlock; -} +ProcessRunLock::~ProcessRunLock() { delete m_rwlock; } -bool ProcessRunLock::ReadTryLock() -{ - ::ReadLock(m_rwlock); - if (m_running == false) - return true; - ::ReadUnlock(m_rwlock); - return false; +bool ProcessRunLock::ReadTryLock() { + ::ReadLock(m_rwlock); + if (m_running == false) + return true; + ::ReadUnlock(m_rwlock); + return false; } -bool ProcessRunLock::ReadUnlock() -{ - return ::ReadUnlock(m_rwlock); +bool ProcessRunLock::ReadUnlock() { return ::ReadUnlock(m_rwlock); } + +bool ProcessRunLock::SetRunning() { + WriteLock(m_rwlock); + m_running = true; + WriteUnlock(m_rwlock); + return true; } -bool ProcessRunLock::SetRunning () -{ - WriteLock(m_rwlock); +bool ProcessRunLock::TrySetRunning() { + if (WriteTryLock(m_rwlock)) { + bool was_running = m_running; m_running = true; WriteUnlock(m_rwlock); - return true; -} - -bool ProcessRunLock::TrySetRunning () -{ - if (WriteTryLock(m_rwlock)) - { - bool was_running = m_running; - m_running = true; - WriteUnlock(m_rwlock); - return !was_running; - } - return false; + return !was_running; + } + return false; } -bool ProcessRunLock::SetStopped () -{ - WriteLock(m_rwlock); - m_running = false; - WriteUnlock(m_rwlock); - return true; +bool ProcessRunLock::SetStopped() { + WriteLock(m_rwlock); + m_running = false; + WriteUnlock(m_rwlock); + return true; } diff --git a/lldb/source/Host/windows/ThisThread.cpp b/lldb/source/Host/windows/ThisThread.cpp index bcd5b8d1c1d..8db12f05b0b 100644 --- a/lldb/source/Host/windows/ThisThread.cpp +++ b/lldb/source/Host/windows/ThisThread.cpp @@ -9,8 +9,8 @@ #include "lldb/Core/Error.h" -#include "lldb/Host/windows/windows.h" #include "lldb/Host/ThisThread.h" +#include "lldb/Host/windows/windows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -20,47 +20,44 @@ using namespace lldb_private; #if defined(_MSC_VER) && !defined(__clang__) -namespace -{ +namespace { static const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push, 8) -struct THREADNAME_INFO -{ - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to thread name - DWORD dwThreadId; // Thread ID (-1 == current thread) - DWORD dwFlags; // Reserved. Do not use. +struct THREADNAME_INFO { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to thread name + DWORD dwThreadId; // Thread ID (-1 == current thread) + DWORD dwFlags; // Reserved. Do not use. }; #pragma pack(pop) } #endif -void -ThisThread::SetName(llvm::StringRef name) -{ -// Other compilers don't yet support SEH, so we can only set the thread if compiling with MSVC. +void ThisThread::SetName(llvm::StringRef name) { +// Other compilers don't yet support SEH, so we can only set the thread if +// compiling with MSVC. // TODO(zturner): Once clang-cl supports SEH, relax this conditional. #if defined(_MSC_VER) && !defined(__clang__) - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name.data(); - info.dwThreadId = ::GetCurrentThreadId(); - info.dwFlags = 0; - - __try { - ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); - } - __except(EXCEPTION_EXECUTE_HANDLER) {} + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name.data(); + info.dwThreadId = ::GetCurrentThreadId(); + info.dwFlags = 0; + + __try { + ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } #endif } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ - // Getting the thread name is not supported on Windows. - // TODO(zturner): In SetName(), make a TLS entry that contains the thread's name, and in this function - // try to extract that TLS entry. - name.clear(); +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { + // Getting the thread name is not supported on Windows. + // TODO(zturner): In SetName(), make a TLS entry that contains the thread's + // name, and in this function + // try to extract that TLS entry. + name.clear(); } diff --git a/lldb/source/Host/windows/Windows.cpp b/lldb/source/Host/windows/Windows.cpp index a1ee5d6e313..8347b82f272 100644 --- a/lldb/source/Host/windows/Windows.cpp +++ b/lldb/source/Host/windows/Windows.cpp @@ -9,276 +9,253 @@ // This file provides Windows support functions -#include "lldb/Host/windows/windows.h" #include "lldb/Host/PosixApi.h" +#include "lldb/Host/windows/windows.h" #include "llvm/Support/ConvertUTF.h" #include <assert.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> -#include <io.h> #include <cerrno> #include <ctype.h> +#include <io.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> -// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors -extern "C" -{ - char *_getcwd(char *buffer, int maxlen); - int _chdir(const char *path); +// These prototypes are defined in <direct.h>, but it also defines chdir() and +// getcwd(), giving multiply defined errors +extern "C" { +char *_getcwd(char *buffer, int maxlen); +int _chdir(const char *path); } -namespace -{ -bool -utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) -{ - const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8); - size_t sourceLen = strlen(utf8) + 1 /* convert null too */; - UTF16 *target = reinterpret_cast<UTF16 *>(buf); - ConversionFlags flags = strictConversion; - return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK; +namespace { +bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) { + const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8); + size_t sourceLen = strlen(utf8) + 1 /* convert null too */; + UTF16 *target = reinterpret_cast<UTF16 *>(buf); + ConversionFlags flags = strictConversion; + return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, + target + bufSize, flags) == conversionOK; } -bool -wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) -{ - const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide); - size_t sourceLen = wcslen(wide) + 1 /* convert null too */; - UTF8 *target = reinterpret_cast<UTF8 *>(buf); - ConversionFlags flags = strictConversion; - return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK; +bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) { + const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide); + size_t sourceLen = wcslen(wide) + 1 /* convert null too */; + UTF8 *target = reinterpret_cast<UTF8 *>(buf); + ConversionFlags flags = strictConversion; + return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, + target + bufSize, flags) == conversionOK; } } -int vasprintf(char **ret, const char *fmt, va_list ap) -{ - char *buf; - int len; - size_t buflen; - va_list ap2; +int vasprintf(char **ret, const char *fmt, va_list ap) { + char *buf; + int len; + size_t buflen; + va_list ap2; #if defined(_MSC_VER) || defined(__MINGW64) - ap2 = ap; - len = _vscprintf(fmt, ap2); + ap2 = ap; + len = _vscprintf(fmt, ap2); #else - va_copy(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); + va_copy(ap2, ap); + len = vsnprintf(NULL, 0, fmt, ap2); #endif - if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; + if (len >= 0 && + (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; } -char* strcasestr(const char *s, const char* find) -{ - char c, sc; - size_t len; - - if ((c = *find++) != 0) { - c = tolower((unsigned char) c); - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return 0; - } while ((char) tolower((unsigned char) sc) != c); - } while (strncasecmp(s, find, len) != 0); - s--; - } - return ((char *) s); +char *strcasestr(const char *s, const char *find) { + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return 0; + } while ((char)tolower((unsigned char)sc) != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); } -char* realpath(const char * name, char * resolved) -{ - char *retname = NULL; - - /* SUSv3 says we must set `errno = EINVAL', and return NULL, - * if `name' is passed as a NULL pointer. - */ - if (name == NULL) - { - errno = EINVAL; - return NULL; - } +char *realpath(const char *name, char *resolved) { + char *retname = NULL; - /* Otherwise, `name' must refer to a readable filesystem object, - * if we are going to resolve its absolute path name. - */ - wchar_t wideNameBuffer[PATH_MAX]; - wchar_t *wideName = wideNameBuffer; - if (!utf8ToWide(name, wideName, PATH_MAX)) - { - errno = EINVAL; - return NULL; - } + /* SUSv3 says we must set `errno = EINVAL', and return NULL, + * if `name' is passed as a NULL pointer. + */ + if (name == NULL) { + errno = EINVAL; + return NULL; + } + + /* Otherwise, `name' must refer to a readable filesystem object, + * if we are going to resolve its absolute path name. + */ + wchar_t wideNameBuffer[PATH_MAX]; + wchar_t *wideName = wideNameBuffer; + if (!utf8ToWide(name, wideName, PATH_MAX)) { + errno = EINVAL; + return NULL; + } - if (_waccess(wideName, 4) != 0) - return NULL; + if (_waccess(wideName, 4) != 0) + return NULL; - /* If `name' didn't point to an existing entity, - * then we don't get to here; we simply fall past this block, - * returning NULL, with `errno' appropriately set by `access'. + /* If `name' didn't point to an existing entity, + * then we don't get to here; we simply fall past this block, + * returning NULL, with `errno' appropriately set by `access'. + * + * When we _do_ get to here, then we can use `_fullpath' to + * resolve the full path for `name' into `resolved', but first, + * check that we have a suitable buffer, in which to return it. + */ + + if ((retname = resolved) == NULL) { + /* Caller didn't give us a buffer, so we'll exercise the + * option granted by SUSv3, and allocate one. * - * When we _do_ get to here, then we can use `_fullpath' to - * resolve the full path for `name' into `resolved', but first, - * check that we have a suitable buffer, in which to return it. + * `_fullpath' would do this for us, but it uses `malloc', and + * Microsoft's implementation doesn't set `errno' on failure. + * If we don't do this explicitly ourselves, then we will not + * know if `_fullpath' fails on `malloc' failure, or for some + * other reason, and we want to set `errno = ENOMEM' for the + * `malloc' failure case. */ - if ((retname = resolved) == NULL) - { - /* Caller didn't give us a buffer, so we'll exercise the - * option granted by SUSv3, and allocate one. - * - * `_fullpath' would do this for us, but it uses `malloc', and - * Microsoft's implementation doesn't set `errno' on failure. - * If we don't do this explicitly ourselves, then we will not - * know if `_fullpath' fails on `malloc' failure, or for some - * other reason, and we want to set `errno = ENOMEM' for the - * `malloc' failure case. - */ - - retname = (char *)malloc(PATH_MAX); - if (retname == NULL) - { - errno = ENOMEM; - return NULL; - } + retname = (char *)malloc(PATH_MAX); + if (retname == NULL) { + errno = ENOMEM; + return NULL; } + } - /* Otherwise, when we do have a valid buffer, - * `_fullpath' should only fail if the path name is too long. - */ + /* Otherwise, when we do have a valid buffer, + * `_fullpath' should only fail if the path name is too long. + */ - wchar_t wideFullPathBuffer[PATH_MAX]; - wchar_t *wideFullPath; - if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL) - { - errno = ENAMETOOLONG; - return NULL; - } + wchar_t wideFullPathBuffer[PATH_MAX]; + wchar_t *wideFullPath; + if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == + NULL) { + errno = ENAMETOOLONG; + return NULL; + } - // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS - // FIXME: Check for failure - size_t initialLength = wcslen(wideFullPath); - GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX); - GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1); + // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS + // FIXME: Check for failure + size_t initialLength = wcslen(wideFullPath); + GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX); + GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1); - // Convert back to UTF-8 - if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) - { - errno = EINVAL; - return NULL; - } + // Convert back to UTF-8 + if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) { + errno = EINVAL; + return NULL; + } - // Force drive to be upper case - if (retname[1] == ':') - retname[0] = toupper(retname[0]); + // Force drive to be upper case + if (retname[1] == ':') + retname[0] = toupper(retname[0]); - return retname; + return retname; } #ifdef _MSC_VER -char* basename(char *path) -{ - char* l1 = strrchr(path, '\\'); - char* l2 = strrchr(path, '/'); - if (l2 > l1) l1 = l2; - if (!l1) return path; // no base name - return &l1[1]; +char *basename(char *path) { + char *l1 = strrchr(path, '\\'); + char *l2 = strrchr(path, '/'); + if (l2 > l1) + l1 = l2; + if (!l1) + return path; // no base name + return &l1[1]; } // use _getcwd() instead of GetCurrentDirectory() because it updates errno -char* getcwd(char* path, int max) -{ - assert(path == NULL || max <= PATH_MAX); - wchar_t wpath[PATH_MAX]; - if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) - { - // Caller is allowed to pass in NULL for `path`. - // In that case, we're supposed to allocate a - // buffer on the caller's behalf. - if (path == NULL) - { - max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1; - path = (char *)malloc(max); - if (path == NULL) - { - errno = ENOMEM; - return NULL; - } - } - if (wideToUtf8(wresult, path, max)) - return path; +char *getcwd(char *path, int max) { + assert(path == NULL || max <= PATH_MAX); + wchar_t wpath[PATH_MAX]; + if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) { + // Caller is allowed to pass in NULL for `path`. + // In that case, we're supposed to allocate a + // buffer on the caller's behalf. + if (path == NULL) { + max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1; + path = (char *)malloc(max); + if (path == NULL) { + errno = ENOMEM; + return NULL; + } } - return NULL; + if (wideToUtf8(wresult, path, max)) + return path; + } + return NULL; } // use _chdir() instead of SetCurrentDirectory() because it updates errno -int chdir(const char* path) -{ - return _chdir(path); -} - -char *dirname(char *path) -{ - char* l1 = strrchr(path, '\\'); - char* l2 = strrchr(path, '/'); - if (l2 > l1) l1 = l2; - if (!l1) return NULL; // no dir name - *l1 = 0; - return path; +int chdir(const char *path) { return _chdir(path); } + +char *dirname(char *path) { + char *l1 = strrchr(path, '\\'); + char *l2 = strrchr(path, '/'); + if (l2 > l1) + l1 = l2; + if (!l1) + return NULL; // no dir name + *l1 = 0; + return path; } -int strcasecmp(const char* s1, const char* s2) -{ - return stricmp(s1, s2); -} +int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); } -int strncasecmp(const char* s1, const char* s2, size_t n) -{ - return strnicmp(s1, s2, n); +int strncasecmp(const char *s1, const char *s2, size_t n) { + return strnicmp(s1, s2, n); } -int usleep(uint32_t useconds) -{ - Sleep(useconds / 1000); - return 0; +int usleep(uint32_t useconds) { + Sleep(useconds / 1000); + return 0; } #if _MSC_VER < 1900 namespace lldb_private { -int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) -{ - int old_errno = errno; - int r = ::vsnprintf(buffer, count, format, argptr); - int new_errno = errno; - buffer[count-1] = '\0'; - if (r == -1 || r == count) - { - FILE *nul = fopen("nul", "w"); - int bytes_written = ::vfprintf(nul, format, argptr); - fclose(nul); - if (bytes_written < count) - errno = new_errno; - else - { - errno = old_errno; - r = bytes_written; - } +int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) { + int old_errno = errno; + int r = ::vsnprintf(buffer, count, format, argptr); + int new_errno = errno; + buffer[count - 1] = '\0'; + if (r == -1 || r == count) { + FILE *nul = fopen("nul", "w"); + int bytes_written = ::vfprintf(nul, format, argptr); + fclose(nul); + if (bytes_written < count) + errno = new_errno; + else { + errno = old_errno; + r = bytes_written; } - return r; + } + return r; } } // namespace lldb_private #endif |