From b9c1b51e45b845debb76d8658edabca70ca56079 Mon Sep 17 00:00:00 2001 From: Kate Stone Date: Tue, 6 Sep 2016 20:57:50 +0000 Subject: *** This commit represents a complete reformatting of the LLDB source code *** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751 --- lldb/source/Host/android/HostInfoAndroid.cpp | 145 +- lldb/source/Host/android/LibcGlue.cpp | 14 +- lldb/source/Host/common/Editline.cpp | 2392 +++++++++---------- lldb/source/Host/common/File.cpp | 1633 ++++++------- lldb/source/Host/common/FileCache.cpp | 183 +- lldb/source/Host/common/FileSpec.cpp | 2393 +++++++++----------- lldb/source/Host/common/FileSystem.cpp | 131 +- lldb/source/Host/common/GetOptInc.cpp | 708 +++--- lldb/source/Host/common/Host.cpp | 1531 ++++++------- lldb/source/Host/common/HostInfoBase.cpp | 665 +++--- lldb/source/Host/common/HostNativeThreadBase.cpp | 73 +- lldb/source/Host/common/HostProcess.cpp | 51 +- lldb/source/Host/common/HostThread.cpp | 65 +- lldb/source/Host/common/LockFileBase.cpp | 136 +- .../Host/common/MonitoringProcessLauncher.cpp | 116 +- lldb/source/Host/common/NativeBreakpoint.cpp | 159 +- lldb/source/Host/common/NativeBreakpointList.cpp | 349 +-- lldb/source/Host/common/NativeProcessProtocol.cpp | 681 +++--- lldb/source/Host/common/NativeRegisterContext.cpp | 662 +++--- .../common/NativeRegisterContextRegisterInfo.cpp | 49 +- lldb/source/Host/common/NativeThreadProtocol.cpp | 79 +- lldb/source/Host/common/NativeWatchpointList.cpp | 24 +- lldb/source/Host/common/OptionParser.cpp | 135 +- lldb/source/Host/common/PipeBase.cpp | 15 +- lldb/source/Host/common/ProcessRunLock.cpp | 102 +- lldb/source/Host/common/Socket.cpp | 660 +++--- lldb/source/Host/common/SocketAddress.cpp | 440 ++-- lldb/source/Host/common/SoftwareBreakpoint.cpp | 558 ++--- lldb/source/Host/common/StringConvert.cpp | 169 +- lldb/source/Host/common/Symbols.cpp | 465 ++-- lldb/source/Host/common/TCPSocket.cpp | 391 ++-- lldb/source/Host/common/Terminal.cpp | 332 ++- lldb/source/Host/common/ThisThread.cpp | 58 +- lldb/source/Host/common/ThreadLauncher.cpp | 100 +- lldb/source/Host/common/TimeValue.cpp | 195 +- lldb/source/Host/common/UDPSocket.cpp | 193 +- lldb/source/Host/common/XML.cpp | 944 ++++---- lldb/source/Host/freebsd/Host.cpp | 418 ++-- lldb/source/Host/freebsd/HostInfoFreeBSD.cpp | 100 +- lldb/source/Host/freebsd/HostThreadFreeBSD.cpp | 77 +- lldb/source/Host/freebsd/ThisThread.cpp | 24 +- lldb/source/Host/linux/AbstractSocket.cpp | 15 +- lldb/source/Host/linux/Host.cpp | 608 +++-- lldb/source/Host/linux/HostInfoLinux.cpp | 403 ++-- lldb/source/Host/linux/HostThreadLinux.cpp | 43 +- lldb/source/Host/linux/LibcGlue.cpp | 27 +- lldb/source/Host/linux/ProcessLauncherLinux.cpp | 330 +-- lldb/source/Host/linux/ThisThread.cpp | 14 +- lldb/source/Host/macosx/Host.mm | 2336 +++++++++---------- lldb/source/Host/macosx/HostInfoMacOSX.mm | 519 ++--- lldb/source/Host/macosx/HostThreadMacOSX.mm | 78 +- lldb/source/Host/macosx/Symbols.cpp | 1040 +++++---- lldb/source/Host/macosx/ThisThread.cpp | 16 +- lldb/source/Host/macosx/cfcpp/CFCBundle.cpp | 112 +- lldb/source/Host/macosx/cfcpp/CFCBundle.h | 38 +- lldb/source/Host/macosx/cfcpp/CFCData.cpp | 78 +- lldb/source/Host/macosx/cfcpp/CFCData.h | 30 +- lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp | 214 +- lldb/source/Host/macosx/cfcpp/CFCMutableArray.h | 47 +- .../Host/macosx/cfcpp/CFCMutableDictionary.cpp | 856 ++++--- .../Host/macosx/cfcpp/CFCMutableDictionary.h | 108 +- lldb/source/Host/macosx/cfcpp/CFCMutableSet.cpp | 115 +- lldb/source/Host/macosx/cfcpp/CFCMutableSet.h | 58 +- lldb/source/Host/macosx/cfcpp/CFCReleaser.h | 218 +- lldb/source/Host/macosx/cfcpp/CFCString.cpp | 230 +- lldb/source/Host/macosx/cfcpp/CFCString.h | 40 +- lldb/source/Host/macosx/cfcpp/CoreFoundationCPP.h | 4 +- lldb/source/Host/netbsd/Host.cpp | 393 ++-- lldb/source/Host/netbsd/HostInfoNetBSD.cpp | 142 +- lldb/source/Host/netbsd/HostThreadNetBSD.cpp | 27 +- lldb/source/Host/netbsd/ThisThread.cpp | 14 +- .../Host/posix/ConnectionFileDescriptorPosix.cpp | 1316 ++++++----- lldb/source/Host/posix/DomainSocket.cpp | 141 +- lldb/source/Host/posix/FileSystem.cpp | 401 ++-- lldb/source/Host/posix/HostInfoPosix.cpp | 309 ++- lldb/source/Host/posix/HostProcessPosix.cpp | 122 +- lldb/source/Host/posix/HostThreadPosix.cpp | 83 +- lldb/source/Host/posix/LockFilePosix.cpp | 69 +- lldb/source/Host/posix/MainLoopPosix.cpp | 286 ++- lldb/source/Host/posix/PipePosix.cpp | 479 ++-- lldb/source/Host/posix/ProcessLauncherPosix.cpp | 21 +- .../Host/windows/ConnectionGenericFileWindows.cpp | 560 +++-- lldb/source/Host/windows/EditLineWin.cpp | 621 +++-- lldb/source/Host/windows/FileSystem.cpp | 418 ++-- lldb/source/Host/windows/Host.cpp | 503 ++-- lldb/source/Host/windows/HostInfoWindows.cpp | 171 +- lldb/source/Host/windows/HostProcessWindows.cpp | 164 +- lldb/source/Host/windows/HostThreadWindows.cpp | 103 +- lldb/source/Host/windows/LockFileWindows.cpp | 91 +- lldb/source/Host/windows/PipeWindows.cpp | 477 ++-- .../source/Host/windows/ProcessLauncherWindows.cpp | 235 +- lldb/source/Host/windows/ProcessRunLock.cpp | 115 +- lldb/source/Host/windows/ThisThread.cpp | 57 +- lldb/source/Host/windows/Windows.cpp | 401 ++-- 94 files changed, 15128 insertions(+), 17783 deletions(-) (limited to 'lldb/source/Host') diff --git a/lldb/source/Host/android/HostInfoAndroid.cpp b/lldb/source/Host/android/HostInfoAndroid.cpp index 3fa50ec8ddf..27ce17a76d7 100644 --- a/lldb/source/Host/android/HostInfoAndroid.cpp +++ b/lldb/source/Host/android/HostInfoAndroid.cpp @@ -15,90 +15,79 @@ using namespace lldb_private; using namespace llvm; -void -HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); - - if (arch_32.IsValid()) - { - arch_32.GetTriple().setEnvironment(llvm::Triple::Android); - } - if (arch_64.IsValid()) - { - arch_64.GetTriple().setEnvironment(llvm::Triple::Android); - } +void HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); + + if (arch_32.IsValid()) { + arch_32.GetTriple().setEnvironment(llvm::Triple::Android); + } + if (arch_64.IsValid()) { + arch_64.GetTriple().setEnvironment(llvm::Triple::Android); + } } -FileSpec -HostInfoAndroid::GetDefaultShell() -{ - return FileSpec("/system/bin/sh", false); +FileSpec HostInfoAndroid::GetDefaultShell() { + return FileSpec("/system/bin/sh", false); } -FileSpec -HostInfoAndroid::ResolveLibraryPath(const std::string& module_path, const ArchSpec& arch) -{ - static const char* const ld_library_path_separator = ":"; - static const char* const default_lib32_path[] = { - "/vendor/lib", - "/system/lib", - nullptr - }; - static const char* const default_lib64_path[] = { - "/vendor/lib64", - "/system/lib64", - nullptr - }; - - if (module_path.empty() || module_path[0] == '/') - return FileSpec(module_path.c_str(), true); - - SmallVector ld_paths; - - if (const char* ld_library_path = ::getenv("LD_LIBRARY_PATH")) - StringRef(ld_library_path).split(ld_paths, StringRef(ld_library_path_separator), -1, false); - - const char* const* default_lib_path = nullptr; - switch (arch.GetAddressByteSize()) - { - case 4: - default_lib_path = default_lib32_path; - break; - case 8: - default_lib_path = default_lib64_path; - break; - default: - assert(false && "Unknown address byte size"); - return FileSpec(); - } - - for(const char* const* it = default_lib_path; *it; ++it) - ld_paths.push_back(StringRef(*it)); - - for (const StringRef& path : ld_paths) - { - FileSpec file_candidate(path.str().c_str(), true); - file_candidate.AppendPathComponent(module_path.c_str()); - - if (file_candidate.Exists()) - return file_candidate; - } - +FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path, + const ArchSpec &arch) { + static const char *const ld_library_path_separator = ":"; + static const char *const default_lib32_path[] = {"/vendor/lib", "/system/lib", + nullptr}; + static const char *const default_lib64_path[] = {"/vendor/lib64", + "/system/lib64", nullptr}; + + if (module_path.empty() || module_path[0] == '/') + return FileSpec(module_path.c_str(), true); + + SmallVector ld_paths; + + if (const char *ld_library_path = ::getenv("LD_LIBRARY_PATH")) + StringRef(ld_library_path) + .split(ld_paths, StringRef(ld_library_path_separator), -1, false); + + const char *const *default_lib_path = nullptr; + switch (arch.GetAddressByteSize()) { + case 4: + default_lib_path = default_lib32_path; + break; + case 8: + default_lib_path = default_lib64_path; + break; + default: + assert(false && "Unknown address byte size"); return FileSpec(); -} + } + + for (const char *const *it = default_lib_path; *it; ++it) + ld_paths.push_back(StringRef(*it)); -bool -HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) -{ - bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + for (const StringRef &path : ld_paths) { + FileSpec file_candidate(path.str().c_str(), true); + file_candidate.AppendPathComponent(module_path.c_str()); - // On Android, there is no path which is guaranteed to be writable. If the user has not - // provided a path via an environment variable, the generic algorithm will deduce /tmp, which - // is plain wrong. In that case we have an invalid directory, we substitute the path with - // /data/local/tmp, which is correct at least in some cases (i.e., when running as shell user). - if (!success || !file_spec.Exists()) - file_spec = FileSpec("/data/local/tmp", false); + if (file_candidate.Exists()) + return file_candidate; + } + + return FileSpec(); +} - return file_spec.Exists(); +bool HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + + // On Android, there is no path which is guaranteed to be writable. If the + // user has not + // provided a path via an environment variable, the generic algorithm will + // deduce /tmp, which + // is plain wrong. In that case we have an invalid directory, we substitute + // the path with + // /data/local/tmp, which is correct at least in some cases (i.e., when + // running as shell user). + if (!success || !file_spec.Exists()) + file_spec = FileSpec("/data/local/tmp", false); + + return file_spec.Exists(); } diff --git a/lldb/source/Host/android/LibcGlue.cpp b/lldb/source/Host/android/LibcGlue.cpp index 091c11d1553..13437f9704e 100644 --- a/lldb/source/Host/android/LibcGlue.cpp +++ b/lldb/source/Host/android/LibcGlue.cpp @@ -15,21 +15,15 @@ #if __ANDROID_API__ < 21 -#include -#include #include #include +#include +#include #include "lldb/Host/Time.h" -time_t timegm(struct tm* t) -{ - return (time_t) timegm64(t); -} +time_t timegm(struct tm *t) { return (time_t)timegm64(t); } -int posix_openpt(int flags) -{ - return open("/dev/ptmx", flags); -} +int posix_openpt(int flags) { return open("/dev/ptmx", flags); } #endif diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index d23a481d168..6e12bfb8972 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -11,11 +11,11 @@ #include #include -#include "lldb/Host/Editline.h" -#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Core/Error.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/StringList.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/Editline.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -34,14 +34,17 @@ using namespace lldb_private::line_editor; // the function declaraction has been hoisted here. #if defined(__APPLE__) extern "C" { - int setupterm(char *term, int fildes, int *errret); +int setupterm(char *term, int fildes, int *errret); } #define USE_SETUPTERM_WORKAROUND #endif -// Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text -// with a single line editor. Preserving this illusion requires fairly careful management of cursor -// state. Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(), +// Editline uses careful cursor management to achieve the illusion of editing a +// multi-line block of text +// with a single line editor. Preserving this illusion requires fairly careful +// management of cursor +// state. Read and understand the relationship between DisplayInput(), +// MoveCursor(), SetCurrentLine(), // and SaveEditedLine() before making changes. #define ESCAPE "\x1b" @@ -63,7 +66,8 @@ extern "C" { #define EditLineConstString(str) str #define EditLineStringFormatSpec "%s" -// use #defines so wide version functions and structs will resolve to old versions +// use #defines so wide version functions and structs will resolve to old +// versions // for case of libedit not built with wide char support #define history_w history #define history_winit history_init @@ -76,1430 +80,1290 @@ extern "C" { #define el_wgetc el_getc #define el_wpush el_push #define el_wparse el_parse -#define el_wset el_set -#define el_wget el_get +#define el_wset el_set +#define el_wget el_get #define el_wline el_line #define el_winsertstr el_insertstr -#define el_wdeletestr el_deletestr +#define el_wdeletestr el_deletestr #endif // #if LLDB_EDITLINE_USE_WCHAR -bool -IsOnlySpaces (const EditLineStringType & content) -{ - for (wchar_t ch : content) - { - if (ch != EditLineCharType(' ')) - return false; - } - return true; +bool IsOnlySpaces(const EditLineStringType &content) { + for (wchar_t ch : content) { + if (ch != EditLineCharType(' ')) + return false; + } + return true; } -EditLineStringType -CombineLines (const std::vector & lines) -{ - EditLineStringStreamType combined_stream; - for (EditLineStringType line : lines) - { - combined_stream << line.c_str() << "\n"; - } - return combined_stream.str(); +EditLineStringType CombineLines(const std::vector &lines) { + EditLineStringStreamType combined_stream; + for (EditLineStringType line : lines) { + combined_stream << line.c_str() << "\n"; + } + return combined_stream.str(); } -std::vector -SplitLines (const EditLineStringType & input) -{ - std::vector result; - size_t start = 0; - while (start < input.length()) - { - size_t end = input.find ('\n', start); - if (end == std::string::npos) - { - result.insert (result.end(), input.substr (start)); - break; - } - result.insert (result.end(), input.substr (start, end - start)); - start = end + 1; +std::vector SplitLines(const EditLineStringType &input) { + std::vector result; + size_t start = 0; + while (start < input.length()) { + size_t end = input.find('\n', start); + if (end == std::string::npos) { + result.insert(result.end(), input.substr(start)); + break; } - return result; + result.insert(result.end(), input.substr(start, end - start)); + start = end + 1; + } + return result; } -EditLineStringType -FixIndentation (const EditLineStringType & line, int indent_correction) -{ - if (indent_correction == 0) - return line; - if (indent_correction < 0) - return line.substr (-indent_correction); - return EditLineStringType (indent_correction, EditLineCharType(' ')) + line; +EditLineStringType FixIndentation(const EditLineStringType &line, + int indent_correction) { + if (indent_correction == 0) + return line; + if (indent_correction < 0) + return line.substr(-indent_correction); + return EditLineStringType(indent_correction, EditLineCharType(' ')) + line; } -int -GetIndentation (const EditLineStringType & line) -{ - int space_count = 0; - for (EditLineCharType ch : line) - { - if (ch != EditLineCharType(' ')) - break; - ++space_count; - } - return space_count; +int GetIndentation(const EditLineStringType &line) { + int space_count = 0; + for (EditLineCharType ch : line) { + if (ch != EditLineCharType(' ')) + break; + ++space_count; + } + return space_count; } -bool -IsInputPending (FILE * file) -{ - // FIXME: This will be broken on Windows if we ever re-enable Editline. You can't use select - // on something that isn't a socket. This will have to be re-written to not use a FILE*, but - // instead use some kind of yet-to-be-created abstraction that select-like functionality on - // non-socket objects. - const int fd = fileno (file); - SelectHelper select_helper; - select_helper.SetTimeout(std::chrono::microseconds(0)); - select_helper.FDSetRead(fd); - return select_helper.Select().Success(); +bool IsInputPending(FILE *file) { + // FIXME: This will be broken on Windows if we ever re-enable Editline. You + // can't use select + // on something that isn't a socket. This will have to be re-written to not + // use a FILE*, but + // instead use some kind of yet-to-be-created abstraction that select-like + // functionality on + // non-socket objects. + const int fd = fileno(file); + SelectHelper select_helper; + select_helper.SetTimeout(std::chrono::microseconds(0)); + select_helper.FDSetRead(fd); + return select_helper.Select().Success(); } -namespace lldb_private -{ - namespace line_editor - { - typedef std::weak_ptr EditlineHistoryWP; - - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. - - class EditlineHistory - { - private: - // Use static GetHistory() function to get a EditlineHistorySP to one of these objects - EditlineHistory (const std::string &prefix, uint32_t size, bool unique_entries) : - m_history (NULL), - m_event (), - m_prefix (prefix), - m_path () - { - m_history = history_winit(); - history_w (m_history, &m_event, H_SETSIZE, size); - if (unique_entries) - history_w (m_history, &m_event, H_SETUNIQUE, 1); - } - - const char * - GetHistoryFilePath() - { - if (m_path.empty() && m_history && !m_prefix.empty()) - { - FileSpec parent_path{"~/.lldb", true}; - char history_path[PATH_MAX]; - if (FileSystem::MakeDirectory(parent_path, lldb::eFilePermissionsDirectoryDefault).Success()) - { - snprintf (history_path, sizeof (history_path), "~/.lldb/%s-history", m_prefix.c_str()); - } - else - { - snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str()); - } - m_path = FileSpec (history_path, true).GetPath(); - } - if (m_path.empty()) - return NULL; - return m_path.c_str(); - } - - public: - - ~EditlineHistory() - { - Save(); - - if (m_history) - { - history_wend (m_history); - m_history = NULL; - } - } - - static EditlineHistorySP - GetHistory (const std::string &prefix) - { - typedef std::map WeakHistoryMap; - static std::recursive_mutex g_mutex; - static WeakHistoryMap g_weak_map; - std::lock_guard guard(g_mutex); - WeakHistoryMap::const_iterator pos = g_weak_map.find (prefix); - EditlineHistorySP history_sp; - if (pos != g_weak_map.end()) - { - history_sp = pos->second.lock(); - if (history_sp) - return history_sp; - g_weak_map.erase (pos); - } - history_sp.reset (new EditlineHistory (prefix, 800, true)); - g_weak_map[prefix] = history_sp; - return history_sp; - } - - bool IsValid() const - { - return m_history != NULL; - } - - HistoryW * - GetHistoryPtr () - { - return m_history; - } - - void - Enter (const EditLineCharType *line_cstr) - { - if (m_history) - history_w (m_history, &m_event, H_ENTER, line_cstr); - } - - bool - Load () - { - if (m_history) - { - const char *path = GetHistoryFilePath(); - if (path) - { - history_w (m_history, &m_event, H_LOAD, path); - return true; - } - } - return false; - } - - bool - Save () - { - if (m_history) - { - const char *path = GetHistoryFilePath(); - if (path) - { - history_w (m_history, &m_event, H_SAVE, path); - return true; - } - } - return false; - } - - protected: - HistoryW * m_history; // The history object - HistEventW m_event; // The history event needed to contain all history events - std::string m_prefix; // The prefix name (usually the editline program name) to use when loading/saving history - std::string m_path; // Path to the history file - }; +namespace lldb_private { +namespace line_editor { +typedef std::weak_ptr EditlineHistoryWP; + +// EditlineHistory objects are sometimes shared between multiple +// Editline instances with the same program name. + +class EditlineHistory { +private: + // Use static GetHistory() function to get a EditlineHistorySP to one of these + // objects + EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) + : m_history(NULL), m_event(), m_prefix(prefix), m_path() { + m_history = history_winit(); + history_w(m_history, &m_event, H_SETSIZE, size); + if (unique_entries) + history_w(m_history, &m_event, H_SETUNIQUE, 1); + } + + const char *GetHistoryFilePath() { + if (m_path.empty() && m_history && !m_prefix.empty()) { + FileSpec parent_path{"~/.lldb", true}; + char history_path[PATH_MAX]; + if (FileSystem::MakeDirectory(parent_path, + lldb::eFilePermissionsDirectoryDefault) + .Success()) { + snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history", + m_prefix.c_str()); + } else { + snprintf(history_path, sizeof(history_path), "~/%s-widehistory", + m_prefix.c_str()); + } + m_path = FileSpec(history_path, true).GetPath(); + } + if (m_path.empty()) + return NULL; + return m_path.c_str(); + } + +public: + ~EditlineHistory() { + Save(); + + if (m_history) { + history_wend(m_history); + m_history = NULL; + } + } + + static EditlineHistorySP GetHistory(const std::string &prefix) { + typedef std::map WeakHistoryMap; + static std::recursive_mutex g_mutex; + static WeakHistoryMap g_weak_map; + std::lock_guard guard(g_mutex); + WeakHistoryMap::const_iterator pos = g_weak_map.find(prefix); + EditlineHistorySP history_sp; + if (pos != g_weak_map.end()) { + history_sp = pos->second.lock(); + if (history_sp) + return history_sp; + g_weak_map.erase(pos); + } + history_sp.reset(new EditlineHistory(prefix, 800, true)); + g_weak_map[prefix] = history_sp; + return history_sp; + } + + bool IsValid() const { return m_history != NULL; } + + HistoryW *GetHistoryPtr() { return m_history; } + + void Enter(const EditLineCharType *line_cstr) { + if (m_history) + history_w(m_history, &m_event, H_ENTER, line_cstr); + } + + bool Load() { + if (m_history) { + const char *path = GetHistoryFilePath(); + if (path) { + history_w(m_history, &m_event, H_LOAD, path); + return true; + } + } + return false; + } + + bool Save() { + if (m_history) { + const char *path = GetHistoryFilePath(); + if (path) { + history_w(m_history, &m_event, H_SAVE, path); + return true; + } } + return false; + } + +protected: + HistoryW *m_history; // The history object + HistEventW m_event; // The history event needed to contain all history events + std::string m_prefix; // The prefix name (usually the editline program name) + // to use when loading/saving history + std::string m_path; // Path to the history file +}; +} } //------------------------------------------------------------------ // Editline private methods //------------------------------------------------------------------ -void -Editline::SetBaseLineNumber (int line_number) -{ - std::stringstream line_number_stream; - line_number_stream << line_number; - m_base_line_number = line_number; - m_line_number_digits = std::max (3, (int)line_number_stream.str().length() + 1); +void Editline::SetBaseLineNumber(int line_number) { + std::stringstream line_number_stream; + line_number_stream << line_number; + m_base_line_number = line_number; + m_line_number_digits = + std::max(3, (int)line_number_stream.str().length() + 1); } -std::string -Editline::PromptForIndex (int line_index) -{ - bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; - std::string prompt = m_set_prompt; - if (use_line_numbers && prompt.length() == 0) - { - prompt = ": "; - } - std::string continuation_prompt = prompt; - if (m_set_continuation_prompt.length() > 0) - { - continuation_prompt = m_set_continuation_prompt; - - // Ensure that both prompts are the same length through space padding - while (continuation_prompt.length() < prompt.length()) - { - continuation_prompt += ' '; - } - while (prompt.length() < continuation_prompt.length()) - { - prompt += ' '; - } +std::string Editline::PromptForIndex(int line_index) { + bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; + std::string prompt = m_set_prompt; + if (use_line_numbers && prompt.length() == 0) { + prompt = ": "; + } + std::string continuation_prompt = prompt; + if (m_set_continuation_prompt.length() > 0) { + continuation_prompt = m_set_continuation_prompt; + + // Ensure that both prompts are the same length through space padding + while (continuation_prompt.length() < prompt.length()) { + continuation_prompt += ' '; } - - if (use_line_numbers) - { - StreamString prompt_stream; - prompt_stream.Printf("%*d%s", m_line_number_digits, m_base_line_number + line_index, - (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); - return std::move (prompt_stream.GetString()); + while (prompt.length() < continuation_prompt.length()) { + prompt += ' '; } - return (line_index == 0) ? prompt : continuation_prompt; + } + + if (use_line_numbers) { + StreamString prompt_stream; + prompt_stream.Printf( + "%*d%s", m_line_number_digits, m_base_line_number + line_index, + (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); + return std::move(prompt_stream.GetString()); + } + return (line_index == 0) ? prompt : continuation_prompt; } -void -Editline::SetCurrentLine (int line_index) -{ - m_current_line_index = line_index; - m_current_prompt = PromptForIndex (line_index); +void Editline::SetCurrentLine(int line_index) { + m_current_line_index = line_index; + m_current_prompt = PromptForIndex(line_index); } -int -Editline::GetPromptWidth() -{ - return (int)PromptForIndex (0).length(); -} +int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); } -bool -Editline::IsEmacs() -{ - const char * editor; - el_get (m_editline, EL_EDITOR, &editor); - return editor[0] == 'e'; +bool Editline::IsEmacs() { + const char *editor; + el_get(m_editline, EL_EDITOR, &editor); + return editor[0] == 'e'; } -bool -Editline::IsOnlySpaces() -{ - const LineInfoW * info = el_wline (m_editline); - for (const EditLineCharType * character = info->buffer; character < info->lastchar; character++) - { - if (*character != ' ') - return false; - } - return true; +bool Editline::IsOnlySpaces() { + const LineInfoW *info = el_wline(m_editline); + for (const EditLineCharType *character = info->buffer; + character < info->lastchar; character++) { + if (*character != ' ') + return false; + } + return true; } -int -Editline::GetLineIndexForLocation (CursorLocation location, int cursor_row) -{ - int line = 0; - if (location == CursorLocation::EditingPrompt || location == CursorLocation::BlockEnd || - location == CursorLocation::EditingCursor) - { - for (unsigned index = 0; index < m_current_line_index; index++) - { - line += CountRowsForLine (m_input_lines[index]); - } - if (location == CursorLocation::EditingCursor) - { - line += cursor_row; - } - else if (location == CursorLocation::BlockEnd) - { - for (unsigned index = m_current_line_index; index < m_input_lines.size(); index++) - { - line += CountRowsForLine (m_input_lines[index]); - } - --line; - } +int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) { + int line = 0; + if (location == CursorLocation::EditingPrompt || + location == CursorLocation::BlockEnd || + location == CursorLocation::EditingCursor) { + for (unsigned index = 0; index < m_current_line_index; index++) { + line += CountRowsForLine(m_input_lines[index]); } - return line; -} - -void -Editline::MoveCursor (CursorLocation from, CursorLocation to) -{ - const LineInfoW * info = el_wline (m_editline); - int editline_cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); - int editline_cursor_row = editline_cursor_position / m_terminal_width; - - // Determine relative starting and ending lines - int fromLine = GetLineIndexForLocation (from, editline_cursor_row); - int toLine = GetLineIndexForLocation (to, editline_cursor_row); - if (toLine != fromLine) - { - fprintf (m_output_file, (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, std::abs (toLine - fromLine)); + if (location == CursorLocation::EditingCursor) { + line += cursor_row; + } else if (location == CursorLocation::BlockEnd) { + for (unsigned index = m_current_line_index; index < m_input_lines.size(); + index++) { + line += CountRowsForLine(m_input_lines[index]); + } + --line; } - - // Determine target column - int toColumn = 1; - if (to == CursorLocation::EditingCursor) - { - toColumn = editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; - } - else if (to == CursorLocation::BlockEnd) - { - toColumn = ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 80) + 1; - } - fprintf (m_output_file, ANSI_SET_COLUMN_N, toColumn); + } + return line; } -void -Editline::DisplayInput (int firstIndex) -{ - fprintf (m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); - int line_count = (int)m_input_lines.size(); - const char *faint = m_color_prompts ? ANSI_FAINT : ""; - const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; - - for (int index = firstIndex; index < line_count; index++) - { - fprintf (m_output_file, "%s" "%s" "%s" EditLineStringFormatSpec " ", - faint, - PromptForIndex (index).c_str(), - unfaint, - m_input_lines[index].c_str()); - if (index < line_count - 1) - fprintf (m_output_file, "\n"); - } +void Editline::MoveCursor(CursorLocation from, CursorLocation to) { + const LineInfoW *info = el_wline(m_editline); + int editline_cursor_position = + (int)((info->cursor - info->buffer) + GetPromptWidth()); + int editline_cursor_row = editline_cursor_position / m_terminal_width; + + // Determine relative starting and ending lines + int fromLine = GetLineIndexForLocation(from, editline_cursor_row); + int toLine = GetLineIndexForLocation(to, editline_cursor_row); + if (toLine != fromLine) { + fprintf(m_output_file, + (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, + std::abs(toLine - fromLine)); + } + + // Determine target column + int toColumn = 1; + if (to == CursorLocation::EditingCursor) { + toColumn = + editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; + } else if (to == CursorLocation::BlockEnd) { + toColumn = + ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % + 80) + + 1; + } + fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn); } +void Editline::DisplayInput(int firstIndex) { + fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); + int line_count = (int)m_input_lines.size(); + const char *faint = m_color_prompts ? ANSI_FAINT : ""; + const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; + + for (int index = firstIndex; index < line_count; index++) { + fprintf(m_output_file, "%s" + "%s" + "%s" EditLineStringFormatSpec " ", + faint, PromptForIndex(index).c_str(), unfaint, + m_input_lines[index].c_str()); + if (index < line_count - 1) + fprintf(m_output_file, "\n"); + } +} -int -Editline::CountRowsForLine (const EditLineStringType & content) -{ - auto prompt = PromptForIndex (0); // Prompt width is constant during an edit session - int line_length = (int)(content.length() + prompt.length()); - return (line_length / m_terminal_width) + 1; +int Editline::CountRowsForLine(const EditLineStringType &content) { + auto prompt = + PromptForIndex(0); // Prompt width is constant during an edit session + int line_length = (int)(content.length() + prompt.length()); + return (line_length / m_terminal_width) + 1; } -void -Editline::SaveEditedLine() -{ - const LineInfoW * info = el_wline (m_editline); - m_input_lines[m_current_line_index] = EditLineStringType (info->buffer, info->lastchar - info->buffer); +void Editline::SaveEditedLine() { + const LineInfoW *info = el_wline(m_editline); + m_input_lines[m_current_line_index] = + EditLineStringType(info->buffer, info->lastchar - info->buffer); } -StringList -Editline::GetInputAsStringList(int line_count) -{ - StringList lines; - for (EditLineStringType line : m_input_lines) - { - if (line_count == 0) - break; +StringList Editline::GetInputAsStringList(int line_count) { + StringList lines; + for (EditLineStringType line : m_input_lines) { + if (line_count == 0) + break; #if LLDB_EDITLINE_USE_WCHAR - lines.AppendString (m_utf8conv.to_bytes (line)); + lines.AppendString(m_utf8conv.to_bytes(line)); #else - lines.AppendString(line); + lines.AppendString(line); #endif - --line_count; - } - return lines; + --line_count; + } + return lines; } -unsigned char -Editline::RecallHistory (bool earlier) -{ - if (!m_history_sp || !m_history_sp->IsValid()) +unsigned char Editline::RecallHistory(bool earlier) { + if (!m_history_sp || !m_history_sp->IsValid()) + return CC_ERROR; + + HistoryW *pHistory = m_history_sp->GetHistoryPtr(); + HistEventW history_event; + std::vector new_input_lines; + + // Treat moving from the "live" entry differently + if (!m_in_history) { + if (earlier == false) + return CC_ERROR; // Can't go newer than the "live" entry + if (history_w(pHistory, &history_event, H_FIRST) == -1) + return CC_ERROR; + + // Save any edits to the "live" entry in case we return by moving forward in + // history + // (it would be more bash-like to save over any current entry, but libedit + // doesn't + // offer the ability to add entries anywhere except the end.) + SaveEditedLine(); + m_live_history_lines = m_input_lines; + m_in_history = true; + } else { + if (history_w(pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) { + // Can't move earlier than the earliest entry + if (earlier) return CC_ERROR; - - HistoryW * pHistory = m_history_sp->GetHistoryPtr(); - HistEventW history_event; - std::vector new_input_lines; - - // Treat moving from the "live" entry differently - if (!m_in_history) - { - if (earlier == false) - return CC_ERROR; // Can't go newer than the "live" entry - if (history_w (pHistory, &history_event, H_FIRST) == -1) - return CC_ERROR; - - // Save any edits to the "live" entry in case we return by moving forward in history - // (it would be more bash-like to save over any current entry, but libedit doesn't - // offer the ability to add entries anywhere except the end.) - SaveEditedLine(); - m_live_history_lines = m_input_lines; - m_in_history = true; - } - else - { - if (history_w (pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) - { - // Can't move earlier than the earliest entry - if (earlier) - return CC_ERROR; - - // ... but moving to newer than the newest yields the "live" entry - new_input_lines = m_live_history_lines; - m_in_history = false; - } + + // ... but moving to newer than the newest yields the "live" entry + new_input_lines = m_live_history_lines; + m_in_history = false; } - - // If we're pulling the lines from history, split them apart - if (m_in_history) - new_input_lines = SplitLines (history_event.str); - - // Erase the current edit session and replace it with a new one - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); - m_input_lines = new_input_lines; - DisplayInput(); - - // Prepare to edit the last line when moving to previous entry, or the first line - // when moving to next entry - SetCurrentLine (m_current_line_index = earlier ? (int)m_input_lines.size() - 1 : 0); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; + } + + // If we're pulling the lines from history, split them apart + if (m_in_history) + new_input_lines = SplitLines(history_event.str); + + // Erase the current edit session and replace it with a new one + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + m_input_lines = new_input_lines; + DisplayInput(); + + // Prepare to edit the last line when moving to previous entry, or the first + // line + // when moving to next entry + SetCurrentLine(m_current_line_index = + earlier ? (int)m_input_lines.size() - 1 : 0); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -int -Editline::GetCharacter (EditLineCharType * c) -{ - const LineInfoW * info = el_wline (m_editline); - - // Paint a faint version of the desired prompt over the version libedit draws - // (will only be requested if colors are supported) - if (m_needs_prompt_repaint) - { - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - fprintf (m_output_file, "%s" "%s" "%s", ANSI_FAINT, Prompt(), ANSI_UNFAINT); - MoveCursor (CursorLocation::EditingPrompt, CursorLocation::EditingCursor); - m_needs_prompt_repaint = false; +int Editline::GetCharacter(EditLineCharType *c) { + const LineInfoW *info = el_wline(m_editline); + + // Paint a faint version of the desired prompt over the version libedit draws + // (will only be requested if colors are supported) + if (m_needs_prompt_repaint) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + fprintf(m_output_file, "%s" + "%s" + "%s", + ANSI_FAINT, Prompt(), ANSI_UNFAINT); + MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor); + m_needs_prompt_repaint = false; + } + + if (m_multiline_enabled) { + // Detect when the number of rows used for this input line changes due to an + // edit + int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); + int new_line_rows = (lineLength / m_terminal_width) + 1; + if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) { + // Respond by repainting the current state from this line on + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + SaveEditedLine(); + DisplayInput(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); } - - if (m_multiline_enabled) - { - // Detect when the number of rows used for this input line changes due to an edit - int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); - int new_line_rows = (lineLength / m_terminal_width) + 1; - if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) - { - // Respond by repainting the current state from this line on - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - SaveEditedLine(); - DisplayInput (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); - } - m_current_line_rows = new_line_rows; + m_current_line_rows = new_line_rows; + } + + // Read an actual character + while (true) { + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char ch = 0; + + // This mutex is locked by our caller (GetLine). Unlock it while we read a + // character + // (blocking operation), so we do not hold the mutex indefinitely. This + // gives a chance + // for someone to interrupt us. After Read returns, immediately lock the + // mutex again and + // check if we were interrupted. + m_output_mutex.unlock(); + int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); + m_output_mutex.lock(); + if (m_editor_status == EditorStatus::Interrupted) { + while (read_count > 0 && status == lldb::eConnectionStatusSuccess) + read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); + lldbassert(status == lldb::eConnectionStatusInterrupted); + return 0; } - - // Read an actual character - while (true) - { - lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; - char ch = 0; - - // This mutex is locked by our caller (GetLine). Unlock it while we read a character - // (blocking operation), so we do not hold the mutex indefinitely. This gives a chance - // for someone to interrupt us. After Read returns, immediately lock the mutex again and - // check if we were interrupted. - m_output_mutex.unlock(); - int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); - m_output_mutex.lock(); - if (m_editor_status == EditorStatus::Interrupted) - { - while (read_count > 0 && status == lldb::eConnectionStatusSuccess) - read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); - lldbassert(status == lldb::eConnectionStatusInterrupted); - return 0; - } - if (read_count) - { + if (read_count) { #if LLDB_EDITLINE_USE_WCHAR - // After the initial interruptible read, this is guaranteed not to block - ungetc (ch, m_input_file); - *c = fgetwc (m_input_file); - if (*c != WEOF) - return 1; + // After the initial interruptible read, this is guaranteed not to block + ungetc(ch, m_input_file); + *c = fgetwc(m_input_file); + if (*c != WEOF) + return 1; #else - *c = ch; - if(ch != (char)EOF) - return 1; + *c = ch; + if (ch != (char)EOF) + return 1; #endif - } - else - { - switch (status) - { - case lldb::eConnectionStatusSuccess: // Success - break; - - case lldb::eConnectionStatusInterrupted: - lldbassert(0 && "Interrupts should have been handled above."); - - case lldb::eConnectionStatusError: // Check GetError() for details - case lldb::eConnectionStatusTimedOut: // Request timed out - case lldb::eConnectionStatusEndOfFile: // End-of-file encountered - case lldb::eConnectionStatusNoConnection: // No connection - case lldb::eConnectionStatusLostConnection: // Lost connection while connected to a valid connection - m_editor_status = EditorStatus::EndOfInput; - return 0; - } - } + } else { + switch (status) { + case lldb::eConnectionStatusSuccess: // Success + break; + + case lldb::eConnectionStatusInterrupted: + lldbassert(0 && "Interrupts should have been handled above."); + + case lldb::eConnectionStatusError: // Check GetError() for details + case lldb::eConnectionStatusTimedOut: // Request timed out + case lldb::eConnectionStatusEndOfFile: // End-of-file encountered + case lldb::eConnectionStatusNoConnection: // No connection + case lldb::eConnectionStatusLostConnection: // Lost connection while + // connected to a valid + // connection + m_editor_status = EditorStatus::EndOfInput; + return 0; + } } + } } -const char * -Editline::Prompt() -{ - if (m_color_prompts) - m_needs_prompt_repaint = true; - return m_current_prompt.c_str(); +const char *Editline::Prompt() { + if (m_color_prompts) + m_needs_prompt_repaint = true; + return m_current_prompt.c_str(); } -unsigned char -Editline::BreakLineCommand (int ch) -{ - // Preserve any content beyond the cursor, truncate and save the current line - const LineInfoW * info = el_wline (m_editline); - auto current_line = EditLineStringType (info->buffer, info->cursor - info->buffer); - auto new_line_fragment = EditLineStringType (info->cursor, info->lastchar - info->cursor); - m_input_lines[m_current_line_index] = current_line; - - // Ignore whitespace-only extra fragments when breaking a line - if (::IsOnlySpaces (new_line_fragment)) - new_line_fragment = EditLineConstString(""); - - // Establish the new cursor position at the start of a line when inserting a line break - m_revert_cursor_index = 0; - - // Don't perform automatic formatting when pasting - if (!IsInputPending (m_input_file)) - { - // Apply smart indentation - if (m_fix_indentation_callback) - { - StringList lines = GetInputAsStringList (m_current_line_index + 1); +unsigned char Editline::BreakLineCommand(int ch) { + // Preserve any content beyond the cursor, truncate and save the current line + const LineInfoW *info = el_wline(m_editline); + auto current_line = + EditLineStringType(info->buffer, info->cursor - info->buffer); + auto new_line_fragment = + EditLineStringType(info->cursor, info->lastchar - info->cursor); + m_input_lines[m_current_line_index] = current_line; + + // Ignore whitespace-only extra fragments when breaking a line + if (::IsOnlySpaces(new_line_fragment)) + new_line_fragment = EditLineConstString(""); + + // Establish the new cursor position at the start of a line when inserting a + // line break + m_revert_cursor_index = 0; + + // Don't perform automatic formatting when pasting + if (!IsInputPending(m_input_file)) { + // Apply smart indentation + if (m_fix_indentation_callback) { + StringList lines = GetInputAsStringList(m_current_line_index + 1); #if LLDB_EDITLINE_USE_WCHAR - lines.AppendString (m_utf8conv.to_bytes (new_line_fragment)); + lines.AppendString(m_utf8conv.to_bytes(new_line_fragment)); #else - lines.AppendString (new_line_fragment); + lines.AppendString(new_line_fragment); #endif - - int indent_correction = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); - new_line_fragment = FixIndentation(new_line_fragment, indent_correction); - m_revert_cursor_index = GetIndentation(new_line_fragment); - } + + int indent_correction = m_fix_indentation_callback( + this, lines, 0, m_fix_indentation_callback_baton); + new_line_fragment = FixIndentation(new_line_fragment, indent_correction); + m_revert_cursor_index = GetIndentation(new_line_fragment); } - - // Insert the new line and repaint everything from the split line on down - m_input_lines.insert (m_input_lines.begin() + m_current_line_index + 1, new_line_fragment); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - DisplayInput (m_current_line_index); - - // Reposition the cursor to the right line and prepare to edit the new line - SetCurrentLine (m_current_line_index + 1); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; + } + + // Insert the new line and repaint everything from the split line on down + m_input_lines.insert(m_input_lines.begin() + m_current_line_index + 1, + new_line_fragment); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput(m_current_line_index); + + // Reposition the cursor to the right line and prepare to edit the new line + SetCurrentLine(m_current_line_index + 1); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -unsigned char -Editline::EndOrAddLineCommand(int ch) -{ - // Don't perform end of input detection when pasting, always treat this as a line break - if (IsInputPending(m_input_file)) - { +unsigned char Editline::EndOrAddLineCommand(int ch) { + // Don't perform end of input detection when pasting, always treat this as a + // line break + if (IsInputPending(m_input_file)) { + return BreakLineCommand(ch); + } + + // Save any edits to this line + SaveEditedLine(); + + // If this is the end of the last line, consider whether to add a line instead + const LineInfoW *info = el_wline(m_editline); + if (m_current_line_index == m_input_lines.size() - 1 && + info->cursor == info->lastchar) { + if (m_is_input_complete_callback) { + auto lines = GetInputAsStringList(); + if (!m_is_input_complete_callback(this, lines, + m_is_input_complete_callback_baton)) { return BreakLineCommand(ch); - } - - // Save any edits to this line - SaveEditedLine(); + } - // If this is the end of the last line, consider whether to add a line instead - const LineInfoW *info = el_wline(m_editline); - if (m_current_line_index == m_input_lines.size() - 1 && info->cursor == info->lastchar) - { - if (m_is_input_complete_callback) - { - auto lines = GetInputAsStringList(); - if (!m_is_input_complete_callback(this, lines, m_is_input_complete_callback_baton)) - { - return BreakLineCommand(ch); - } - - // The completion test is allowed to change the input lines when complete - m_input_lines.clear(); - for (unsigned index = 0; index < lines.GetSize(); index++) - { + // The completion test is allowed to change the input lines when complete + m_input_lines.clear(); + for (unsigned index = 0; index < lines.GetSize(); index++) { #if LLDB_EDITLINE_USE_WCHAR - m_input_lines.insert(m_input_lines.end(), m_utf8conv.from_bytes(lines[index])); + m_input_lines.insert(m_input_lines.end(), + m_utf8conv.from_bytes(lines[index])); #else - m_input_lines.insert(m_input_lines.end(), lines[index]); + m_input_lines.insert(m_input_lines.end(), lines[index]); #endif - } - } + } } - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); - fprintf(m_output_file, "\n"); - m_editor_status = EditorStatus::Complete; - return CC_NEWLINE; + } + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); + fprintf(m_output_file, "\n"); + m_editor_status = EditorStatus::Complete; + return CC_NEWLINE; } -unsigned char -Editline::DeleteNextCharCommand(int ch) -{ - LineInfoW * info = const_cast(el_wline (m_editline)); - - // Just delete the next character normally if possible - if (info->cursor < info->lastchar) - { - info->cursor++; - el_deletestr (m_editline, 1); - return CC_REFRESH; - } +unsigned char Editline::DeleteNextCharCommand(int ch) { + LineInfoW *info = const_cast(el_wline(m_editline)); - // Fail when at the end of the last line, except when ^D is pressed on - // the line is empty, in which case it is treated as EOF - if (m_current_line_index == m_input_lines.size() - 1) - { - if (ch == 4 && info->buffer == info->lastchar) - { - fprintf (m_output_file, "^D\n"); - m_editor_status = EditorStatus::EndOfInput; - return CC_EOF; - } - return CC_ERROR; - } - - // Prepare to combine this line with the one below - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - - // Insert the next line of text at the cursor and restore the cursor position - const EditLineCharType * cursor = info->cursor; - el_winsertstr (m_editline, m_input_lines[m_current_line_index + 1].c_str()); - info->cursor = cursor; - SaveEditedLine(); - - // Delete the extra line - m_input_lines.erase (m_input_lines.begin() + m_current_line_index + 1); - - // Clear and repaint from this line on down - DisplayInput (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); + // Just delete the next character normally if possible + if (info->cursor < info->lastchar) { + info->cursor++; + el_deletestr(m_editline, 1); return CC_REFRESH; + } + + // Fail when at the end of the last line, except when ^D is pressed on + // the line is empty, in which case it is treated as EOF + if (m_current_line_index == m_input_lines.size() - 1) { + if (ch == 4 && info->buffer == info->lastchar) { + fprintf(m_output_file, "^D\n"); + m_editor_status = EditorStatus::EndOfInput; + return CC_EOF; + } + return CC_ERROR; + } + + // Prepare to combine this line with the one below + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Insert the next line of text at the cursor and restore the cursor position + const EditLineCharType *cursor = info->cursor; + el_winsertstr(m_editline, m_input_lines[m_current_line_index + 1].c_str()); + info->cursor = cursor; + SaveEditedLine(); + + // Delete the extra line + m_input_lines.erase(m_input_lines.begin() + m_current_line_index + 1); + + // Clear and repaint from this line on down + DisplayInput(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + return CC_REFRESH; } -unsigned char -Editline::DeletePreviousCharCommand (int ch) -{ - LineInfoW * info = const_cast(el_wline (m_editline)); - - // Just delete the previous character normally when not at the start of a line - if (info->cursor > info->buffer) - { - el_deletestr (m_editline, 1); - return CC_REFRESH; - } - - // No prior line and no prior character? Let the user know - if (m_current_line_index == 0) - return CC_ERROR; - - // No prior character, but prior line? Combine with the line above - SaveEditedLine(); - SetCurrentLine (m_current_line_index - 1); - auto priorLine = m_input_lines[m_current_line_index]; - m_input_lines.erase (m_input_lines.begin() + m_current_line_index); - m_input_lines[m_current_line_index] = priorLine + m_input_lines[m_current_line_index]; - - // Repaint from the new line down - fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, CountRowsForLine (priorLine), 1); - DisplayInput (m_current_line_index); - - // Put the cursor back where libedit expects it to be before returning to editing - // by telling libedit about the newly inserted text - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - el_winsertstr (m_editline, priorLine.c_str()); - return CC_REDISPLAY; +unsigned char Editline::DeletePreviousCharCommand(int ch) { + LineInfoW *info = const_cast(el_wline(m_editline)); + + // Just delete the previous character normally when not at the start of a line + if (info->cursor > info->buffer) { + el_deletestr(m_editline, 1); + return CC_REFRESH; + } + + // No prior line and no prior character? Let the user know + if (m_current_line_index == 0) + return CC_ERROR; + + // No prior character, but prior line? Combine with the line above + SaveEditedLine(); + SetCurrentLine(m_current_line_index - 1); + auto priorLine = m_input_lines[m_current_line_index]; + m_input_lines.erase(m_input_lines.begin() + m_current_line_index); + m_input_lines[m_current_line_index] = + priorLine + m_input_lines[m_current_line_index]; + + // Repaint from the new line down + fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, + CountRowsForLine(priorLine), 1); + DisplayInput(m_current_line_index); + + // Put the cursor back where libedit expects it to be before returning to + // editing + // by telling libedit about the newly inserted text + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + el_winsertstr(m_editline, priorLine.c_str()); + return CC_REDISPLAY; } -unsigned char -Editline::PreviousLineCommand (int ch) -{ - SaveEditedLine(); +unsigned char Editline::PreviousLineCommand(int ch) { + SaveEditedLine(); - if (m_current_line_index == 0) { - return RecallHistory (true); - } - - // Start from a known location - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - - // Treat moving up from a blank last line as a deletion of that line - if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) - { - m_input_lines.erase (m_input_lines.begin() + m_current_line_index); - fprintf (m_output_file, ANSI_CLEAR_BELOW); - } - - SetCurrentLine (m_current_line_index - 1); - fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, - CountRowsForLine (m_input_lines[m_current_line_index]), 1); - return CC_NEWLINE; + if (m_current_line_index == 0) { + return RecallHistory(true); + } + + // Start from a known location + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Treat moving up from a blank last line as a deletion of that line + if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) { + m_input_lines.erase(m_input_lines.begin() + m_current_line_index); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + } + + SetCurrentLine(m_current_line_index - 1); + fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, + CountRowsForLine(m_input_lines[m_current_line_index]), 1); + return CC_NEWLINE; } -unsigned char -Editline::NextLineCommand (int ch) -{ - SaveEditedLine(); +unsigned char Editline::NextLineCommand(int ch) { + SaveEditedLine(); - // Handle attempts to move down from the last line - if (m_current_line_index == m_input_lines.size() - 1) - { - // Don't add an extra line if the existing last line is blank, move through history instead - if (IsOnlySpaces()) - { - return RecallHistory (false); - } - - // Determine indentation for the new line - int indentation = 0; - if (m_fix_indentation_callback) - { - StringList lines = GetInputAsStringList(); - lines.AppendString(""); - indentation = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); - } - m_input_lines.insert (m_input_lines.end(), EditLineStringType (indentation, EditLineCharType(' '))); + // Handle attempts to move down from the last line + if (m_current_line_index == m_input_lines.size() - 1) { + // Don't add an extra line if the existing last line is blank, move through + // history instead + if (IsOnlySpaces()) { + return RecallHistory(false); } - - // Move down past the current line using newlines to force scrolling if needed - SetCurrentLine (m_current_line_index + 1); - const LineInfoW * info = el_wline (m_editline); - int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); - int cursor_row = cursor_position / m_terminal_width; - for (int line_count = 0; line_count < m_current_line_rows - cursor_row; line_count++) - { - fprintf (m_output_file, "\n"); + + // Determine indentation for the new line + int indentation = 0; + if (m_fix_indentation_callback) { + StringList lines = GetInputAsStringList(); + lines.AppendString(""); + indentation = m_fix_indentation_callback( + this, lines, 0, m_fix_indentation_callback_baton); } - return CC_NEWLINE; + m_input_lines.insert( + m_input_lines.end(), + EditLineStringType(indentation, EditLineCharType(' '))); + } + + // Move down past the current line using newlines to force scrolling if needed + SetCurrentLine(m_current_line_index + 1); + const LineInfoW *info = el_wline(m_editline); + int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); + int cursor_row = cursor_position / m_terminal_width; + for (int line_count = 0; line_count < m_current_line_rows - cursor_row; + line_count++) { + fprintf(m_output_file, "\n"); + } + return CC_NEWLINE; } -unsigned char -Editline::PreviousHistoryCommand(int ch) -{ - SaveEditedLine(); +unsigned char Editline::PreviousHistoryCommand(int ch) { + SaveEditedLine(); - return RecallHistory(true); + return RecallHistory(true); } -unsigned char -Editline::NextHistoryCommand(int ch) -{ - SaveEditedLine(); +unsigned char Editline::NextHistoryCommand(int ch) { + SaveEditedLine(); - return RecallHistory(false); + return RecallHistory(false); } -unsigned char -Editline::FixIndentationCommand(int ch) -{ - if (!m_fix_indentation_callback) - return CC_NORM; +unsigned char Editline::FixIndentationCommand(int ch) { + if (!m_fix_indentation_callback) + return CC_NORM; - // Insert the character typed before proceeding - EditLineCharType inserted[] = { (EditLineCharType)ch, 0 }; - el_winsertstr (m_editline, inserted); - LineInfoW * info = const_cast(el_wline (m_editline)); - int cursor_position = info->cursor - info->buffer; + // Insert the character typed before proceeding + EditLineCharType inserted[] = {(EditLineCharType)ch, 0}; + el_winsertstr(m_editline, inserted); + LineInfoW *info = const_cast(el_wline(m_editline)); + int cursor_position = info->cursor - info->buffer; - // Save the edits and determine the correct indentation level - SaveEditedLine(); - StringList lines = GetInputAsStringList (m_current_line_index + 1); - int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton); - - // If it is already correct no special work is needed - if (indent_correction == 0) - return CC_REFRESH; - - // Change the indentation level of the line - std::string currentLine = lines.GetStringAtIndex (m_current_line_index); - if (indent_correction > 0) - { - currentLine = currentLine.insert (0, indent_correction, ' '); - } - else - { - currentLine = currentLine.erase (0, -indent_correction); - } + // Save the edits and determine the correct indentation level + SaveEditedLine(); + StringList lines = GetInputAsStringList(m_current_line_index + 1); + int indent_correction = m_fix_indentation_callback( + this, lines, cursor_position, m_fix_indentation_callback_baton); + + // If it is already correct no special work is needed + if (indent_correction == 0) + return CC_REFRESH; + + // Change the indentation level of the line + std::string currentLine = lines.GetStringAtIndex(m_current_line_index); + if (indent_correction > 0) { + currentLine = currentLine.insert(0, indent_correction, ' '); + } else { + currentLine = currentLine.erase(0, -indent_correction); + } #if LLDB_EDITLINE_USE_WCHAR - m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine); + m_input_lines[m_current_line_index] = m_utf8conv.from_bytes(currentLine); #else - m_input_lines[m_current_line_index] = currentLine; + m_input_lines[m_current_line_index] = currentLine; #endif - // Update the display to reflect the change - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - DisplayInput (m_current_line_index); - - // Reposition the cursor back on the original line and prepare to restart editing - // with a new cursor position - SetCurrentLine (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - m_revert_cursor_index = cursor_position + indent_correction; - return CC_NEWLINE; + // Update the display to reflect the change + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput(m_current_line_index); + + // Reposition the cursor back on the original line and prepare to restart + // editing + // with a new cursor position + SetCurrentLine(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + m_revert_cursor_index = cursor_position + indent_correction; + return CC_NEWLINE; } -unsigned char -Editline::RevertLineCommand (int ch) -{ - el_winsertstr (m_editline, m_input_lines[m_current_line_index].c_str()); - if (m_revert_cursor_index >= 0) - { - LineInfoW * info = const_cast(el_wline (m_editline)); - info->cursor = info->buffer + m_revert_cursor_index; - if (info->cursor > info->lastchar) - { - info->cursor = info->lastchar; - } - m_revert_cursor_index = -1; +unsigned char Editline::RevertLineCommand(int ch) { + el_winsertstr(m_editline, m_input_lines[m_current_line_index].c_str()); + if (m_revert_cursor_index >= 0) { + LineInfoW *info = const_cast(el_wline(m_editline)); + info->cursor = info->buffer + m_revert_cursor_index; + if (info->cursor > info->lastchar) { + info->cursor = info->lastchar; } - return CC_REFRESH; + m_revert_cursor_index = -1; + } + return CC_REFRESH; } -unsigned char -Editline::BufferStartCommand (int ch) -{ - SaveEditedLine(); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); - SetCurrentLine (0); - m_revert_cursor_index = 0; - return CC_NEWLINE; +unsigned char Editline::BufferStartCommand(int ch) { + SaveEditedLine(); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + SetCurrentLine(0); + m_revert_cursor_index = 0; + return CC_NEWLINE; } -unsigned char -Editline::BufferEndCommand (int ch) -{ - SaveEditedLine(); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockEnd); - SetCurrentLine ((int)m_input_lines.size() - 1); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; +unsigned char Editline::BufferEndCommand(int ch) { + SaveEditedLine(); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); + SetCurrentLine((int)m_input_lines.size() - 1); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -unsigned char -Editline::TabCommand (int ch) -{ - if (m_completion_callback == nullptr) - return CC_ERROR; - - const LineInfo *line_info = el_line (m_editline); - StringList completions; - int page_size = 40; - - const int num_completions = m_completion_callback (line_info->buffer, - line_info->cursor, - line_info->lastchar, - 0, // Don't skip any matches (start at match zero) - -1, // Get all the matches - completions, - m_completion_callback_baton); - - if (num_completions == 0) - return CC_ERROR; - // if (num_completions == -1) - // { - // el_insertstr (m_editline, m_completion_key); - // return CC_REDISPLAY; - // } - // else - if (num_completions == -2) - { - // Replace the entire line with the first string... - el_deletestr (m_editline, line_info->cursor - line_info->buffer); - el_insertstr (m_editline, completions.GetStringAtIndex (0)); - return CC_REDISPLAY; - } - - // If we get a longer match display that first. - const char *completion_str = completions.GetStringAtIndex (0); - if (completion_str != nullptr && *completion_str != '\0') - { - el_insertstr (m_editline, completion_str); - return CC_REDISPLAY; - } - - if (num_completions > 1) - { - int num_elements = num_completions + 1; - fprintf (m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); - if (num_completions < page_size) - { - for (int i = 1; i < num_elements; i++) - { - completion_str = completions.GetStringAtIndex (i); - fprintf (m_output_file, "\n\t%s", completion_str); - } - fprintf (m_output_file, "\n"); +unsigned char Editline::TabCommand(int ch) { + if (m_completion_callback == nullptr) + return CC_ERROR; + + const LineInfo *line_info = el_line(m_editline); + StringList completions; + int page_size = 40; + + const int num_completions = m_completion_callback( + line_info->buffer, line_info->cursor, line_info->lastchar, + 0, // Don't skip any matches (start at match zero) + -1, // Get all the matches + completions, m_completion_callback_baton); + + if (num_completions == 0) + return CC_ERROR; + // if (num_completions == -1) + // { + // el_insertstr (m_editline, m_completion_key); + // return CC_REDISPLAY; + // } + // else + if (num_completions == -2) { + // Replace the entire line with the first string... + el_deletestr(m_editline, line_info->cursor - line_info->buffer); + el_insertstr(m_editline, completions.GetStringAtIndex(0)); + return CC_REDISPLAY; + } + + // If we get a longer match display that first. + const char *completion_str = completions.GetStringAtIndex(0); + if (completion_str != nullptr && *completion_str != '\0') { + el_insertstr(m_editline, completion_str); + return CC_REDISPLAY; + } + + if (num_completions > 1) { + int num_elements = num_completions + 1; + fprintf(m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); + if (num_completions < page_size) { + for (int i = 1; i < num_elements; i++) { + completion_str = completions.GetStringAtIndex(i); + fprintf(m_output_file, "\n\t%s", completion_str); + } + fprintf(m_output_file, "\n"); + } else { + int cur_pos = 1; + char reply; + int got_char; + while (cur_pos < num_elements) { + int endpoint = cur_pos + page_size; + if (endpoint > num_elements) + endpoint = num_elements; + for (; cur_pos < endpoint; cur_pos++) { + completion_str = completions.GetStringAtIndex(cur_pos); + fprintf(m_output_file, "\n\t%s", completion_str); } - else - { - int cur_pos = 1; - char reply; - int got_char; - while (cur_pos < num_elements) - { - int endpoint = cur_pos + page_size; - if (endpoint > num_elements) - endpoint = num_elements; - for (; cur_pos < endpoint; cur_pos++) - { - completion_str = completions.GetStringAtIndex (cur_pos); - fprintf (m_output_file, "\n\t%s", completion_str); - } - - if (cur_pos >= num_elements) - { - fprintf (m_output_file, "\n"); - break; - } - - fprintf (m_output_file, "\nMore (Y/n/a): "); - reply = 'n'; - got_char = el_getc(m_editline, &reply); - if (got_char == -1 || reply == 'n') - break; - if (reply == 'a') - page_size = num_elements - cur_pos; - } + + if (cur_pos >= num_elements) { + fprintf(m_output_file, "\n"); + break; } - DisplayInput(); - MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + + fprintf(m_output_file, "\nMore (Y/n/a): "); + reply = 'n'; + got_char = el_getc(m_editline, &reply); + if (got_char == -1 || reply == 'n') + break; + if (reply == 'a') + page_size = num_elements - cur_pos; + } } - return CC_REDISPLAY; + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + } + return CC_REDISPLAY; } -void -Editline::ConfigureEditor (bool multiline) -{ - if (m_editline && m_multiline_enabled == multiline) - return; - m_multiline_enabled = multiline; - - if (m_editline) - { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. - el_set (m_editline, EL_EDITMODE, 0); - el_end (m_editline); - } - - m_editline = el_init (m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); - TerminalSizeChanged(); - - if (m_history_sp && m_history_sp->IsValid()) - { - m_history_sp->Load(); - el_wset (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); - } - el_set (m_editline, EL_CLIENTDATA, this); - el_set (m_editline, EL_SIGNAL, 0); - el_set (m_editline, EL_EDITOR, "emacs"); - el_set (m_editline, EL_PROMPT, (EditlinePromptCallbackType)([] (EditLine *editline) { - return Editline::InstanceFor (editline)->Prompt(); - })); - - el_wset (m_editline, EL_GETCFN, - (EditlineGetCharCallbackType)([] (EditLine * editline, EditLineCharType * c) { - return Editline::InstanceFor (editline)->GetCharacter (c); - })); - - // Commands used for multiline support, registered whether or not they're used - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), EditLineConstString("Insert a line break"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BreakLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), - EditLineConstString("End editing or continue when incomplete"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), - EditLineConstString("Delete next character"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), - EditLineConstString("Delete previous character"), - (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), - EditLineConstString("Move to previous line"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->PreviousLineCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), EditLineConstString("Move to next line"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), - EditLineConstString("Move to previous history"), - (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), EditLineConstString("Move to next history"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextHistoryCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), - EditLineConstString("Move to start of buffer"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferStartCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), EditLineConstString("Move to end of buffer"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferEndCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), - EditLineConstString("Fix line indentation"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor (editline)->FixIndentationCommand (ch); - })); - - // Register the complete callback under two names for compatibility with older clients using - // custom .editrc files (largely because libedit has a bad bug where if you have a bind command - // that tries to bind to a function name that doesn't exist, it can corrupt the heap and - // crash your process later.) - EditlineCommandCallbackType complete_callback = [] (EditLine * editline, int ch) { - return Editline::InstanceFor (editline)->TabCommand (ch); - }; - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"), EditLineConstString("Invoke completion"), - complete_callback); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"), EditLineConstString("Invoke completion"), - complete_callback); - - // General bindings we don't mind being overridden - if (!multiline) { - el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string - } - el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash in emacs mode - el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to auto complete - - // Allow user-specific customization prior to registering bindings we absolutely require - el_source (m_editline, NULL); - - // Register an internal binding that external developers shouldn't use - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), - EditLineConstString("Revert line to saved state"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->RevertLineCommand(ch); })); - - // Register keys that perform auto-indent correction - if (m_fix_indentation_callback && m_fix_indentation_callback_chars) - { - char bind_key[2] = { 0, 0 }; - const char * indent_chars = m_fix_indentation_callback_chars; - while (*indent_chars) - { - bind_key[0] = *indent_chars; - el_set (m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); - ++indent_chars; - } +void Editline::ConfigureEditor(bool multiline) { + if (m_editline && m_multiline_enabled == multiline) + return; + m_multiline_enabled = multiline; + + if (m_editline) { + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set(m_editline, EL_EDITMODE, 0); + el_end(m_editline); + } + + m_editline = + el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); + TerminalSizeChanged(); + + if (m_history_sp && m_history_sp->IsValid()) { + m_history_sp->Load(); + el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); + } + el_set(m_editline, EL_CLIENTDATA, this); + el_set(m_editline, EL_SIGNAL, 0); + el_set(m_editline, EL_EDITOR, "emacs"); + el_set(m_editline, EL_PROMPT, + (EditlinePromptCallbackType)([](EditLine *editline) { + return Editline::InstanceFor(editline)->Prompt(); + })); + + el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([]( + EditLine *editline, EditLineCharType *c) { + return Editline::InstanceFor(editline)->GetCharacter(c); + })); + + // Commands used for multiline support, registered whether or not they're used + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), + EditLineConstString("Insert a line break"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BreakLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), + EditLineConstString("End editing or continue when incomplete"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), + EditLineConstString("Delete next character"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); + })); + el_wset( + m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), + EditLineConstString("Delete previous character"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), + EditLineConstString("Move to previous line"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->PreviousLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), + EditLineConstString("Move to next line"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->NextLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), + EditLineConstString("Move to previous history"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), + EditLineConstString("Move to next history"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->NextHistoryCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), + EditLineConstString("Move to start of buffer"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferStartCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), + EditLineConstString("Move to end of buffer"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferEndCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), + EditLineConstString("Fix line indentation"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->FixIndentationCommand(ch); + })); + + // Register the complete callback under two names for compatibility with older + // clients using + // custom .editrc files (largely because libedit has a bad bug where if you + // have a bind command + // that tries to bind to a function name that doesn't exist, it can corrupt + // the heap and + // crash your process later.) + EditlineCommandCallbackType complete_callback = [](EditLine *editline, + int ch) { + return Editline::InstanceFor(editline)->TabCommand(ch); + }; + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"), + EditLineConstString("Invoke completion"), complete_callback); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"), + EditLineConstString("Invoke completion"), complete_callback); + + // General bindings we don't mind being overridden + if (!multiline) { + el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev", + NULL); // Cycle through backwards search, entering string + } + el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word", + NULL); // Delete previous word, behave like bash in emacs mode + el_set(m_editline, EL_BIND, "\t", "lldb-complete", + NULL); // Bind TAB to auto complete + + // Allow user-specific customization prior to registering bindings we + // absolutely require + el_source(m_editline, NULL); + + // Register an internal binding that external developers shouldn't use + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), + EditLineConstString("Revert line to saved state"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->RevertLineCommand(ch); + })); + + // Register keys that perform auto-indent correction + if (m_fix_indentation_callback && m_fix_indentation_callback_chars) { + char bind_key[2] = {0, 0}; + const char *indent_chars = m_fix_indentation_callback_chars; + while (*indent_chars) { + bind_key[0] = *indent_chars; + el_set(m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); + ++indent_chars; } - - // Multi-line editor bindings - if (multiline) - { - el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); - el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); - el_set (m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "^n", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); - el_set (m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); - - // Editor-specific bindings - if (IsEmacs()) - { - el_set (m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); - el_set (m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); - } - else - { - el_set (m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); - - el_set (m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", NULL); - el_set (m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", NULL); - - // Escape is absorbed exiting edit mode, so re-register important sequences - // without the prefix - el_set (m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); - } + } + + // Multi-line editor bindings + if (multiline) { + el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, "^n", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); + el_set(m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); + + // Editor-specific bindings + if (IsEmacs()) { + el_set(m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); + el_set(m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); + } else { + el_set(m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); + + el_set(m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", + NULL); + el_set(m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", + NULL); + el_set(m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", + NULL); + + // Escape is absorbed exiting edit mode, so re-register important + // sequences + // without the prefix + el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); } + } } //------------------------------------------------------------------ // Editline public methods //------------------------------------------------------------------ -Editline * -Editline::InstanceFor (EditLine * editline) -{ - Editline * editor; - el_get (editline, EL_CLIENTDATA, &editor); - return editor; +Editline *Editline::InstanceFor(EditLine *editline) { + Editline *editor; + el_get(editline, EL_CLIENTDATA, &editor); + return editor; } -Editline::Editline (const char * editline_name, FILE * input_file, FILE * output_file, FILE * error_file, bool color_prompts) : - m_editor_status (EditorStatus::Complete), - m_color_prompts(color_prompts), - m_input_file (input_file), - m_output_file (output_file), - m_error_file (error_file), - m_input_connection (fileno(input_file), false) -{ - // Get a shared history instance - m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; - m_history_sp = EditlineHistory::GetHistory (m_editor_name); +Editline::Editline(const char *editline_name, FILE *input_file, + FILE *output_file, FILE *error_file, bool color_prompts) + : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), + m_input_file(input_file), m_output_file(output_file), + m_error_file(error_file), m_input_connection(fileno(input_file), false) { + // Get a shared history instance + m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; + m_history_sp = EditlineHistory::GetHistory(m_editor_name); #ifdef USE_SETUPTERM_WORKAROUND - if (m_output_file) - { - const int term_fd = fileno(m_output_file); - if (term_fd != -1) - { - static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; - static std::set *g_init_terminal_fds_ptr = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [&]() { - g_init_terminal_fds_mutex_ptr = new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues - g_init_terminal_fds_ptr = new std::set(); // NOTE: Leak to avoid C++ destructor chain issues - }); - - // We must make sure to initialize the terminal a given file descriptor - // only once. If we do this multiple times, we start leaking memory. - std::lock_guard guard(*g_init_terminal_fds_mutex_ptr); - if (g_init_terminal_fds_ptr->find(term_fd) == g_init_terminal_fds_ptr->end()) - { - g_init_terminal_fds_ptr->insert(term_fd); - setupterm((char *)0, term_fd, (int *)0); - } - } + if (m_output_file) { + const int term_fd = fileno(m_output_file); + if (term_fd != -1) { + static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; + static std::set *g_init_terminal_fds_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, [&]() { + g_init_terminal_fds_mutex_ptr = + new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues + g_init_terminal_fds_ptr = new std::set(); // NOTE: Leak to avoid + // C++ destructor chain + // issues + }); + + // We must make sure to initialize the terminal a given file descriptor + // only once. If we do this multiple times, we start leaking memory. + std::lock_guard guard(*g_init_terminal_fds_mutex_ptr); + if (g_init_terminal_fds_ptr->find(term_fd) == + g_init_terminal_fds_ptr->end()) { + g_init_terminal_fds_ptr->insert(term_fd); + setupterm((char *)0, term_fd, (int *)0); + } } + } #endif } -Editline::~Editline() -{ - if (m_editline) - { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. - el_set (m_editline, EL_EDITMODE, 0); - el_end (m_editline); - m_editline = nullptr; - } - - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. So just release - // our shared pointer and if we are the last owner, it will save the - // history to the history save file automatically. - m_history_sp.reset(); +Editline::~Editline() { + if (m_editline) { + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set(m_editline, EL_EDITMODE, 0); + el_end(m_editline); + m_editline = nullptr; + } + + // EditlineHistory objects are sometimes shared between multiple + // Editline instances with the same program name. So just release + // our shared pointer and if we are the last owner, it will save the + // history to the history save file automatically. + m_history_sp.reset(); } -void -Editline::SetPrompt (const char * prompt) -{ - m_set_prompt = prompt == nullptr ? "" : prompt; +void Editline::SetPrompt(const char *prompt) { + m_set_prompt = prompt == nullptr ? "" : prompt; } -void -Editline::SetContinuationPrompt (const char * continuation_prompt) -{ - m_set_continuation_prompt = continuation_prompt == nullptr ? "" : continuation_prompt; +void Editline::SetContinuationPrompt(const char *continuation_prompt) { + m_set_continuation_prompt = + continuation_prompt == nullptr ? "" : continuation_prompt; } -void -Editline::TerminalSizeChanged() -{ - if (m_editline != nullptr) - { - el_resize (m_editline); - int columns; - // Despite the man page claiming non-zero indicates success, it's actually zero - if (el_get (m_editline, EL_GETTC, "co", &columns) == 0) - { - m_terminal_width = columns; - if (m_current_line_rows != -1) - { - const LineInfoW * info = el_wline (m_editline); - int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); - m_current_line_rows = (lineLength / columns) + 1; - } - } - else - { - m_terminal_width = INT_MAX; - m_current_line_rows = 1; - } +void Editline::TerminalSizeChanged() { + if (m_editline != nullptr) { + el_resize(m_editline); + int columns; + // Despite the man page claiming non-zero indicates success, it's actually + // zero + if (el_get(m_editline, EL_GETTC, "co", &columns) == 0) { + m_terminal_width = columns; + if (m_current_line_rows != -1) { + const LineInfoW *info = el_wline(m_editline); + int lineLength = + (int)((info->lastchar - info->buffer) + GetPromptWidth()); + m_current_line_rows = (lineLength / columns) + 1; + } + } else { + m_terminal_width = INT_MAX; + m_current_line_rows = 1; } + } } -const char * -Editline::GetPrompt() -{ - return m_set_prompt.c_str(); -} +const char *Editline::GetPrompt() { return m_set_prompt.c_str(); } -uint32_t -Editline::GetCurrentLine() -{ - return m_current_line_index; -} +uint32_t Editline::GetCurrentLine() { return m_current_line_index; } -bool -Editline::Interrupt() -{ - bool result = true; - std::lock_guard guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) { - fprintf(m_output_file, "^C\n"); - result = m_input_connection.InterruptRead(); - } - m_editor_status = EditorStatus::Interrupted; - return result; +bool Editline::Interrupt() { + bool result = true; + std::lock_guard guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + fprintf(m_output_file, "^C\n"); + result = m_input_connection.InterruptRead(); + } + m_editor_status = EditorStatus::Interrupted; + return result; } -bool -Editline::Cancel() -{ - bool result = true; - std::lock_guard guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) { - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); - fprintf(m_output_file, ANSI_CLEAR_BELOW); - result = m_input_connection.InterruptRead(); - } - m_editor_status = EditorStatus::Interrupted; - return result; +bool Editline::Cancel() { + bool result = true; + std::lock_guard guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + result = m_input_connection.InterruptRead(); + } + m_editor_status = EditorStatus::Interrupted; + return result; } -void -Editline::SetAutoCompleteCallback (CompleteCallbackType callback, void * baton) -{ - m_completion_callback = callback; - m_completion_callback_baton = baton; +void Editline::SetAutoCompleteCallback(CompleteCallbackType callback, + void *baton) { + m_completion_callback = callback; + m_completion_callback_baton = baton; } -void -Editline::SetIsInputCompleteCallback (IsInputCompleteCallbackType callback, void * baton) -{ - m_is_input_complete_callback = callback; - m_is_input_complete_callback_baton = baton; +void Editline::SetIsInputCompleteCallback(IsInputCompleteCallbackType callback, + void *baton) { + m_is_input_complete_callback = callback; + m_is_input_complete_callback_baton = baton; } -bool -Editline::SetFixIndentationCallback (FixIndentationCallbackType callback, - void * baton, - const char * indent_chars) -{ - m_fix_indentation_callback = callback; - m_fix_indentation_callback_baton = baton; - m_fix_indentation_callback_chars = indent_chars; - return false; +bool Editline::SetFixIndentationCallback(FixIndentationCallbackType callback, + void *baton, + const char *indent_chars) { + m_fix_indentation_callback = callback; + m_fix_indentation_callback_baton = baton; + m_fix_indentation_callback_chars = indent_chars; + return false; } -bool -Editline::GetLine (std::string &line, bool &interrupted) -{ - ConfigureEditor (false); - m_input_lines = std::vector(); - m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); +bool Editline::GetLine(std::string &line, bool &interrupted) { + ConfigureEditor(false); + m_input_lines = std::vector(); + m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); - std::lock_guard guard(m_output_mutex); + std::lock_guard guard(m_output_mutex); - lldbassert(m_editor_status != EditorStatus::Editing); - if (m_editor_status == EditorStatus::Interrupted) - { - m_editor_status = EditorStatus::Complete; - interrupted = true; - return true; - } - - SetCurrentLine (0); - m_in_history = false; - m_editor_status = EditorStatus::Editing; - m_revert_cursor_index = -1; - - int count; - auto input = el_wgets (m_editline, &count); - - interrupted = m_editor_status == EditorStatus::Interrupted; - if (!interrupted) - { - if (input == nullptr) - { - fprintf (m_output_file, "\n"); - m_editor_status = EditorStatus::EndOfInput; - } - else - { - m_history_sp->Enter (input); + lldbassert(m_editor_status != EditorStatus::Editing); + if (m_editor_status == EditorStatus::Interrupted) { + m_editor_status = EditorStatus::Complete; + interrupted = true; + return true; + } + + SetCurrentLine(0); + m_in_history = false; + m_editor_status = EditorStatus::Editing; + m_revert_cursor_index = -1; + + int count; + auto input = el_wgets(m_editline, &count); + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) { + if (input == nullptr) { + fprintf(m_output_file, "\n"); + m_editor_status = EditorStatus::EndOfInput; + } else { + m_history_sp->Enter(input); #if LLDB_EDITLINE_USE_WCHAR - line = m_utf8conv.to_bytes (SplitLines (input)[0]); + line = m_utf8conv.to_bytes(SplitLines(input)[0]); #else - line = SplitLines (input)[0]; + line = SplitLines(input)[0]; #endif - m_editor_status = EditorStatus::Complete; - } + m_editor_status = EditorStatus::Complete; } - return m_editor_status != EditorStatus::EndOfInput; + } + return m_editor_status != EditorStatus::EndOfInput; } -bool -Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted) -{ - ConfigureEditor (true); - - // Print the initial input lines, then move the cursor back up to the start of input - SetBaseLineNumber (first_line_number); - m_input_lines = std::vector(); - m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); - - std::lock_guard guard(m_output_mutex); - // Begin the line editing loop - DisplayInput(); - SetCurrentLine (0); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::BlockStart); - m_editor_status = EditorStatus::Editing; - m_in_history = false; - - m_revert_cursor_index = -1; - while (m_editor_status == EditorStatus::Editing) - { - int count; - m_current_line_rows = -1; - el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content - el_wgets (m_editline, &count); - } - - interrupted = m_editor_status == EditorStatus::Interrupted; - if (!interrupted) - { - // Save the completed entry in history before returning - m_history_sp->Enter (CombineLines (m_input_lines).c_str()); - - lines = GetInputAsStringList(); - } - return m_editor_status != EditorStatus::EndOfInput; +bool Editline::GetLines(int first_line_number, StringList &lines, + bool &interrupted) { + ConfigureEditor(true); + + // Print the initial input lines, then move the cursor back up to the start of + // input + SetBaseLineNumber(first_line_number); + m_input_lines = std::vector(); + m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + + std::lock_guard guard(m_output_mutex); + // Begin the line editing loop + DisplayInput(); + SetCurrentLine(0); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart); + m_editor_status = EditorStatus::Editing; + m_in_history = false; + + m_revert_cursor_index = -1; + while (m_editor_status == EditorStatus::Editing) { + int count; + m_current_line_rows = -1; + el_wpush(m_editline, EditLineConstString( + "\x1b[^")); // Revert to the existing line content + el_wgets(m_editline, &count); + } + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) { + // Save the completed entry in history before returning + m_history_sp->Enter(CombineLines(m_input_lines).c_str()); + + lines = GetInputAsStringList(); + } + return m_editor_status != EditorStatus::EndOfInput; } -void -Editline::PrintAsync (Stream *stream, const char *s, size_t len) -{ - std::lock_guard guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) - { - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); - fprintf(m_output_file, ANSI_CLEAR_BELOW); - } - stream->Write (s, len); - stream->Flush(); - if (m_editor_status == EditorStatus::Editing) - { - DisplayInput(); - MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); - } +void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { + std::lock_guard guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + } + stream->Write(s, len); + stream->Flush(); + if (m_editor_status == EditorStatus::Editing) { + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + } } diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 89587a999d9..fcd1416e9ce 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -34,1028 +34,829 @@ using namespace lldb; using namespace lldb_private; -static const char * -GetStreamOpenModeFromOptions (uint32_t options) -{ - if (options & File::eOpenOptionAppend) - { - if (options & File::eOpenOptionRead) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "a+x"; - else - return "a+"; - } - else if (options & File::eOpenOptionWrite) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "ax"; - else - return "a"; - } - } - else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) - { - if (options & File::eOpenOptionCanCreate) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "w+x"; - else - return "w+"; - } - else - return "r+"; - } - else if (options & File::eOpenOptionRead) - { - return "r"; - } - else if (options & File::eOpenOptionWrite) - { - return "w"; - } - return NULL; +static const char *GetStreamOpenModeFromOptions(uint32_t options) { + if (options & File::eOpenOptionAppend) { + if (options & File::eOpenOptionRead) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "a+x"; + else + return "a+"; + } else if (options & File::eOpenOptionWrite) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "ax"; + else + return "a"; + } + } else if (options & File::eOpenOptionRead && + options & File::eOpenOptionWrite) { + if (options & File::eOpenOptionCanCreate) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "w+x"; + else + return "w+"; + } else + return "r+"; + } else if (options & File::eOpenOptionRead) { + return "r"; + } else if (options & File::eOpenOptionWrite) { + return "w"; + } + return NULL; } int File::kInvalidDescriptor = -1; -FILE * File::kInvalidStream = NULL; - -File::File(const char *path, uint32_t options, uint32_t permissions) : - IOObject(eFDTypeFile, false), - m_descriptor (kInvalidDescriptor), - m_stream (kInvalidStream), - m_options (), - m_own_stream (false), - m_is_interactive (eLazyBoolCalculate), - m_is_real_terminal (eLazyBoolCalculate) -{ - Open (path, options, permissions); -} - -File::File (const FileSpec& filespec, - uint32_t options, - uint32_t permissions) : - IOObject(eFDTypeFile, false), - m_descriptor (kInvalidDescriptor), - m_stream (kInvalidStream), - m_options (0), - m_own_stream (false), - m_is_interactive (eLazyBoolCalculate), - m_is_real_terminal (eLazyBoolCalculate) +FILE *File::kInvalidStream = NULL; -{ - if (filespec) - { - Open (filespec.GetPath().c_str(), options, permissions); - } +File::File(const char *path, uint32_t options, uint32_t permissions) + : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), + m_stream(kInvalidStream), m_options(), m_own_stream(false), + m_is_interactive(eLazyBoolCalculate), + m_is_real_terminal(eLazyBoolCalculate) { + Open(path, options, permissions); } -File::~File() +File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions) + : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), + m_stream(kInvalidStream), m_options(0), m_own_stream(false), + m_is_interactive(eLazyBoolCalculate), + m_is_real_terminal(eLazyBoolCalculate) + { - Close (); + if (filespec) { + Open(filespec.GetPath().c_str(), options, permissions); + } } +File::~File() { Close(); } -int -File::GetDescriptor() const -{ - if (DescriptorIsValid()) - return m_descriptor; +int File::GetDescriptor() const { + if (DescriptorIsValid()) + return m_descriptor; - // Don't open the file descriptor if we don't need to, just get it from the - // stream if we have one. - if (StreamIsValid()) - { + // Don't open the file descriptor if we don't need to, just get it from the + // stream if we have one. + if (StreamIsValid()) { #if defined(LLVM_ON_WIN32) - return _fileno(m_stream); + return _fileno(m_stream); #else - return fileno(m_stream); + return fileno(m_stream); #endif - } + } - // Invalid descriptor and invalid stream, return invalid descriptor. - return kInvalidDescriptor; -} - -IOObject::WaitableHandle -File::GetWaitableHandle() -{ - return m_descriptor; + // Invalid descriptor and invalid stream, return invalid descriptor. + return kInvalidDescriptor; } +IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; } -void -File::SetDescriptor (int fd, bool transfer_ownership) -{ - if (IsValid()) - Close(); - m_descriptor = fd; - m_should_close_fd = transfer_ownership; +void File::SetDescriptor(int fd, bool transfer_ownership) { + if (IsValid()) + Close(); + m_descriptor = fd; + m_should_close_fd = transfer_ownership; } - -FILE * -File::GetStream () -{ - if (!StreamIsValid()) - { - if (DescriptorIsValid()) - { - const char *mode = GetStreamOpenModeFromOptions (m_options); - if (mode) - { - if (!m_should_close_fd) - { - // We must duplicate the file descriptor if we don't own it because - // when you call fdopen, the stream will own the fd +FILE *File::GetStream() { + if (!StreamIsValid()) { + if (DescriptorIsValid()) { + const char *mode = GetStreamOpenModeFromOptions(m_options); + if (mode) { + if (!m_should_close_fd) { +// We must duplicate the file descriptor if we don't own it because +// when you call fdopen, the stream will own the fd #ifdef _WIN32 - m_descriptor = ::_dup(GetDescriptor()); + m_descriptor = ::_dup(GetDescriptor()); #else - m_descriptor = dup(GetDescriptor()); + m_descriptor = dup(GetDescriptor()); #endif - m_should_close_fd = true; - } - - do - { - m_stream = ::fdopen (m_descriptor, mode); - } while (m_stream == NULL && errno == EINTR); - - // If we got a stream, then we own the stream and should no - // longer own the descriptor because fclose() will close it for us - - if (m_stream) - { - m_own_stream = true; - m_should_close_fd = false; - } - } + m_should_close_fd = true; + } + + do { + m_stream = ::fdopen(m_descriptor, mode); + } while (m_stream == NULL && errno == EINTR); + + // If we got a stream, then we own the stream and should no + // longer own the descriptor because fclose() will close it for us + + if (m_stream) { + m_own_stream = true; + m_should_close_fd = false; } + } } - return m_stream; + } + return m_stream; } -void -File::SetStream (FILE *fh, bool transfer_ownership) -{ - if (IsValid()) - Close(); - m_stream = fh; - m_own_stream = transfer_ownership; +void File::SetStream(FILE *fh, bool transfer_ownership) { + if (IsValid()) + Close(); + m_stream = fh; + m_own_stream = transfer_ownership; } -Error -File::Open (const char *path, uint32_t options, uint32_t permissions) -{ - Error error; - if (IsValid()) - Close (); - - int oflag = 0; - const bool read = options & eOpenOptionRead; - const bool write = options & eOpenOptionWrite; - if (write) - { - if (read) - oflag |= O_RDWR; - else - oflag |= O_WRONLY; - - if (options & eOpenOptionAppend) - oflag |= O_APPEND; - - if (options & eOpenOptionTruncate) - oflag |= O_TRUNC; - - if (options & eOpenOptionCanCreate) - oflag |= O_CREAT; - - if (options & eOpenOptionCanCreateNewOnly) - oflag |= O_CREAT | O_EXCL; - } - else if (read) - { - oflag |= O_RDONLY; +Error File::Open(const char *path, uint32_t options, uint32_t permissions) { + Error error; + if (IsValid()) + Close(); + + int oflag = 0; + const bool read = options & eOpenOptionRead; + const bool write = options & eOpenOptionWrite; + if (write) { + if (read) + oflag |= O_RDWR; + else + oflag |= O_WRONLY; + + if (options & eOpenOptionAppend) + oflag |= O_APPEND; + + if (options & eOpenOptionTruncate) + oflag |= O_TRUNC; + + if (options & eOpenOptionCanCreate) + oflag |= O_CREAT; + + if (options & eOpenOptionCanCreateNewOnly) + oflag |= O_CREAT | O_EXCL; + } else if (read) { + oflag |= O_RDONLY; #ifndef _WIN32 - if (options & eOpenOptionDontFollowSymlinks) - oflag |= O_NOFOLLOW; + if (options & eOpenOptionDontFollowSymlinks) + oflag |= O_NOFOLLOW; #endif - } - + } + #ifndef _WIN32 - if (options & eOpenOptionNonBlocking) - oflag |= O_NONBLOCK; - if (options & eOpenOptionCloseOnExec) - oflag |= O_CLOEXEC; + if (options & eOpenOptionNonBlocking) + oflag |= O_NONBLOCK; + if (options & eOpenOptionCloseOnExec) + oflag |= O_CLOEXEC; #else - oflag |= O_BINARY; + oflag |= O_BINARY; #endif - mode_t mode = 0; - if (oflag & O_CREAT) - { - if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; - if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; - if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; - if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; - if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; - if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; - if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; - if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; - if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; + mode_t mode = 0; + if (oflag & O_CREAT) { + if (permissions & lldb::eFilePermissionsUserRead) + mode |= S_IRUSR; + if (permissions & lldb::eFilePermissionsUserWrite) + mode |= S_IWUSR; + if (permissions & lldb::eFilePermissionsUserExecute) + mode |= S_IXUSR; + if (permissions & lldb::eFilePermissionsGroupRead) + mode |= S_IRGRP; + if (permissions & lldb::eFilePermissionsGroupWrite) + mode |= S_IWGRP; + if (permissions & lldb::eFilePermissionsGroupExecute) + mode |= S_IXGRP; + if (permissions & lldb::eFilePermissionsWorldRead) + mode |= S_IROTH; + if (permissions & lldb::eFilePermissionsWorldWrite) + mode |= S_IWOTH; + if (permissions & lldb::eFilePermissionsWorldExecute) + mode |= S_IXOTH; + } + + do { +#ifdef _WIN32 + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + m_descriptor = -1; + error.SetErrorString("Error converting path to UTF-16"); + return error; } + ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); +#else + m_descriptor = ::open(path, oflag, mode); +#endif + } while (m_descriptor < 0 && errno == EINTR); + + if (!DescriptorIsValid()) + error.SetErrorToErrno(); + else { + m_should_close_fd = true; + m_options = options; + } + + return error; +} + +uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) { + if (file_spec) { + struct stat file_stats; + int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); + if (stat_result == -1) + error.SetErrorToErrno(); + else { + error.Clear(); + return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + } else + error.SetErrorString("empty file spec"); + return 0; +} + +uint32_t File::GetPermissions(Error &error) const { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + struct stat file_stats; + if (::fstat(fd, &file_stats) == -1) + error.SetErrorToErrno(); + else { + error.Clear(); + return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + } else { + error.SetErrorString("invalid file descriptor"); + } + return 0; +} + +Error File::Close() { + Error error; + if (StreamIsValid() && m_own_stream) { + if (::fclose(m_stream) == EOF) + error.SetErrorToErrno(); + } + + if (DescriptorIsValid() && m_should_close_fd) { + if (::close(m_descriptor) != 0) + error.SetErrorToErrno(); + } + m_descriptor = kInvalidDescriptor; + m_stream = kInvalidStream; + m_options = 0; + m_own_stream = false; + m_should_close_fd = false; + m_is_interactive = eLazyBoolCalculate; + m_is_real_terminal = eLazyBoolCalculate; + return error; +} + +void File::Clear() { + m_stream = nullptr; + m_descriptor = -1; + m_options = 0; + m_own_stream = false; + m_is_interactive = m_supports_colors = m_is_real_terminal = + eLazyBoolCalculate; +} + +Error File::GetFileSpec(FileSpec &file_spec) const { + Error error; +#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED + if (IsValid()) { + char path[PATH_MAX]; + if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) + error.SetErrorToErrno(); + else + file_spec.SetFile(path, false); + } else { + error.SetErrorString("invalid file handle"); + } +#elif defined(__linux__) + char proc[64]; + char path[PATH_MAX]; + if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) + error.SetErrorString("cannot resolve file descriptor"); + else { + ssize_t len; + if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) + error.SetErrorToErrno(); + else { + path[len] = '\0'; + file_spec.SetFile(path, false); + } + } +#else + error.SetErrorString("File::GetFileSpec is not supported on this platform"); +#endif - do - { + if (error.Fail()) + file_spec.Clear(); + return error; +} + +off_t File::SeekFromStart(off_t offset, Error *error_ptr) { + off_t result = 0; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_SET); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_SET); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) { + off_t result = -1; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_CUR); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_CUR); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +off_t File::SeekFromEnd(off_t offset, Error *error_ptr) { + off_t result = -1; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_END); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_END); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +Error File::Flush() { + Error error; + if (StreamIsValid()) { + int err = 0; + do { + err = ::fflush(m_stream); + } while (err == EOF && errno == EINTR); + + if (err == EOF) + error.SetErrorToErrno(); + } else if (!DescriptorIsValid()) { + error.SetErrorString("invalid file handle"); + } + return error; +} + +Error File::Sync() { + Error error; + if (DescriptorIsValid()) { #ifdef _WIN32 - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - m_descriptor = -1; - error.SetErrorString("Error converting path to UTF-16"); - return error; - } - ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); + int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); + if (err == 0) + error.SetErrorToGenericError(); #else - m_descriptor = ::open(path, oflag, mode); -#endif - } while (m_descriptor < 0 && errno == EINTR); + int err = 0; + do { + err = ::fsync(m_descriptor); + } while (err == -1 && errno == EINTR); - if (!DescriptorIsValid()) - error.SetErrorToErrno(); - else - { - m_should_close_fd = true; - m_options = options; - } - - return error; + if (err == -1) + error.SetErrorToErrno(); +#endif + } else { + error.SetErrorString("invalid file handle"); + } + return error; } -uint32_t -File::GetPermissions(const FileSpec &file_spec, Error &error) -{ - if (file_spec) - { - struct stat file_stats; - int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); - if (stat_result == -1) - error.SetErrorToErrno(); - else - { - error.Clear(); - return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - } - else - error.SetErrorString ("empty file spec"); - return 0; -} +#if defined(__APPLE__) +// Darwin kernels only can read/write <= INT_MAX bytes +#define MAX_READ_SIZE INT_MAX +#define MAX_WRITE_SIZE INT_MAX +#endif -uint32_t -File::GetPermissions(Error &error) const -{ - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == -1) - error.SetErrorToErrno(); - else - { - error.Clear(); - return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - } - else - { - error.SetErrorString ("invalid file descriptor"); - } - return 0; -} +Error File::Read(void *buf, size_t &num_bytes) { + Error error; +#if defined(MAX_READ_SIZE) + if (num_bytes > MAX_READ_SIZE) { + uint8_t *p = (uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes read to zero + num_bytes = 0; -Error -File::Close () -{ - Error error; - if (StreamIsValid() && m_own_stream) - { - if (::fclose (m_stream) == EOF) - error.SetErrorToErrno(); - } - - if (DescriptorIsValid() && m_should_close_fd) - { - if (::close (m_descriptor) != 0) - error.SetErrorToErrno(); - } - m_descriptor = kInvalidDescriptor; - m_stream = kInvalidStream; - m_options = 0; - m_own_stream = false; - m_should_close_fd = false; - m_is_interactive = eLazyBoolCalculate; - m_is_real_terminal = eLazyBoolCalculate; - return error; -} + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_READ_SIZE) + curr_num_bytes = MAX_READ_SIZE; + else + curr_num_bytes = bytes_left; -void -File::Clear () -{ - m_stream = nullptr; - m_descriptor = -1; - m_options = 0; - m_own_stream = false; - m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate; -} + error = Read(p + num_bytes, curr_num_bytes); -Error -File::GetFileSpec (FileSpec &file_spec) const -{ - Error error; -#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED - if (IsValid ()) - { - char path[PATH_MAX]; - if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) - error.SetErrorToErrno(); - else - file_spec.SetFile (path, false); - } - else - { - error.SetErrorString("invalid file handle"); - } -#elif defined(__linux__) - char proc[64]; - char path[PATH_MAX]; - if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) - error.SetErrorString ("cannot resolve file descriptor"); - else - { - ssize_t len; - if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) - error.SetErrorToErrno(); - else - { - path[len] = '\0'; - file_spec.SetFile (path, false); - } + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } -#else - error.SetErrorString ("File::GetFileSpec is not supported on this platform"); + return error; + } #endif - if (error.Fail()) - file_spec.Clear(); - return error; + ssize_t bytes_read = -1; + if (DescriptorIsValid()) { + do { + bytes_read = ::read(m_descriptor, buf, num_bytes); + } while (bytes_read < 0 && errno == EINTR); + + if (bytes_read == -1) { + error.SetErrorToErrno(); + num_bytes = 0; + } else + num_bytes = bytes_read; + } else if (StreamIsValid()) { + bytes_read = ::fread(buf, 1, num_bytes, m_stream); + + if (bytes_read == 0) { + if (::feof(m_stream)) + error.SetErrorString("feof"); + else if (::ferror(m_stream)) + error.SetErrorString("ferror"); + num_bytes = 0; + } else + num_bytes = bytes_read; + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } + return error; } -off_t -File::SeekFromStart (off_t offset, Error *error_ptr) -{ - off_t result = 0; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_SET); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_SET); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} +Error File::Write(const void *buf, size_t &num_bytes) { + Error error; -off_t -File::SeekFromCurrent (off_t offset, Error *error_ptr) -{ - off_t result = -1; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_CUR); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_CUR); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} +#if defined(MAX_WRITE_SIZE) + if (num_bytes > MAX_WRITE_SIZE) { + const uint8_t *p = (const uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes written to zero + num_bytes = 0; -off_t -File::SeekFromEnd (off_t offset, Error *error_ptr) -{ - off_t result = -1; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_END); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_END); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_WRITE_SIZE) + curr_num_bytes = MAX_WRITE_SIZE; + else + curr_num_bytes = bytes_left; -Error -File::Flush () -{ - Error error; - if (StreamIsValid()) - { - int err = 0; - do - { - err = ::fflush (m_stream); - } while (err == EOF && errno == EINTR); - - if (err == EOF) - error.SetErrorToErrno(); - } - else if (!DescriptorIsValid()) - { - error.SetErrorString("invalid file handle"); - } - return error; -} + error = Write(p + num_bytes, curr_num_bytes); + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; -Error -File::Sync () -{ - Error error; - if (DescriptorIsValid()) - { -#ifdef _WIN32 - int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); - if (err == 0) - error.SetErrorToGenericError(); -#else - int err = 0; - do - { - err = ::fsync (m_descriptor); - } while (err == -1 && errno == EINTR); - - if (err == -1) - error.SetErrorToErrno(); -#endif - } - else - { - error.SetErrorString("invalid file handle"); + if (error.Fail()) + break; } return error; -} - -#if defined (__APPLE__) -// Darwin kernels only can read/write <= INT_MAX bytes -#define MAX_READ_SIZE INT_MAX -#define MAX_WRITE_SIZE INT_MAX + } #endif -Error -File::Read (void *buf, size_t &num_bytes) -{ - Error error; - -#if defined (MAX_READ_SIZE) - if (num_bytes > MAX_READ_SIZE) - { - uint8_t *p = (uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes read to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_READ_SIZE) - curr_num_bytes = MAX_READ_SIZE; - else - curr_num_bytes = bytes_left; - - error = Read (p + num_bytes, curr_num_bytes); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; - } -#endif + ssize_t bytes_written = -1; + if (DescriptorIsValid()) { + do { + bytes_written = ::write(m_descriptor, buf, num_bytes); + } while (bytes_written < 0 && errno == EINTR); + + if (bytes_written == -1) { + error.SetErrorToErrno(); + num_bytes = 0; + } else + num_bytes = bytes_written; + } else if (StreamIsValid()) { + bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); + + if (bytes_written == 0) { + if (::feof(m_stream)) + error.SetErrorString("feof"); + else if (::ferror(m_stream)) + error.SetErrorString("ferror"); + num_bytes = 0; + } else + num_bytes = bytes_written; + + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } - ssize_t bytes_read = -1; - if (DescriptorIsValid()) - { - do - { - bytes_read = ::read (m_descriptor, buf, num_bytes); - } while (bytes_read < 0 && errno == EINTR); - - if (bytes_read == -1) - { - error.SetErrorToErrno(); - num_bytes = 0; - } - else - num_bytes = bytes_read; - } - else if (StreamIsValid()) - { - bytes_read = ::fread (buf, 1, num_bytes, m_stream); - - if (bytes_read == 0) - { - if (::feof(m_stream)) - error.SetErrorString ("feof"); - else if (::ferror (m_stream)) - error.SetErrorString ("ferror"); - num_bytes = 0; - } - else - num_bytes = bytes_read; - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } - return error; + return error; } - -Error -File::Write (const void *buf, size_t &num_bytes) -{ - Error error; - -#if defined (MAX_WRITE_SIZE) - if (num_bytes > MAX_WRITE_SIZE) - { - const uint8_t *p = (const uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes written to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_WRITE_SIZE) - curr_num_bytes = MAX_WRITE_SIZE; - else - curr_num_bytes = bytes_left; - - error = Write (p + num_bytes, curr_num_bytes); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; - } -#endif - ssize_t bytes_written = -1; - if (DescriptorIsValid()) - { - do - { - bytes_written = ::write (m_descriptor, buf, num_bytes); - } while (bytes_written < 0 && errno == EINTR); - - if (bytes_written == -1) - { - error.SetErrorToErrno(); - num_bytes = 0; - } - else - num_bytes = bytes_written; - } - else if (StreamIsValid()) - { - bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); - - if (bytes_written == 0) - { - if (::feof(m_stream)) - error.SetErrorString ("feof"); - else if (::ferror (m_stream)) - error.SetErrorString ("ferror"); - num_bytes = 0; - } - else - num_bytes = bytes_written; - - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } +Error File::Read(void *buf, size_t &num_bytes, off_t &offset) { + Error error; - return error; -} +#if defined(MAX_READ_SIZE) + if (num_bytes > MAX_READ_SIZE) { + uint8_t *p = (uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes read to zero + num_bytes = 0; + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_READ_SIZE) + curr_num_bytes = MAX_READ_SIZE; + else + curr_num_bytes = bytes_left; -Error -File::Read (void *buf, size_t &num_bytes, off_t &offset) -{ - Error error; - -#if defined (MAX_READ_SIZE) - if (num_bytes > MAX_READ_SIZE) - { - uint8_t *p = (uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes read to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_READ_SIZE) - curr_num_bytes = MAX_READ_SIZE; - else - curr_num_bytes = bytes_left; - - error = Read (p + num_bytes, curr_num_bytes, offset); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; + error = Read(p + num_bytes, curr_num_bytes, offset); + + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } + return error; + } #endif #ifndef _WIN32 - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - ssize_t bytes_read = -1; - do - { - bytes_read = ::pread (fd, buf, num_bytes, offset); - } while (bytes_read < 0 && errno == EINTR); - - if (bytes_read < 0) - { - num_bytes = 0; - error.SetErrorToErrno(); - } - else - { - offset += bytes_read; - num_bytes = bytes_read; - } - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + ssize_t bytes_read = -1; + do { + bytes_read = ::pread(fd, buf, num_bytes, offset); + } while (bytes_read < 0 && errno == EINTR); + + if (bytes_read < 0) { + num_bytes = 0; + error.SetErrorToErrno(); + } else { + offset += bytes_read; + num_bytes = bytes_read; + } + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } #else - long cur = ::lseek(m_descriptor, 0, SEEK_CUR); - SeekFromStart(offset); - error = Read(buf, num_bytes); - if (!error.Fail()) - SeekFromStart(cur); + long cur = ::lseek(m_descriptor, 0, SEEK_CUR); + SeekFromStart(offset); + error = Read(buf, num_bytes); + if (!error.Fail()) + SeekFromStart(cur); #endif - return error; + return error; } -Error -File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) -{ - Error error; - - if (num_bytes > 0) - { - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == 0) - { - if (file_stats.st_size > offset) - { - const size_t bytes_left = file_stats.st_size - offset; - if (num_bytes > bytes_left) - num_bytes = bytes_left; - - size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); - std::unique_ptr data_heap_ap; - data_heap_ap.reset(new DataBufferHeap()); - data_heap_ap->SetByteSize(num_bytes_plus_nul_char); - - if (data_heap_ap.get()) - { - error = Read (data_heap_ap->GetBytes(), num_bytes, offset); - if (error.Success()) - { - // Make sure we read exactly what we asked for and if we got - // less, adjust the array - if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) - data_heap_ap->SetByteSize(num_bytes_plus_nul_char); - data_buffer_sp.reset(data_heap_ap.release()); - return error; - } - } - } - else - error.SetErrorString("file is empty"); +Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, + DataBufferSP &data_buffer_sp) { + Error error; + + if (num_bytes > 0) { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + struct stat file_stats; + if (::fstat(fd, &file_stats) == 0) { + if (file_stats.st_size > offset) { + const size_t bytes_left = file_stats.st_size - offset; + if (num_bytes > bytes_left) + num_bytes = bytes_left; + + size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); + std::unique_ptr data_heap_ap; + data_heap_ap.reset(new DataBufferHeap()); + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); + + if (data_heap_ap.get()) { + error = Read(data_heap_ap->GetBytes(), num_bytes, offset); + if (error.Success()) { + // Make sure we read exactly what we asked for and if we got + // less, adjust the array + if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); + data_buffer_sp.reset(data_heap_ap.release()); + return error; } - else - error.SetErrorToErrno(); - } - else - error.SetErrorString("invalid file handle"); - } - else - error.SetErrorString("invalid file handle"); + } + } else + error.SetErrorString("file is empty"); + } else + error.SetErrorToErrno(); + } else + error.SetErrorString("invalid file handle"); + } else + error.SetErrorString("invalid file handle"); - num_bytes = 0; - data_buffer_sp.reset(); - return error; + num_bytes = 0; + data_buffer_sp.reset(); + return error; } -Error -File::Write (const void *buf, size_t &num_bytes, off_t &offset) -{ - Error error; - -#if defined (MAX_WRITE_SIZE) - if (num_bytes > MAX_WRITE_SIZE) - { - const uint8_t *p = (const uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes written to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_WRITE_SIZE) - curr_num_bytes = MAX_WRITE_SIZE; - else - curr_num_bytes = bytes_left; - - error = Write (p + num_bytes, curr_num_bytes, offset); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; +Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) { + Error error; + +#if defined(MAX_WRITE_SIZE) + if (num_bytes > MAX_WRITE_SIZE) { + const uint8_t *p = (const uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes written to zero + num_bytes = 0; + + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_WRITE_SIZE) + curr_num_bytes = MAX_WRITE_SIZE; + else + curr_num_bytes = bytes_left; + + error = Write(p + num_bytes, curr_num_bytes, offset); + + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } + return error; + } #endif - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { #ifndef _WIN32 - ssize_t bytes_written = -1; - do - { - bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); - } while (bytes_written < 0 && errno == EINTR); - - if (bytes_written < 0) - { - num_bytes = 0; - error.SetErrorToErrno(); - } - else - { - offset += bytes_written; - num_bytes = bytes_written; - } + ssize_t bytes_written = -1; + do { + bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); + } while (bytes_written < 0 && errno == EINTR); + + if (bytes_written < 0) { + num_bytes = 0; + error.SetErrorToErrno(); + } else { + offset += bytes_written; + num_bytes = bytes_written; + } #else - long cur = ::lseek(m_descriptor, 0, SEEK_CUR); - error = Write(buf, num_bytes); - long after = ::lseek(m_descriptor, 0, SEEK_CUR); + long cur = ::lseek(m_descriptor, 0, SEEK_CUR); + error = Write(buf, num_bytes); + long after = ::lseek(m_descriptor, 0, SEEK_CUR); - if (!error.Fail()) - SeekFromStart(cur); + if (!error.Fail()) + SeekFromStart(cur); - offset = after; + offset = after; #endif - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } - return error; + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } + return error; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -File::Printf (const char *format, ...) -{ - va_list args; - va_start (args, format); - size_t result = PrintfVarArg (format, args); - va_end (args); - return result; +size_t File::Printf(const char *format, ...) { + va_list args; + va_start(args, format); + size_t result = PrintfVarArg(format, args); + va_end(args); + return result; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -File::PrintfVarArg (const char *format, va_list args) -{ - size_t result = 0; - if (DescriptorIsValid()) - { - char *s = NULL; - result = vasprintf(&s, format, args); - if (s != NULL) - { - if (result > 0) - { - size_t s_len = result; - Write (s, s_len); - result = s_len; - } - free (s); - } - } - else if (StreamIsValid()) - { - result = ::vfprintf (m_stream, format, args); - } - return result; -} - -mode_t -File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) -{ - mode_t mode = 0; - if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) - mode |= O_RDWR; - else if (open_options & eOpenOptionWrite) - mode |= O_WRONLY; - - if (open_options & eOpenOptionAppend) - mode |= O_APPEND; - - if (open_options & eOpenOptionTruncate) - mode |= O_TRUNC; - - if (open_options & eOpenOptionNonBlocking) - mode |= O_NONBLOCK; - - if (open_options & eOpenOptionCanCreateNewOnly) - mode |= O_CREAT | O_EXCL; - else if (open_options & eOpenOptionCanCreate) - mode |= O_CREAT; - - return mode; -} - -void -File::CalculateInteractiveAndTerminal () -{ - const int fd = GetDescriptor(); - if (fd >= 0) - { - m_is_interactive = eLazyBoolNo; - m_is_real_terminal = eLazyBoolNo; +size_t File::PrintfVarArg(const char *format, va_list args) { + size_t result = 0; + if (DescriptorIsValid()) { + char *s = NULL; + result = vasprintf(&s, format, args); + if (s != NULL) { + if (result > 0) { + size_t s_len = result; + Write(s, s_len); + result = s_len; + } + free(s); + } + } else if (StreamIsValid()) { + result = ::vfprintf(m_stream, format, args); + } + return result; +} + +mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { + mode_t mode = 0; + if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) + mode |= O_RDWR; + else if (open_options & eOpenOptionWrite) + mode |= O_WRONLY; + + if (open_options & eOpenOptionAppend) + mode |= O_APPEND; + + if (open_options & eOpenOptionTruncate) + mode |= O_TRUNC; + + if (open_options & eOpenOptionNonBlocking) + mode |= O_NONBLOCK; + + if (open_options & eOpenOptionCanCreateNewOnly) + mode |= O_CREAT | O_EXCL; + else if (open_options & eOpenOptionCanCreate) + mode |= O_CREAT; + + return mode; +} + +void File::CalculateInteractiveAndTerminal() { + const int fd = GetDescriptor(); + if (fd >= 0) { + m_is_interactive = eLazyBoolNo; + m_is_real_terminal = eLazyBoolNo; #if defined(_WIN32) - if (_isatty(fd)) - { - m_is_interactive = eLazyBoolYes; - m_is_real_terminal = eLazyBoolYes; - } + if (_isatty(fd)) { + m_is_interactive = eLazyBoolYes; + m_is_real_terminal = eLazyBoolYes; + } #else - if (isatty(fd)) - { - m_is_interactive = eLazyBoolYes; - struct winsize window_size; - if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) - { - if (window_size.ws_col > 0) - { - m_is_real_terminal = eLazyBoolYes; - if (llvm::sys::Process::FileDescriptorHasColors(fd)) - m_supports_colors = eLazyBoolYes; - } - } + if (isatty(fd)) { + m_is_interactive = eLazyBoolYes; + struct winsize window_size; + if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { + if (window_size.ws_col > 0) { + m_is_real_terminal = eLazyBoolYes; + if (llvm::sys::Process::FileDescriptorHasColors(fd)) + m_supports_colors = eLazyBoolYes; } -#endif + } } +#endif + } } -bool -File::GetIsInteractive () -{ - if (m_is_interactive == eLazyBoolCalculate) - CalculateInteractiveAndTerminal (); - return m_is_interactive == eLazyBoolYes; +bool File::GetIsInteractive() { + if (m_is_interactive == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_interactive == eLazyBoolYes; } -bool -File::GetIsRealTerminal () -{ - if (m_is_real_terminal == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_is_real_terminal == eLazyBoolYes; +bool File::GetIsRealTerminal() { + if (m_is_real_terminal == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_real_terminal == eLazyBoolYes; } -bool -File::GetIsTerminalWithColors () -{ - if (m_supports_colors == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_supports_colors == eLazyBoolYes; +bool File::GetIsTerminalWithColors() { + if (m_supports_colors == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_supports_colors == eLazyBoolYes; } - diff --git a/lldb/source/Host/common/FileCache.cpp b/lldb/source/Host/common/FileCache.cpp index 96b2a2ec02a..db71813e4ff 100644 --- a/lldb/source/Host/common/FileCache.cpp +++ b/lldb/source/Host/common/FileCache.cpp @@ -16,112 +16,97 @@ using namespace lldb_private; FileCache *FileCache::m_instance = nullptr; -FileCache & -FileCache::GetInstance() -{ - if (m_instance == nullptr) - m_instance = new FileCache(); +FileCache &FileCache::GetInstance() { + if (m_instance == nullptr) + m_instance = new FileCache(); - return *m_instance; + return *m_instance; } -lldb::user_id_t -FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, uint32_t mode, Error &error) -{ - std::string path(file_spec.GetPath()); - if (path.empty()) - { - error.SetErrorString("empty path"); - return UINT64_MAX; - } - FileSP file_sp(new File()); - error = file_sp->Open(path.c_str(), flags, mode); - if (file_sp->IsValid() == false) - return UINT64_MAX; - lldb::user_id_t fd = file_sp->GetDescriptor(); - m_cache[fd] = file_sp; - return fd; +lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, + uint32_t mode, Error &error) { + std::string path(file_spec.GetPath()); + if (path.empty()) { + error.SetErrorString("empty path"); + return UINT64_MAX; + } + FileSP file_sp(new File()); + error = file_sp->Open(path.c_str(), flags, mode); + if (file_sp->IsValid() == false) + return UINT64_MAX; + lldb::user_id_t fd = file_sp->GetDescriptor(); + m_cache[fd] = file_sp; + return fd; } -bool -FileCache::CloseFile(lldb::user_id_t fd, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return false; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return false; - } - error = file_sp->Close(); - m_cache.erase(pos); - return error.Success(); +bool FileCache::CloseFile(lldb::user_id_t fd, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return false; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return false; + } + error = file_sp->Close(); + m_cache.erase(pos); + return error.Success(); } -uint64_t -FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return UINT64_MAX; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return UINT64_MAX; - } - if (static_cast(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail()) - return UINT64_MAX; - size_t bytes_written = src_len; - error = file_sp->Write(src, bytes_written); - if (error.Fail()) - return UINT64_MAX; - return bytes_written; +uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, + const void *src, uint64_t src_len, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return UINT64_MAX; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return UINT64_MAX; + } + if (static_cast(file_sp->SeekFromStart(offset, &error)) != offset || + error.Fail()) + return UINT64_MAX; + size_t bytes_written = src_len; + error = file_sp->Write(src, bytes_written); + if (error.Fail()) + return UINT64_MAX; + return bytes_written; } -uint64_t -FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return UINT64_MAX; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return UINT64_MAX; - } - if (static_cast(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail()) - return UINT64_MAX; - size_t bytes_read = dst_len; - error = file_sp->Read(dst, bytes_read); - if (error.Fail()) - return UINT64_MAX; - return bytes_read; +uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, + uint64_t dst_len, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return UINT64_MAX; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return UINT64_MAX; + } + if (static_cast(file_sp->SeekFromStart(offset, &error)) != offset || + error.Fail()) + return UINT64_MAX; + size_t bytes_read = dst_len; + error = file_sp->Read(dst, bytes_read); + if (error.Fail()) + return UINT64_MAX; + return bytes_read; } diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 62117b78f06..0f2a6641f99 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef _WIN32 #include #else @@ -17,9 +16,9 @@ #ifndef _MSC_VER #include #endif +#include #include #include -#include #include "lldb/Host/Config.h" // Have to include this before we test the define... #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER @@ -30,8 +29,8 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataBufferMemoryMap.h" #include "lldb/Core/RegularExpression.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" @@ -49,339 +48,291 @@ using namespace lldb_private; namespace { -bool -PathSyntaxIsPosix(FileSpec::PathSyntax syntax) -{ - return (syntax == FileSpec::ePathSyntaxPosix || - (syntax == FileSpec::ePathSyntaxHostNative && - FileSystem::GetNativePathSyntax() == FileSpec::ePathSyntaxPosix)); +bool PathSyntaxIsPosix(FileSpec::PathSyntax syntax) { + return (syntax == FileSpec::ePathSyntaxPosix || + (syntax == FileSpec::ePathSyntaxHostNative && + FileSystem::GetNativePathSyntax() == FileSpec::ePathSyntaxPosix)); } -const char * -GetPathSeparators(FileSpec::PathSyntax syntax) -{ - return PathSyntaxIsPosix(syntax) ? "/" : "\\/"; +const char *GetPathSeparators(FileSpec::PathSyntax syntax) { + return PathSyntaxIsPosix(syntax) ? "/" : "\\/"; } -char -GetPrefferedPathSeparator(FileSpec::PathSyntax syntax) -{ - return GetPathSeparators(syntax)[0]; +char GetPrefferedPathSeparator(FileSpec::PathSyntax syntax) { + return GetPathSeparators(syntax)[0]; } -bool -IsPathSeparator(char value, FileSpec::PathSyntax syntax) -{ - return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\'); +bool IsPathSeparator(char value, FileSpec::PathSyntax syntax) { + return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\'); } -void -Normalize(llvm::SmallVectorImpl &path, FileSpec::PathSyntax syntax) -{ - if (PathSyntaxIsPosix(syntax)) return; +void Normalize(llvm::SmallVectorImpl &path, FileSpec::PathSyntax syntax) { + if (PathSyntaxIsPosix(syntax)) + return; - std::replace(path.begin(), path.end(), '\\', '/'); - // Windows path can have \\ slashes which can be changed by replace - // call above to //. Here we remove the duplicate. - auto iter = std::unique ( path.begin(), path.end(), - []( char &c1, char &c2 ){ - return (c1 == '/' && c2 == '/');}); - path.erase(iter, path.end()); + std::replace(path.begin(), path.end(), '\\', '/'); + // Windows path can have \\ slashes which can be changed by replace + // call above to //. Here we remove the duplicate. + auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) { + return (c1 == '/' && c2 == '/'); + }); + path.erase(iter, path.end()); } -void -Denormalize(llvm::SmallVectorImpl &path, FileSpec::PathSyntax syntax) -{ - if (PathSyntaxIsPosix(syntax)) return; +void Denormalize(llvm::SmallVectorImpl &path, + FileSpec::PathSyntax syntax) { + if (PathSyntaxIsPosix(syntax)) + return; - std::replace(path.begin(), path.end(), '/', '\\'); + std::replace(path.begin(), path.end(), '/', '\\'); } -bool -GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr) -{ - char resolved_path[PATH_MAX]; - if (file_spec->GetPath (resolved_path, sizeof(resolved_path))) - return FileSystem::Stat(resolved_path, stats_ptr) == 0; - return false; +bool GetFileStats(const FileSpec *file_spec, struct stat *stats_ptr) { + char resolved_path[PATH_MAX]; + if (file_spec->GetPath(resolved_path, sizeof(resolved_path))) + return FileSystem::Stat(resolved_path, stats_ptr) == 0; + return false; } -size_t -FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) -{ - if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) - return 0; +size_t FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) { + if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) + return 0; - if (str.size() > 0 && IsPathSeparator(str.back(), syntax)) - return str.size() - 1; + if (str.size() > 0 && IsPathSeparator(str.back(), syntax)) + return str.size() - 1; - size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1); + size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1); - if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos) - pos = str.find_last_of(':', str.size() - 2); + if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos) + pos = str.find_last_of(':', str.size() - 2); - if (pos == llvm::StringRef::npos || (pos == 1 && IsPathSeparator(str[0], syntax))) - return 0; + if (pos == llvm::StringRef::npos || + (pos == 1 && IsPathSeparator(str[0], syntax))) + return 0; - return pos + 1; + return pos + 1; } -size_t -RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) -{ - // case "c:/" - if (!PathSyntaxIsPosix(syntax) && (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax))) - return 2; +size_t RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) { + // case "c:/" + if (!PathSyntaxIsPosix(syntax) && + (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax))) + return 2; - // case "//" - if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) - return llvm::StringRef::npos; + // case "//" + if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) + return llvm::StringRef::npos; - // case "//net" - if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] && !IsPathSeparator(str[2], syntax)) - return str.find_first_of(GetPathSeparators(syntax), 2); + // case "//net" + if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] && + !IsPathSeparator(str[2], syntax)) + return str.find_first_of(GetPathSeparators(syntax), 2); - // case "/" - if (str.size() > 0 && IsPathSeparator(str[0], syntax)) - return 0; + // case "/" + if (str.size() > 0 && IsPathSeparator(str[0], syntax)) + return 0; - return llvm::StringRef::npos; + return llvm::StringRef::npos; } -size_t -ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) -{ - size_t end_pos = FilenamePos(path, syntax); +size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) { + size_t end_pos = FilenamePos(path, syntax); - bool filename_was_sep = path.size() > 0 && IsPathSeparator(path[end_pos], syntax); + bool filename_was_sep = + path.size() > 0 && IsPathSeparator(path[end_pos], syntax); - // Skip separators except for root dir. - size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax); + // Skip separators except for root dir. + size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax); - while (end_pos > 0 && (end_pos - 1) != root_dir_pos && IsPathSeparator(path[end_pos - 1], syntax)) - --end_pos; + while (end_pos > 0 && (end_pos - 1) != root_dir_pos && + IsPathSeparator(path[end_pos - 1], syntax)) + --end_pos; - if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) - return llvm::StringRef::npos; + if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) + return llvm::StringRef::npos; - return end_pos; + return end_pos; } } // end anonymous namespace // Resolves the username part of a path of the form ~user/other/directories, and -// writes the result into dst_path. This will also resolve "~" to the current user. -// If you want to complete "~" to the list of users, pass it to ResolvePartialUsername. -void -FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) -{ +// writes the result into dst_path. This will also resolve "~" to the current +// user. +// If you want to complete "~" to the list of users, pass it to +// ResolvePartialUsername. +void FileSpec::ResolveUsername(llvm::SmallVectorImpl &path) { #if LLDB_CONFIG_TILDE_RESOLVES_TO_USER - if (path.empty() || path[0] != '~') - return; - - llvm::StringRef path_str(path.data(), path.size()); - size_t slash_pos = path_str.find('/', 1); - if (slash_pos == 1 || path.size() == 1) - { - // A path of ~/ resolves to the current user's home dir - llvm::SmallString<64> home_dir; - // llvm::sys::path::home_directory() only checks if "HOME" is set in the - // environment and does nothing else to locate the user home directory - if (!llvm::sys::path::home_directory(home_dir)) - { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir && pw->pw_dir[0]) - { - // Update our environemnt so llvm::sys::path::home_directory() works next time - setenv("HOME", pw->pw_dir, 0); - home_dir.assign(llvm::StringRef(pw->pw_dir)); - } - else - { - return; - } - } - - // Overwrite the ~ with the first character of the homedir, and insert - // the rest. This way we only trigger one move, whereas an insert - // followed by a delete (or vice versa) would trigger two. - path[0] = home_dir[0]; - path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end()); + if (path.empty() || path[0] != '~') + return; + + llvm::StringRef path_str(path.data(), path.size()); + size_t slash_pos = path_str.find('/', 1); + if (slash_pos == 1 || path.size() == 1) { + // A path of ~/ resolves to the current user's home dir + llvm::SmallString<64> home_dir; + // llvm::sys::path::home_directory() only checks if "HOME" is set in the + // environment and does nothing else to locate the user home directory + if (!llvm::sys::path::home_directory(home_dir)) { + struct passwd *pw = getpwuid(getuid()); + if (pw && pw->pw_dir && pw->pw_dir[0]) { + // Update our environemnt so llvm::sys::path::home_directory() works + // next time + setenv("HOME", pw->pw_dir, 0); + home_dir.assign(llvm::StringRef(pw->pw_dir)); + } else { return; + } } - - auto username_begin = path.begin()+1; - auto username_end = (slash_pos == llvm::StringRef::npos) - ? path.end() - : (path.begin() + slash_pos); - size_t replacement_length = std::distance(path.begin(), username_end); - - llvm::SmallString<20> username(username_begin, username_end); - struct passwd *user_entry = ::getpwnam(username.c_str()); - if (user_entry != nullptr) - { - // Copy over the first n characters of the path, where n is the smaller of the length - // of the home directory and the slash pos. - llvm::StringRef homedir(user_entry->pw_dir); - size_t initial_copy_length = std::min(homedir.size(), replacement_length); - auto src_begin = homedir.begin(); - auto src_end = src_begin + initial_copy_length; - std::copy(src_begin, src_end, path.begin()); - if (replacement_length > homedir.size()) - { - // We copied the entire home directory, but the ~username portion of the path was - // longer, so there's characters that need to be removed. - path.erase(path.begin() + initial_copy_length, username_end); - } - else if (replacement_length < homedir.size()) - { - // We copied all the way up to the slash in the destination, but there's still more - // characters that need to be inserted. - path.insert(username_end, src_end, homedir.end()); - } - } - else - { - // Unable to resolve username (user doesn't exist?) - path.clear(); + + // Overwrite the ~ with the first character of the homedir, and insert + // the rest. This way we only trigger one move, whereas an insert + // followed by a delete (or vice versa) would trigger two. + path[0] = home_dir[0]; + path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end()); + return; + } + + auto username_begin = path.begin() + 1; + auto username_end = (slash_pos == llvm::StringRef::npos) + ? path.end() + : (path.begin() + slash_pos); + size_t replacement_length = std::distance(path.begin(), username_end); + + llvm::SmallString<20> username(username_begin, username_end); + struct passwd *user_entry = ::getpwnam(username.c_str()); + if (user_entry != nullptr) { + // Copy over the first n characters of the path, where n is the smaller of + // the length + // of the home directory and the slash pos. + llvm::StringRef homedir(user_entry->pw_dir); + size_t initial_copy_length = std::min(homedir.size(), replacement_length); + auto src_begin = homedir.begin(); + auto src_end = src_begin + initial_copy_length; + std::copy(src_begin, src_end, path.begin()); + if (replacement_length > homedir.size()) { + // We copied the entire home directory, but the ~username portion of the + // path was + // longer, so there's characters that need to be removed. + path.erase(path.begin() + initial_copy_length, username_end); + } else if (replacement_length < homedir.size()) { + // We copied all the way up to the slash in the destination, but there's + // still more + // characters that need to be inserted. + path.insert(username_end, src_end, homedir.end()); } + } else { + // Unable to resolve username (user doesn't exist?) + path.clear(); + } #endif } -size_t -FileSpec::ResolvePartialUsername (const char *partial_name, StringList &matches) -{ +size_t FileSpec::ResolvePartialUsername(const char *partial_name, + StringList &matches) { #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - size_t extant_entries = matches.GetSize(); - - setpwent(); - struct passwd *user_entry; - const char *name_start = partial_name + 1; - std::set name_list; - - while ((user_entry = getpwent()) != NULL) - { - if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) - { - std::string tmp_buf("~"); - tmp_buf.append(user_entry->pw_name); - tmp_buf.push_back('/'); - name_list.insert(tmp_buf); - } + size_t extant_entries = matches.GetSize(); + + setpwent(); + struct passwd *user_entry; + const char *name_start = partial_name + 1; + std::set name_list; + + while ((user_entry = getpwent()) != NULL) { + if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) { + std::string tmp_buf("~"); + tmp_buf.append(user_entry->pw_name); + tmp_buf.push_back('/'); + name_list.insert(tmp_buf); } - std::set::iterator pos, end = name_list.end(); - for (pos = name_list.begin(); pos != end; pos++) - { - matches.AppendString((*pos).c_str()); - } - return matches.GetSize() - extant_entries; + } + std::set::iterator pos, end = name_list.end(); + for (pos = name_list.begin(); pos != end; pos++) { + matches.AppendString((*pos).c_str()); + } + return matches.GetSize() - extant_entries; #else - // Resolving home directories is not supported, just copy the path... - return 0; -#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER + // Resolving home directories is not supported, just copy the path... + return 0; +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER } -void -FileSpec::Resolve (llvm::SmallVectorImpl &path) -{ - if (path.empty()) - return; +void FileSpec::Resolve(llvm::SmallVectorImpl &path) { + if (path.empty()) + return; #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - if (path[0] == '~') - ResolveUsername(path); + if (path[0] == '~') + ResolveUsername(path); #endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - // Save a copy of the original path that's passed in - llvm::SmallString<128> original_path(path.begin(), path.end()); + // Save a copy of the original path that's passed in + llvm::SmallString<128> original_path(path.begin(), path.end()); - llvm::sys::fs::make_absolute(path); - if (!llvm::sys::fs::exists(path)) - { - path.clear(); - path.append(original_path.begin(), original_path.end()); - } + llvm::sys::fs::make_absolute(path); + if (!llvm::sys::fs::exists(path)) { + path.clear(); + path.append(original_path.begin(), original_path.end()); + } } -FileSpec::FileSpec() : - m_directory(), - m_filename(), - m_syntax(FileSystem::GetNativePathSyntax()) -{ +FileSpec::FileSpec() + : m_directory(), m_filename(), m_syntax(FileSystem::GetNativePathSyntax()) { } //------------------------------------------------------------------ // Default constructor that can take an optional full path to a // file on disk. //------------------------------------------------------------------ -FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) : - m_directory(), - m_filename(), - m_is_resolved(false), - m_syntax(syntax) -{ - if (pathname && pathname[0]) - SetFile(pathname, resolve_path, syntax); +FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) + : m_directory(), m_filename(), m_is_resolved(false), m_syntax(syntax) { + if (pathname && pathname[0]) + SetFile(pathname, resolve_path, syntax); } -FileSpec::FileSpec(const char *pathname, bool resolve_path, ArchSpec arch) : - FileSpec{pathname, resolve_path, arch.GetTriple().isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix} -{ -} +FileSpec::FileSpec(const char *pathname, bool resolve_path, ArchSpec arch) + : FileSpec{pathname, resolve_path, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix} {} -FileSpec::FileSpec(const std::string &path, bool resolve_path, PathSyntax syntax) : - FileSpec{path.c_str(), resolve_path, syntax} -{ -} +FileSpec::FileSpec(const std::string &path, bool resolve_path, + PathSyntax syntax) + : FileSpec{path.c_str(), resolve_path, syntax} {} -FileSpec::FileSpec(const std::string &path, bool resolve_path, ArchSpec arch) : - FileSpec{path.c_str(), resolve_path, arch} -{ -} +FileSpec::FileSpec(const std::string &path, bool resolve_path, ArchSpec arch) + : FileSpec{path.c_str(), resolve_path, arch} {} //------------------------------------------------------------------ // Copy constructor //------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec& rhs) : - m_directory (rhs.m_directory), - m_filename (rhs.m_filename), - m_is_resolved (rhs.m_is_resolved), - m_syntax (rhs.m_syntax) -{ -} +FileSpec::FileSpec(const FileSpec &rhs) + : m_directory(rhs.m_directory), m_filename(rhs.m_filename), + m_is_resolved(rhs.m_is_resolved), m_syntax(rhs.m_syntax) {} //------------------------------------------------------------------ // Copy constructor //------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec* rhs) : - m_directory(), - m_filename() -{ - if (rhs) - *this = *rhs; +FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() { + if (rhs) + *this = *rhs; } //------------------------------------------------------------------ // Virtual destructor in case anyone inherits from this class. //------------------------------------------------------------------ -FileSpec::~FileSpec() -{ -} +FileSpec::~FileSpec() {} //------------------------------------------------------------------ // Assignment operator. //------------------------------------------------------------------ -const FileSpec& -FileSpec::operator= (const FileSpec& rhs) -{ - if (this != &rhs) - { - m_directory = rhs.m_directory; - m_filename = rhs.m_filename; - m_is_resolved = rhs.m_is_resolved; - m_syntax = rhs.m_syntax; - } - return *this; +const FileSpec &FileSpec::operator=(const FileSpec &rhs) { + if (this != &rhs) { + m_directory = rhs.m_directory; + m_filename = rhs.m_filename; + m_is_resolved = rhs.m_is_resolved; + m_syntax = rhs.m_syntax; + } + return *this; } //------------------------------------------------------------------ @@ -389,66 +340,62 @@ FileSpec::operator= (const FileSpec& rhs) // be split up into a directory and filename and stored as uniqued // string values for quick comparison and efficient memory usage. //------------------------------------------------------------------ -void -FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax) -{ - m_filename.Clear(); - m_directory.Clear(); - m_is_resolved = false; - m_syntax = (syntax == ePathSyntaxHostNative) ? FileSystem::GetNativePathSyntax() : syntax; - - if (pathname == NULL || pathname[0] == '\0') - return; +void FileSpec::SetFile(const char *pathname, bool resolve, PathSyntax syntax) { + m_filename.Clear(); + m_directory.Clear(); + m_is_resolved = false; + m_syntax = (syntax == ePathSyntaxHostNative) + ? FileSystem::GetNativePathSyntax() + : syntax; + + if (pathname == NULL || pathname[0] == '\0') + return; - llvm::SmallString<64> resolved(pathname); + llvm::SmallString<64> resolved(pathname); - if (resolve) - { - FileSpec::Resolve (resolved); - m_is_resolved = true; - } + if (resolve) { + FileSpec::Resolve(resolved); + m_is_resolved = true; + } - Normalize(resolved, syntax); + Normalize(resolved, syntax); - llvm::StringRef resolve_path_ref(resolved.c_str()); - size_t dir_end = ParentPathEnd(resolve_path_ref, syntax); - if (dir_end == 0) - { - m_filename.SetString(resolve_path_ref); - return; - } + llvm::StringRef resolve_path_ref(resolved.c_str()); + size_t dir_end = ParentPathEnd(resolve_path_ref, syntax); + if (dir_end == 0) { + m_filename.SetString(resolve_path_ref); + return; + } - m_directory.SetString(resolve_path_ref.substr(0, dir_end)); + m_directory.SetString(resolve_path_ref.substr(0, dir_end)); - size_t filename_begin = dir_end; - size_t root_dir_start = RootDirStart(resolve_path_ref, syntax); - while (filename_begin != llvm::StringRef::npos && filename_begin < resolve_path_ref.size() && - filename_begin != root_dir_start && IsPathSeparator(resolve_path_ref[filename_begin], syntax)) - ++filename_begin; - m_filename.SetString((filename_begin == llvm::StringRef::npos || filename_begin >= resolve_path_ref.size()) - ? "." - : resolve_path_ref.substr(filename_begin)); + size_t filename_begin = dir_end; + size_t root_dir_start = RootDirStart(resolve_path_ref, syntax); + while (filename_begin != llvm::StringRef::npos && + filename_begin < resolve_path_ref.size() && + filename_begin != root_dir_start && + IsPathSeparator(resolve_path_ref[filename_begin], syntax)) + ++filename_begin; + m_filename.SetString((filename_begin == llvm::StringRef::npos || + filename_begin >= resolve_path_ref.size()) + ? "." + : resolve_path_ref.substr(filename_begin)); } -void -FileSpec::SetFile(const char *pathname, bool resolve, ArchSpec arch) -{ - return SetFile(pathname, resolve, - arch.GetTriple().isOSWindows() - ? ePathSyntaxWindows - : ePathSyntaxPosix); +void FileSpec::SetFile(const char *pathname, bool resolve, ArchSpec arch) { + return SetFile(pathname, resolve, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix); } -void -FileSpec::SetFile(const std::string &pathname, bool resolve, PathSyntax syntax) -{ - return SetFile(pathname.c_str(), resolve, syntax); +void FileSpec::SetFile(const std::string &pathname, bool resolve, + PathSyntax syntax) { + return SetFile(pathname.c_str(), resolve, syntax); } -void -FileSpec::SetFile(const std::string &pathname, bool resolve, ArchSpec arch) -{ - return SetFile(pathname.c_str(), resolve, arch); +void FileSpec::SetFile(const std::string &pathname, bool resolve, + ArchSpec arch) { + return SetFile(pathname.c_str(), resolve, arch); } //---------------------------------------------------------------------- @@ -458,10 +405,7 @@ FileSpec::SetFile(const std::string &pathname, bool resolve, ArchSpec arch) // if (file_spec) // {} //---------------------------------------------------------------------- -FileSpec::operator bool() const -{ - return m_filename || m_directory; -} +FileSpec::operator bool() const { return m_filename || m_directory; } //---------------------------------------------------------------------- // Logical NOT operator. This allows code to check any FileSpec @@ -470,123 +414,96 @@ FileSpec::operator bool() const // if (!file_spec) // {} //---------------------------------------------------------------------- -bool -FileSpec::operator!() const -{ - return !m_directory && !m_filename; -} +bool FileSpec::operator!() const { return !m_directory && !m_filename; } -bool -FileSpec::DirectoryEquals(const FileSpec &rhs) const -{ - const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); - return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive); +bool FileSpec::DirectoryEquals(const FileSpec &rhs) const { + const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); + return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive); } -bool -FileSpec::FileEquals(const FileSpec &rhs) const -{ - const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); - return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive); +bool FileSpec::FileEquals(const FileSpec &rhs) const { + const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); + return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive); } //------------------------------------------------------------------ // Equal to operator //------------------------------------------------------------------ -bool -FileSpec::operator== (const FileSpec& rhs) const -{ - if (!FileEquals(rhs)) - return false; - if (DirectoryEquals(rhs)) - return true; - - // TODO: determine if we want to keep this code in here. - // The code below was added to handle a case where we were - // trying to set a file and line breakpoint and one path - // was resolved, and the other not and the directory was - // in a mount point that resolved to a more complete path: - // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling - // this out... - if (IsResolved() && rhs.IsResolved()) - { - // Both paths are resolved, no need to look further... - return false; - } - - FileSpec resolved_lhs(*this); - - // If "this" isn't resolved, resolve it - if (!IsResolved()) - { - if (resolved_lhs.ResolvePath()) - { - // This path wasn't resolved but now it is. Check if the resolved - // directory is the same as our unresolved directory, and if so, - // we can mark this object as resolved to avoid more future resolves - m_is_resolved = (m_directory == resolved_lhs.m_directory); - } - else - return false; - } - - FileSpec resolved_rhs(rhs); - if (!rhs.IsResolved()) - { - if (resolved_rhs.ResolvePath()) - { - // rhs's path wasn't resolved but now it is. Check if the resolved - // directory is the same as rhs's unresolved directory, and if so, - // we can mark this object as resolved to avoid more future resolves - rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory); - } - else - return false; - } - - // If we reach this point in the code we were able to resolve both paths - // and since we only resolve the paths if the basenames are equal, then - // we can just check if both directories are equal... - return DirectoryEquals(rhs); +bool FileSpec::operator==(const FileSpec &rhs) const { + if (!FileEquals(rhs)) + return false; + if (DirectoryEquals(rhs)) + return true; + + // TODO: determine if we want to keep this code in here. + // The code below was added to handle a case where we were + // trying to set a file and line breakpoint and one path + // was resolved, and the other not and the directory was + // in a mount point that resolved to a more complete path: + // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling + // this out... + if (IsResolved() && rhs.IsResolved()) { + // Both paths are resolved, no need to look further... + return false; + } + + FileSpec resolved_lhs(*this); + + // If "this" isn't resolved, resolve it + if (!IsResolved()) { + if (resolved_lhs.ResolvePath()) { + // This path wasn't resolved but now it is. Check if the resolved + // directory is the same as our unresolved directory, and if so, + // we can mark this object as resolved to avoid more future resolves + m_is_resolved = (m_directory == resolved_lhs.m_directory); + } else + return false; + } + + FileSpec resolved_rhs(rhs); + if (!rhs.IsResolved()) { + if (resolved_rhs.ResolvePath()) { + // rhs's path wasn't resolved but now it is. Check if the resolved + // directory is the same as rhs's unresolved directory, and if so, + // we can mark this object as resolved to avoid more future resolves + rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory); + } else + return false; + } + + // If we reach this point in the code we were able to resolve both paths + // and since we only resolve the paths if the basenames are equal, then + // we can just check if both directories are equal... + return DirectoryEquals(rhs); } //------------------------------------------------------------------ // Not equal to operator //------------------------------------------------------------------ -bool -FileSpec::operator!= (const FileSpec& rhs) const -{ - return !(*this == rhs); -} +bool FileSpec::operator!=(const FileSpec &rhs) const { return !(*this == rhs); } //------------------------------------------------------------------ // Less than operator //------------------------------------------------------------------ -bool -FileSpec::operator< (const FileSpec& rhs) const -{ - return FileSpec::Compare(*this, rhs, true) < 0; +bool FileSpec::operator<(const FileSpec &rhs) const { + return FileSpec::Compare(*this, rhs, true) < 0; } //------------------------------------------------------------------ // Dump a FileSpec object to a stream //------------------------------------------------------------------ -Stream& -lldb_private::operator << (Stream &s, const FileSpec& f) -{ - f.Dump(&s); - return s; +Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) { + f.Dump(&s); + return s; } //------------------------------------------------------------------ // Clear this object by releasing both the directory and filename // string values and making them both the empty string. //------------------------------------------------------------------ -void -FileSpec::Clear() -{ - m_directory.Clear(); - m_filename.Clear(); +void FileSpec::Clear() { + m_directory.Clear(); + m_filename.Clear(); } //------------------------------------------------------------------ @@ -600,166 +517,148 @@ FileSpec::Clear() // Return -1 if the "a" is less than "b", 0 if "a" is equal to "b" // and "1" if "a" is greater than "b". //------------------------------------------------------------------ -int -FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full) -{ - int result = 0; - - // case sensitivity of compare - const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - - // If full is true, then we must compare both the directory and filename. - - // If full is false, then if either directory is empty, then we match on - // the basename only, and if both directories have valid values, we still - // do a full compare. This allows for matching when we just have a filename - // in one of the FileSpec objects. - - if (full || (a.m_directory && b.m_directory)) - { - result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive); - if (result) - return result; - } - return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive); -} - -bool -FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full, bool remove_backups) -{ - // case sensitivity of equality test - const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - - if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) - return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive); - else if (remove_backups == false) - return a == b; - else - { - if (!ConstString::Equals(a.m_filename, b.m_filename, case_sensitive)) - return false; - if (ConstString::Equals(a.m_directory, b.m_directory, case_sensitive)) - return true; - ConstString a_without_dots; - ConstString b_without_dots; +int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) { + int result = 0; + + // case sensitivity of compare + const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); + + // If full is true, then we must compare both the directory and filename. + + // If full is false, then if either directory is empty, then we match on + // the basename only, and if both directories have valid values, we still + // do a full compare. This allows for matching when we just have a filename + // in one of the FileSpec objects. + + if (full || (a.m_directory && b.m_directory)) { + result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive); + if (result) + return result; + } + return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive); +} + +bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full, + bool remove_backups) { + // case sensitivity of equality test + const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); + + if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) + return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive); + else if (remove_backups == false) + return a == b; + else { + if (!ConstString::Equals(a.m_filename, b.m_filename, case_sensitive)) + return false; + if (ConstString::Equals(a.m_directory, b.m_directory, case_sensitive)) + return true; + ConstString a_without_dots; + ConstString b_without_dots; + + RemoveBackupDots(a.m_directory, a_without_dots); + RemoveBackupDots(b.m_directory, b_without_dots); + return ConstString::Equals(a_without_dots, b_without_dots, case_sensitive); + } +} + +void FileSpec::NormalizePath() { + ConstString normalized_directory; + FileSpec::RemoveBackupDots(m_directory, normalized_directory); + m_directory = normalized_directory; +} + +void FileSpec::RemoveBackupDots(const ConstString &input_const_str, + ConstString &result_const_str) { + const char *input = input_const_str.GetCString(); + result_const_str.Clear(); + if (!input || input[0] == '\0') + return; - RemoveBackupDots (a.m_directory, a_without_dots); - RemoveBackupDots (b.m_directory, b_without_dots); - return ConstString::Equals(a_without_dots, b_without_dots, case_sensitive); + const char win_sep = '\\'; + const char unix_sep = '/'; + char found_sep; + const char *win_backup = "\\.."; + const char *unix_backup = "/.."; + + bool is_win = false; + + // Determine the platform for the path (win or unix): + + if (input[0] == win_sep) + is_win = true; + else if (input[0] == unix_sep) + is_win = false; + else if (input[1] == ':') + is_win = true; + else if (strchr(input, unix_sep) != nullptr) + is_win = false; + else if (strchr(input, win_sep) != nullptr) + is_win = true; + else { + // No separators at all, no reason to do any work here. + result_const_str = input_const_str; + return; + } + + llvm::StringRef backup_sep; + if (is_win) { + found_sep = win_sep; + backup_sep = win_backup; + } else { + found_sep = unix_sep; + backup_sep = unix_backup; + } + + llvm::StringRef input_ref(input); + llvm::StringRef curpos(input); + + bool had_dots = false; + std::string result; + + while (1) { + // Start of loop + llvm::StringRef before_sep; + std::pair around_sep = + curpos.split(backup_sep); + + before_sep = around_sep.first; + curpos = around_sep.second; + + if (curpos.empty()) { + if (had_dots) { + while (before_sep.startswith("//")) + before_sep = before_sep.substr(1); + if (!before_sep.empty()) { + result.append(before_sep.data(), before_sep.size()); + } + } + break; } -} - -void -FileSpec::NormalizePath () -{ - ConstString normalized_directory; - FileSpec::RemoveBackupDots(m_directory, normalized_directory); - m_directory = normalized_directory; -} + had_dots = true; -void -FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str) -{ - const char *input = input_const_str.GetCString(); - result_const_str.Clear(); - if (!input || input[0] == '\0') - return; + unsigned num_backups = 1; + while (curpos.startswith(backup_sep)) { + num_backups++; + curpos = curpos.slice(backup_sep.size(), curpos.size()); + } - const char win_sep = '\\'; - const char unix_sep = '/'; - char found_sep; - const char *win_backup = "\\.."; - const char *unix_backup = "/.."; - - bool is_win = false; - - // Determine the platform for the path (win or unix): - - if (input[0] == win_sep) - is_win = true; - else if (input[0] == unix_sep) - is_win = false; - else if (input[1] == ':') - is_win = true; - else if (strchr(input, unix_sep) != nullptr) - is_win = false; - else if (strchr(input, win_sep) != nullptr) - is_win = true; - else - { - // No separators at all, no reason to do any work here. + size_t end_pos = before_sep.size(); + while (num_backups-- > 0) { + end_pos = before_sep.rfind(found_sep, end_pos); + if (end_pos == llvm::StringRef::npos) { result_const_str = input_const_str; return; + } } + result.append(before_sep.data(), end_pos); + } - llvm::StringRef backup_sep; - if (is_win) - { - found_sep = win_sep; - backup_sep = win_backup; - } - else - { - found_sep = unix_sep; - backup_sep = unix_backup; - } - - llvm::StringRef input_ref(input); - llvm::StringRef curpos(input); - - bool had_dots = false; - std::string result; - - while (1) - { - // Start of loop - llvm::StringRef before_sep; - std::pair around_sep = curpos.split(backup_sep); - - before_sep = around_sep.first; - curpos = around_sep.second; - - if (curpos.empty()) - { - if (had_dots) - { - while (before_sep.startswith("//")) - before_sep = before_sep.substr(1); - if (!before_sep.empty()) - { - result.append(before_sep.data(), before_sep.size()); - } - } - break; - } - had_dots = true; - - unsigned num_backups = 1; - while (curpos.startswith(backup_sep)) - { - num_backups++; - curpos = curpos.slice(backup_sep.size(), curpos.size()); - } - - size_t end_pos = before_sep.size(); - while (num_backups-- > 0) - { - end_pos = before_sep.rfind(found_sep, end_pos); - if (end_pos == llvm::StringRef::npos) - { - result_const_str = input_const_str; - return; - } - } - result.append(before_sep.data(), end_pos); - } + if (had_dots) + result_const_str.SetCString(result.c_str()); + else + result_const_str = input_const_str; - if (had_dots) - result_const_str.SetCString(result.c_str()); - else - result_const_str = input_const_str; - - return; + return; } //------------------------------------------------------------------ @@ -767,279 +666,230 @@ FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &res // a valid directory name, it will be displayed followed by a // directory delimiter, and the filename. //------------------------------------------------------------------ -void -FileSpec::Dump(Stream *s) const -{ - if (s) - { - std::string path{GetPath(true)}; - s->PutCString(path.c_str()); - char path_separator = GetPrefferedPathSeparator(m_syntax); - if (!m_filename && !path.empty() && path.back() != path_separator) - s->PutChar(path_separator); - } +void FileSpec::Dump(Stream *s) const { + if (s) { + std::string path{GetPath(true)}; + s->PutCString(path.c_str()); + char path_separator = GetPrefferedPathSeparator(m_syntax); + if (!m_filename && !path.empty() && path.back() != path_separator) + s->PutChar(path_separator); + } } //------------------------------------------------------------------ // Returns true if the file exists. //------------------------------------------------------------------ -bool -FileSpec::Exists () const -{ - struct stat file_stats; - return GetFileStats (this, &file_stats); -} - -bool -FileSpec::Readable () const -{ - const uint32_t permissions = GetPermissions(); - if (permissions & eFilePermissionsEveryoneR) - return true; - return false; -} - -bool -FileSpec::ResolveExecutableLocation () -{ - if (!m_directory) - { - const char *file_cstr = m_filename.GetCString(); - if (file_cstr) - { - const std::string file_str (file_cstr); - llvm::ErrorOr error_or_path = llvm::sys::findProgramByName (file_str); - if (!error_or_path) - return false; - std::string path = error_or_path.get(); - llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); - if (!dir_ref.empty()) - { - // FindProgramByName returns "." if it can't find the file. - if (strcmp (".", dir_ref.data()) == 0) - return false; - - m_directory.SetCString (dir_ref.data()); - if (Exists()) - return true; - else - { - // If FindProgramByName found the file, it returns the directory + filename in its return results. - // We need to separate them. - FileSpec tmp_file (dir_ref.data(), false); - if (tmp_file.Exists()) - { - m_directory = tmp_file.m_directory; - return true; - } - } - } +bool FileSpec::Exists() const { + struct stat file_stats; + return GetFileStats(this, &file_stats); +} + +bool FileSpec::Readable() const { + const uint32_t permissions = GetPermissions(); + if (permissions & eFilePermissionsEveryoneR) + return true; + return false; +} + +bool FileSpec::ResolveExecutableLocation() { + if (!m_directory) { + const char *file_cstr = m_filename.GetCString(); + if (file_cstr) { + const std::string file_str(file_cstr); + llvm::ErrorOr error_or_path = + llvm::sys::findProgramByName(file_str); + if (!error_or_path) + return false; + std::string path = error_or_path.get(); + llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); + if (!dir_ref.empty()) { + // FindProgramByName returns "." if it can't find the file. + if (strcmp(".", dir_ref.data()) == 0) + return false; + + m_directory.SetCString(dir_ref.data()); + if (Exists()) + return true; + else { + // If FindProgramByName found the file, it returns the directory + + // filename in its return results. + // We need to separate them. + FileSpec tmp_file(dir_ref.data(), false); + if (tmp_file.Exists()) { + m_directory = tmp_file.m_directory; + return true; + } } + } } - - return false; + } + + return false; } -bool -FileSpec::ResolvePath () -{ - if (m_is_resolved) - return true; // We have already resolved this path +bool FileSpec::ResolvePath() { + if (m_is_resolved) + return true; // We have already resolved this path - char path_buf[PATH_MAX]; - if (!GetPath (path_buf, PATH_MAX, false)) - return false; - // SetFile(...) will set m_is_resolved correctly if it can resolve the path - SetFile (path_buf, true); - return m_is_resolved; + char path_buf[PATH_MAX]; + if (!GetPath(path_buf, PATH_MAX, false)) + return false; + // SetFile(...) will set m_is_resolved correctly if it can resolve the path + SetFile(path_buf, true); + return m_is_resolved; } -uint64_t -FileSpec::GetByteSize() const -{ - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - return file_stats.st_size; - return 0; +uint64_t FileSpec::GetByteSize() const { + struct stat file_stats; + if (GetFileStats(this, &file_stats)) + return file_stats.st_size; + return 0; } -FileSpec::PathSyntax -FileSpec::GetPathSyntax() const -{ - return m_syntax; -} +FileSpec::PathSyntax FileSpec::GetPathSyntax() const { return m_syntax; } -FileSpec::FileType -FileSpec::GetFileType () const -{ - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - { - mode_t file_type = file_stats.st_mode & S_IFMT; - switch (file_type) - { - case S_IFDIR: return eFileTypeDirectory; - case S_IFREG: return eFileTypeRegular; +FileSpec::FileType FileSpec::GetFileType() const { + struct stat file_stats; + if (GetFileStats(this, &file_stats)) { + mode_t file_type = file_stats.st_mode & S_IFMT; + switch (file_type) { + case S_IFDIR: + return eFileTypeDirectory; + case S_IFREG: + return eFileTypeRegular; #ifndef _WIN32 - case S_IFIFO: return eFileTypePipe; - case S_IFSOCK: return eFileTypeSocket; - case S_IFLNK: return eFileTypeSymbolicLink; + case S_IFIFO: + return eFileTypePipe; + case S_IFSOCK: + return eFileTypeSocket; + case S_IFLNK: + return eFileTypeSymbolicLink; #endif - default: - break; - } - return eFileTypeUnknown; + default: + break; } - return eFileTypeInvalid; + return eFileTypeUnknown; + } + return eFileTypeInvalid; } -bool -FileSpec::IsSymbolicLink () const -{ - char resolved_path[PATH_MAX]; - if (!GetPath (resolved_path, sizeof (resolved_path))) - return false; +bool FileSpec::IsSymbolicLink() const { + char resolved_path[PATH_MAX]; + if (!GetPath(resolved_path, sizeof(resolved_path))) + return false; #ifdef _WIN32 - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(resolved_path, wpath)) - return false; - auto attrs = ::GetFileAttributesW(wpath.c_str()); - if (attrs == INVALID_FILE_ATTRIBUTES) - return false; + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(resolved_path, wpath)) + return false; + auto attrs = ::GetFileAttributesW(wpath.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) + return false; - return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); + return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); #else - struct stat file_stats; - if (::lstat (resolved_path, &file_stats) != 0) - return false; + struct stat file_stats; + if (::lstat(resolved_path, &file_stats) != 0) + return false; - return (file_stats.st_mode & S_IFMT) == S_IFLNK; + return (file_stats.st_mode & S_IFMT) == S_IFLNK; #endif } -uint32_t -FileSpec::GetPermissions () const -{ - uint32_t file_permissions = 0; - if (*this) - FileSystem::GetFilePermissions(*this, file_permissions); - return file_permissions; +uint32_t FileSpec::GetPermissions() const { + uint32_t file_permissions = 0; + if (*this) + FileSystem::GetFilePermissions(*this, file_permissions); + return file_permissions; } -TimeValue -FileSpec::GetModificationTime () const -{ - TimeValue mod_time; - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - mod_time.OffsetWithSeconds(file_stats.st_mtime); - return mod_time; +TimeValue FileSpec::GetModificationTime() const { + TimeValue mod_time; + struct stat file_stats; + if (GetFileStats(this, &file_stats)) + mod_time.OffsetWithSeconds(file_stats.st_mtime); + return mod_time; } //------------------------------------------------------------------ // Directory string get accessor. //------------------------------------------------------------------ -ConstString & -FileSpec::GetDirectory() -{ - return m_directory; -} +ConstString &FileSpec::GetDirectory() { return m_directory; } //------------------------------------------------------------------ // Directory string const get accessor. //------------------------------------------------------------------ -const ConstString & -FileSpec::GetDirectory() const -{ - return m_directory; -} +const ConstString &FileSpec::GetDirectory() const { return m_directory; } //------------------------------------------------------------------ // Filename string get accessor. //------------------------------------------------------------------ -ConstString & -FileSpec::GetFilename() -{ - return m_filename; -} +ConstString &FileSpec::GetFilename() { return m_filename; } //------------------------------------------------------------------ // Filename string const get accessor. //------------------------------------------------------------------ -const ConstString & -FileSpec::GetFilename() const -{ - return m_filename; -} +const ConstString &FileSpec::GetFilename() const { return m_filename; } //------------------------------------------------------------------ // Extract the directory and path into a fixed buffer. This is // needed as the directory and path are stored in separate string // values. //------------------------------------------------------------------ -size_t -FileSpec::GetPath(char *path, size_t path_max_len, bool denormalize) const -{ - if (!path) - return 0; - - std::string result = GetPath(denormalize); - ::snprintf(path, path_max_len, "%s", result.c_str()); - return std::min(path_max_len-1, result.length()); -} - -std::string -FileSpec::GetPath(bool denormalize) const -{ - llvm::SmallString<64> result; - GetPath(result, denormalize); - return std::string(result.begin(), result.end()); -} - -const char * -FileSpec::GetCString(bool denormalize) const -{ - return ConstString{GetPath(denormalize)}.AsCString(NULL); -} - -void -FileSpec::GetPath(llvm::SmallVectorImpl &path, bool denormalize) const -{ - path.append(m_directory.GetStringRef().begin(), m_directory.GetStringRef().end()); - if (m_directory && m_filename && !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) - path.insert(path.end(), GetPrefferedPathSeparator(m_syntax)); - path.append(m_filename.GetStringRef().begin(), m_filename.GetStringRef().end()); - Normalize(path, m_syntax); - if (denormalize && !path.empty()) - Denormalize(path, m_syntax); -} - -ConstString -FileSpec::GetFileNameExtension () const -{ - if (m_filename) - { - const char *filename = m_filename.GetCString(); - const char* dot_pos = strrchr(filename, '.'); - if (dot_pos && dot_pos[1] != '\0') - return ConstString(dot_pos+1); - } - return ConstString(); +size_t FileSpec::GetPath(char *path, size_t path_max_len, + bool denormalize) const { + if (!path) + return 0; + + std::string result = GetPath(denormalize); + ::snprintf(path, path_max_len, "%s", result.c_str()); + return std::min(path_max_len - 1, result.length()); } -ConstString -FileSpec::GetFileNameStrippingExtension () const -{ +std::string FileSpec::GetPath(bool denormalize) const { + llvm::SmallString<64> result; + GetPath(result, denormalize); + return std::string(result.begin(), result.end()); +} + +const char *FileSpec::GetCString(bool denormalize) const { + return ConstString{GetPath(denormalize)}.AsCString(NULL); +} + +void FileSpec::GetPath(llvm::SmallVectorImpl &path, + bool denormalize) const { + path.append(m_directory.GetStringRef().begin(), + m_directory.GetStringRef().end()); + if (m_directory && m_filename && + !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) + path.insert(path.end(), GetPrefferedPathSeparator(m_syntax)); + path.append(m_filename.GetStringRef().begin(), + m_filename.GetStringRef().end()); + Normalize(path, m_syntax); + if (denormalize && !path.empty()) + Denormalize(path, m_syntax); +} + +ConstString FileSpec::GetFileNameExtension() const { + if (m_filename) { const char *filename = m_filename.GetCString(); - if (filename == NULL) - return ConstString(); - - const char* dot_pos = strrchr(filename, '.'); - if (dot_pos == NULL) - return m_filename; - - return ConstString(filename, dot_pos-filename); + const char *dot_pos = strrchr(filename, '.'); + if (dot_pos && dot_pos[1] != '\0') + return ConstString(dot_pos + 1); + } + return ConstString(); +} + +ConstString FileSpec::GetFileNameStrippingExtension() const { + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + const char *dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return m_filename; + + return ConstString(filename, dot_pos - filename); } //------------------------------------------------------------------ @@ -1053,66 +903,56 @@ FileSpec::GetFileNameStrippingExtension () const // truncated. The final number of bytes that get mapped can be // verified using the DataBuffer::GetByteSize() function. //------------------------------------------------------------------ -DataBufferSP -FileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const -{ - DataBufferSP data_sp; - std::unique_ptr mmap_data(new DataBufferMemoryMap()); - if (mmap_data.get()) - { - const size_t mapped_length = mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size); - if (((file_size == SIZE_MAX) && (mapped_length > 0)) || (mapped_length >= file_size)) - data_sp.reset(mmap_data.release()); - } - return data_sp; -} - -DataBufferSP -FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, size_t file_size) const -{ - if (FileSystem::IsLocal(*this)) - return MemoryMapFileContents(file_offset, file_size); - else - return ReadFileContents(file_offset, file_size, NULL); +DataBufferSP FileSpec::MemoryMapFileContents(off_t file_offset, + size_t file_size) const { + DataBufferSP data_sp; + std::unique_ptr mmap_data(new DataBufferMemoryMap()); + if (mmap_data.get()) { + const size_t mapped_length = + mmap_data->MemoryMapFromFileSpec(this, file_offset, file_size); + if (((file_size == SIZE_MAX) && (mapped_length > 0)) || + (mapped_length >= file_size)) + data_sp.reset(mmap_data.release()); + } + return data_sp; +} + +DataBufferSP FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, + size_t file_size) const { + if (FileSystem::IsLocal(*this)) + return MemoryMapFileContents(file_offset, file_size); + else + return ReadFileContents(file_offset, file_size, NULL); } - //------------------------------------------------------------------ // Return the size in bytes that this object takes in memory. This // returns the size in bytes of this object, not any shared string // values it may refer to. //------------------------------------------------------------------ -size_t -FileSpec::MemorySize() const -{ - return m_filename.MemorySize() + m_directory.MemorySize(); -} - - -size_t -FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const -{ - Error error; - size_t bytes_read = 0; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - off_t file_offset_after_seek = file_offset; - bytes_read = dst_len; - error = file.Read(dst, bytes_read, file_offset_after_seek); - } - } - else - { - error.SetErrorString("invalid file specification"); +size_t FileSpec::MemorySize() const { + return m_filename.MemorySize() + m_directory.MemorySize(); +} + +size_t FileSpec::ReadFileContents(off_t file_offset, void *dst, size_t dst_len, + Error *error_ptr) const { + Error error; + size_t bytes_read = 0; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + off_t file_offset_after_seek = file_offset; + bytes_read = dst_len; + error = file.Read(dst, bytes_read, file_offset_after_seek); } - if (error_ptr) - *error_ptr = error; - return bytes_read; + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return bytes_read; } //------------------------------------------------------------------ @@ -1126,489 +966,450 @@ FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error // truncated. The final number of bytes that get mapped can be // verified using the DataBuffer::GetByteSize() function. //------------------------------------------------------------------ -DataBufferSP -FileSpec::ReadFileContents (off_t file_offset, size_t file_size, Error *error_ptr) const -{ - Error error; - DataBufferSP data_sp; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - const bool null_terminate = false; - error = file.Read (file_size, file_offset, null_terminate, data_sp); - } - } - else - { - error.SetErrorString("invalid file specification"); - } - if (error_ptr) - *error_ptr = error; - return data_sp; -} - -DataBufferSP -FileSpec::ReadFileContentsAsCString(Error *error_ptr) -{ - Error error; - DataBufferSP data_sp; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - off_t offset = 0; - size_t length = SIZE_MAX; - const bool null_terminate = true; - error = file.Read (length, offset, null_terminate, data_sp); - } +DataBufferSP FileSpec::ReadFileContents(off_t file_offset, size_t file_size, + Error *error_ptr) const { + Error error; + DataBufferSP data_sp; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + const bool null_terminate = false; + error = file.Read(file_size, file_offset, null_terminate, data_sp); } - else - { - error.SetErrorString("invalid file specification"); + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return data_sp; +} + +DataBufferSP FileSpec::ReadFileContentsAsCString(Error *error_ptr) { + Error error; + DataBufferSP data_sp; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + off_t offset = 0; + size_t length = SIZE_MAX; + const bool null_terminate = true; + error = file.Read(length, offset, null_terminate, data_sp); } - if (error_ptr) - *error_ptr = error; - return data_sp; -} - -size_t -FileSpec::ReadFileLines (STLStringArray &lines) -{ - lines.clear(); - char path[PATH_MAX]; - if (GetPath(path, sizeof(path))) - { - std::ifstream file_stream (path); - - if (file_stream) - { - std::string line; - while (getline (file_stream, line)) - lines.push_back (line); - } + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return data_sp; +} + +size_t FileSpec::ReadFileLines(STLStringArray &lines) { + lines.clear(); + char path[PATH_MAX]; + if (GetPath(path, sizeof(path))) { + std::ifstream file_stream(path); + + if (file_stream) { + std::string line; + while (getline(file_stream, line)) + lines.push_back(line); } - return lines.size(); + } + return lines.size(); } FileSpec::EnumerateDirectoryResult -FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const &callback) -{ - if (dir_path && dir_path[0]) - { +FileSpec::ForEachItemInDirectory(const char *dir_path, + DirectoryCallback const &callback) { + if (dir_path && dir_path[0]) { #ifdef _WIN32 - std::string szDir(dir_path); - szDir += "\\*"; + std::string szDir(dir_path); + szDir += "\\*"; - std::wstring wszDir; - if (!llvm::ConvertUTF8toWide(szDir, wszDir)) - { - return eEnumerateDirectoryResultNext; - } + std::wstring wszDir; + if (!llvm::ConvertUTF8toWide(szDir, wszDir)) { + return eEnumerateDirectoryResultNext; + } - WIN32_FIND_DATAW ffd; - HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd); + WIN32_FIND_DATAW ffd; + HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd); - if (hFind == INVALID_HANDLE_VALUE) - { - return eEnumerateDirectoryResultNext; - } + if (hFind == INVALID_HANDLE_VALUE) { + return eEnumerateDirectoryResultNext; + } - do - { - FileSpec::FileType file_type = eFileTypeUnknown; - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - size_t len = wcslen(ffd.cFileName); + do { + FileSpec::FileType file_type = eFileTypeUnknown; + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + size_t len = wcslen(ffd.cFileName); + + if (len == 1 && ffd.cFileName[0] == L'.') + continue; + + if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.') + continue; + + file_type = eFileTypeDirectory; + } else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { + file_type = eFileTypeOther; + } else { + file_type = eFileTypeRegular; + } + + std::string fileName; + if (!llvm::convertWideToUTF8(ffd.cFileName, fileName)) { + continue; + } + + std::vector child_path(PATH_MAX); + const int child_path_len = + ::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, + fileName.c_str()); + if (child_path_len < (int)(child_path.size() - 1)) { + // Don't resolve the file type or path + FileSpec child_path_spec(child_path.data(), false); + + EnumerateDirectoryResult result = callback(file_type, child_path_spec); + + switch (result) { + case eEnumerateDirectoryResultNext: + // Enumerate next entry in the current directory. We just + // exit this switch and will continue enumerating the + // current directory as we currently are... + break; + + case eEnumerateDirectoryResultEnter: // Recurse into the current entry + // if it is a directory or symlink, + // or next if not + if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == + eEnumerateDirectoryResultQuit) { + // The subdirectory returned Quit, which means to + // stop all directory enumerations at all levels. + return eEnumerateDirectoryResultQuit; + } + break; + + case eEnumerateDirectoryResultExit: // Exit from the current directory + // at the current level. + // Exit from this directory level and tell parent to + // keep enumerating. + return eEnumerateDirectoryResultNext; + + case eEnumerateDirectoryResultQuit: // Stop directory enumerations at + // any level + return eEnumerateDirectoryResultQuit; + } + } + } while (FindNextFileW(hFind, &ffd) != 0); - if (len == 1 && ffd.cFileName[0] == L'.') - continue; + FindClose(hFind); +#else + lldb_utility::CleanUp dir_path_dir(opendir(dir_path), NULL, + closedir); + if (dir_path_dir.is_valid()) { + char dir_path_last_char = dir_path[strlen(dir_path) - 1]; + + long path_max = fpathconf(dirfd(dir_path_dir.get()), _PC_NAME_MAX); +#if defined(__APPLE_) && defined(__DARWIN_MAXPATHLEN) + if (path_max < __DARWIN_MAXPATHLEN) + path_max = __DARWIN_MAXPATHLEN; +#endif + struct dirent *buf, *dp; + buf = (struct dirent *)malloc(offsetof(struct dirent, d_name) + path_max + + 1); - if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.') - continue; + while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp) { + // Only search directories + if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) { + size_t len = strlen(dp->d_name); - file_type = eFileTypeDirectory; - } - else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) - { - file_type = eFileTypeOther; - } - else - { - file_type = eFileTypeRegular; - } + if (len == 1 && dp->d_name[0] == '.') + continue; - std::string fileName; - if (!llvm::convertWideToUTF8(ffd.cFileName, fileName)) - { - continue; - } + if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') + continue; + } - std::vector child_path(PATH_MAX); - const int child_path_len = - ::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, fileName.c_str()); - if (child_path_len < (int)(child_path.size() - 1)) - { - // Don't resolve the file type or path - FileSpec child_path_spec(child_path.data(), false); - - EnumerateDirectoryResult result = callback (file_type, child_path_spec); - - switch (result) - { - case eEnumerateDirectoryResultNext: - // Enumerate next entry in the current directory. We just - // exit this switch and will continue enumerating the - // current directory as we currently are... - break; - - case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not - if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == - eEnumerateDirectoryResultQuit) - { - // The subdirectory returned Quit, which means to - // stop all directory enumerations at all levels. - return eEnumerateDirectoryResultQuit; - } - break; - - case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level. - // Exit from this directory level and tell parent to - // keep enumerating. - return eEnumerateDirectoryResultNext; - - case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level - return eEnumerateDirectoryResultQuit; - } - } - } while (FindNextFileW(hFind, &ffd) != 0); + FileSpec::FileType file_type = eFileTypeUnknown; - FindClose(hFind); -#else - lldb_utility::CleanUp dir_path_dir(opendir(dir_path), NULL, closedir); - if (dir_path_dir.is_valid()) - { - char dir_path_last_char = dir_path[strlen(dir_path) - 1]; - - long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX); -#if defined (__APPLE_) && defined (__DARWIN_MAXPATHLEN) - if (path_max < __DARWIN_MAXPATHLEN) - path_max = __DARWIN_MAXPATHLEN; -#endif - struct dirent *buf, *dp; - buf = (struct dirent *) malloc (offsetof (struct dirent, d_name) + path_max + 1); - - while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp) - { - // Only search directories - if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) - { - size_t len = strlen(dp->d_name); - - if (len == 1 && dp->d_name[0] == '.') - continue; - - if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') - continue; - } - - FileSpec::FileType file_type = eFileTypeUnknown; - - switch (dp->d_type) - { - default: - case DT_UNKNOWN: file_type = eFileTypeUnknown; break; - case DT_FIFO: file_type = eFileTypePipe; break; - case DT_CHR: file_type = eFileTypeOther; break; - case DT_DIR: file_type = eFileTypeDirectory; break; - case DT_BLK: file_type = eFileTypeOther; break; - case DT_REG: file_type = eFileTypeRegular; break; - case DT_LNK: file_type = eFileTypeSymbolicLink; break; - case DT_SOCK: file_type = eFileTypeSocket; break; + switch (dp->d_type) { + default: + case DT_UNKNOWN: + file_type = eFileTypeUnknown; + break; + case DT_FIFO: + file_type = eFileTypePipe; + break; + case DT_CHR: + file_type = eFileTypeOther; + break; + case DT_DIR: + file_type = eFileTypeDirectory; + break; + case DT_BLK: + file_type = eFileTypeOther; + break; + case DT_REG: + file_type = eFileTypeRegular; + break; + case DT_LNK: + file_type = eFileTypeSymbolicLink; + break; + case DT_SOCK: + file_type = eFileTypeSocket; + break; #if !defined(__OpenBSD__) - case DT_WHT: file_type = eFileTypeOther; break; + case DT_WHT: + file_type = eFileTypeOther; + break; #endif - } - - char child_path[PATH_MAX]; - - // Don't make paths with "/foo//bar", that just confuses everybody. - int child_path_len; - if (dir_path_last_char == '/') - child_path_len = ::snprintf (child_path, sizeof(child_path), "%s%s", dir_path, dp->d_name); - else - child_path_len = ::snprintf (child_path, sizeof(child_path), "%s/%s", dir_path, dp->d_name); - - if (child_path_len < (int)(sizeof(child_path) - 1)) - { - // Don't resolve the file type or path - FileSpec child_path_spec (child_path, false); - - EnumerateDirectoryResult result = callback (file_type, child_path_spec); - - switch (result) - { - case eEnumerateDirectoryResultNext: - // Enumerate next entry in the current directory. We just - // exit this switch and will continue enumerating the - // current directory as we currently are... - break; - - case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not - if (FileSpec::ForEachItemInDirectory (child_path, callback) == eEnumerateDirectoryResultQuit) - { - // The subdirectory returned Quit, which means to - // stop all directory enumerations at all levels. - if (buf) - free (buf); - return eEnumerateDirectoryResultQuit; - } - break; - - case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level. - // Exit from this directory level and tell parent to - // keep enumerating. - if (buf) - free (buf); - return eEnumerateDirectoryResultNext; - - case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level - if (buf) - free (buf); - return eEnumerateDirectoryResultQuit; - } - } + } + + char child_path[PATH_MAX]; + + // Don't make paths with "/foo//bar", that just confuses everybody. + int child_path_len; + if (dir_path_last_char == '/') + child_path_len = ::snprintf(child_path, sizeof(child_path), "%s%s", + dir_path, dp->d_name); + else + child_path_len = ::snprintf(child_path, sizeof(child_path), "%s/%s", + dir_path, dp->d_name); + + if (child_path_len < (int)(sizeof(child_path) - 1)) { + // Don't resolve the file type or path + FileSpec child_path_spec(child_path, false); + + EnumerateDirectoryResult result = + callback(file_type, child_path_spec); + + switch (result) { + case eEnumerateDirectoryResultNext: + // Enumerate next entry in the current directory. We just + // exit this switch and will continue enumerating the + // current directory as we currently are... + break; + + case eEnumerateDirectoryResultEnter: // Recurse into the current entry + // if it is a directory or + // symlink, or next if not + if (FileSpec::ForEachItemInDirectory(child_path, callback) == + eEnumerateDirectoryResultQuit) { + // The subdirectory returned Quit, which means to + // stop all directory enumerations at all levels. + if (buf) + free(buf); + return eEnumerateDirectoryResultQuit; } + break; + + case eEnumerateDirectoryResultExit: // Exit from the current directory + // at the current level. + // Exit from this directory level and tell parent to + // keep enumerating. if (buf) - { - free (buf); - } + free(buf); + return eEnumerateDirectoryResultNext; + + case eEnumerateDirectoryResultQuit: // Stop directory enumerations at + // any level + if (buf) + free(buf); + return eEnumerateDirectoryResultQuit; + } } -#endif + } + if (buf) { + free(buf); + } } - // By default when exiting a directory, we tell the parent enumeration - // to continue enumerating. - return eEnumerateDirectoryResultNext; +#endif + } + // By default when exiting a directory, we tell the parent enumeration + // to continue enumerating. + return eEnumerateDirectoryResultNext; } FileSpec::EnumerateDirectoryResult -FileSpec::EnumerateDirectory -( - const char *dir_path, - bool find_directories, - bool find_files, - bool find_other, - EnumerateDirectoryCallbackType callback, - void *callback_baton -) -{ - return ForEachItemInDirectory(dir_path, - [&find_directories, &find_files, &find_other, &callback, &callback_baton] - (FileType file_type, const FileSpec &file_spec) { - switch (file_type) - { - case FileType::eFileTypeDirectory: - if (find_directories) - return callback(callback_baton, file_type, file_spec); - break; - case FileType::eFileTypeRegular: - if (find_files) - return callback(callback_baton, file_type, file_spec); - break; - default: - if (find_other) - return callback(callback_baton, file_type, file_spec); - break; - } - return eEnumerateDirectoryResultNext; - }); -} - -FileSpec -FileSpec::CopyByAppendingPathComponent (const char *new_path) const -{ - FileSpec ret = *this; - ret.AppendPathComponent(new_path); - return ret; -} - -FileSpec -FileSpec::CopyByRemovingLastPathComponent () const -{ - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - return FileSpec("",resolve); - if (m_directory.IsEmpty()) - return FileSpec("",resolve); - if (m_filename.IsEmpty()) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - - // check for obvious cases before doing the full thing - if (!last_slash_ptr) - return FileSpec("",resolve); - if (last_slash_ptr == dir_cstr) - return FileSpec("/",resolve); - - size_t last_slash_pos = last_slash_ptr - dir_cstr+1; - ConstString new_path(dir_cstr,last_slash_pos); - return FileSpec(new_path.GetCString(),resolve); - } - else - return FileSpec(m_directory.GetCString(),resolve); -} - -ConstString -FileSpec::GetLastPathComponent () const -{ - if (m_filename) - return m_filename; - if (m_directory) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - if (last_slash_ptr == NULL) - return m_directory; - if (last_slash_ptr == dir_cstr) - { - if (last_slash_ptr[1] == 0) - return ConstString(last_slash_ptr); - else - return ConstString(last_slash_ptr+1); - } - if (last_slash_ptr[1] != 0) - return ConstString(last_slash_ptr+1); - const char* penultimate_slash_ptr = last_slash_ptr; - while (*penultimate_slash_ptr) - { - --penultimate_slash_ptr; - if (penultimate_slash_ptr == dir_cstr) - break; - if (*penultimate_slash_ptr == '/') - break; +FileSpec::EnumerateDirectory(const char *dir_path, bool find_directories, + bool find_files, bool find_other, + EnumerateDirectoryCallbackType callback, + void *callback_baton) { + return ForEachItemInDirectory( + dir_path, + [&find_directories, &find_files, &find_other, &callback, + &callback_baton](FileType file_type, const FileSpec &file_spec) { + switch (file_type) { + case FileType::eFileTypeDirectory: + if (find_directories) + return callback(callback_baton, file_type, file_spec); + break; + case FileType::eFileTypeRegular: + if (find_files) + return callback(callback_baton, file_type, file_spec); + break; + default: + if (find_other) + return callback(callback_baton, file_type, file_spec); + break; } - ConstString result(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr); - return result; - } - return ConstString(); + return eEnumerateDirectoryResultNext; + }); } -void -FileSpec::PrependPathComponent(const char *new_path) -{ - if (!new_path) return; - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - { - SetFile(new_path, resolve); - return; +FileSpec FileSpec::CopyByAppendingPathComponent(const char *new_path) const { + FileSpec ret = *this; + ret.AppendPathComponent(new_path); + return ret; +} + +FileSpec FileSpec::CopyByRemovingLastPathComponent() const { + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) + return FileSpec("", resolve); + if (m_directory.IsEmpty()) + return FileSpec("", resolve); + if (m_filename.IsEmpty()) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + + // check for obvious cases before doing the full thing + if (!last_slash_ptr) + return FileSpec("", resolve); + if (last_slash_ptr == dir_cstr) + return FileSpec("/", resolve); + + size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; + ConstString new_path(dir_cstr, last_slash_pos); + return FileSpec(new_path.GetCString(), resolve); + } else + return FileSpec(m_directory.GetCString(), resolve); +} + +ConstString FileSpec::GetLastPathComponent() const { + if (m_filename) + return m_filename; + if (m_directory) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + if (last_slash_ptr == NULL) + return m_directory; + if (last_slash_ptr == dir_cstr) { + if (last_slash_ptr[1] == 0) + return ConstString(last_slash_ptr); + else + return ConstString(last_slash_ptr + 1); } - StreamString stream; - if (m_filename.IsEmpty()) - stream.Printf("%s/%s", new_path, m_directory.GetCString()); - else if (m_directory.IsEmpty()) - stream.Printf("%s/%s", new_path, m_filename.GetCString()); - else - stream.Printf("%s/%s/%s", new_path, m_directory.GetCString(), m_filename.GetCString()); - SetFile(stream.GetData(), resolve); -} - -void -FileSpec::PrependPathComponent(const std::string &new_path) -{ - return PrependPathComponent(new_path.c_str()); -} - -void -FileSpec::PrependPathComponent(const FileSpec &new_path) -{ - return PrependPathComponent(new_path.GetPath(false)); -} - -void -FileSpec::AppendPathComponent(const char *new_path) -{ - if (!new_path) return; - - StreamString stream; - if (!m_directory.IsEmpty()) - { - stream.PutCString(m_directory.GetCString()); - if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + if (last_slash_ptr[1] != 0) + return ConstString(last_slash_ptr + 1); + const char *penultimate_slash_ptr = last_slash_ptr; + while (*penultimate_slash_ptr) { + --penultimate_slash_ptr; + if (penultimate_slash_ptr == dir_cstr) + break; + if (*penultimate_slash_ptr == '/') + break; } + ConstString result(penultimate_slash_ptr + 1, + last_slash_ptr - penultimate_slash_ptr); + return result; + } + return ConstString(); +} - if (!m_filename.IsEmpty()) - { - stream.PutCString(m_filename.GetCString()); - if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); - } +void FileSpec::PrependPathComponent(const char *new_path) { + if (!new_path) + return; + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) { + SetFile(new_path, resolve); + return; + } + StreamString stream; + if (m_filename.IsEmpty()) + stream.Printf("%s/%s", new_path, m_directory.GetCString()); + else if (m_directory.IsEmpty()) + stream.Printf("%s/%s", new_path, m_filename.GetCString()); + else + stream.Printf("%s/%s/%s", new_path, m_directory.GetCString(), + m_filename.GetCString()); + SetFile(stream.GetData(), resolve); +} + +void FileSpec::PrependPathComponent(const std::string &new_path) { + return PrependPathComponent(new_path.c_str()); +} + +void FileSpec::PrependPathComponent(const FileSpec &new_path) { + return PrependPathComponent(new_path.GetPath(false)); +} + +void FileSpec::AppendPathComponent(const char *new_path) { + if (!new_path) + return; + + StreamString stream; + if (!m_directory.IsEmpty()) { + stream.PutCString(m_directory.GetCString()); + if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) + stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + } + + if (!m_filename.IsEmpty()) { + stream.PutCString(m_filename.GetCString()); + if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) + stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + } - while (IsPathSeparator(new_path[0], m_syntax)) - new_path++; + while (IsPathSeparator(new_path[0], m_syntax)) + new_path++; - stream.PutCString(new_path); + stream.PutCString(new_path); - const bool resolve = false; - SetFile(stream.GetData(), resolve, m_syntax); + const bool resolve = false; + SetFile(stream.GetData(), resolve, m_syntax); } -void -FileSpec::AppendPathComponent(const std::string &new_path) -{ - return AppendPathComponent(new_path.c_str()); +void FileSpec::AppendPathComponent(const std::string &new_path) { + return AppendPathComponent(new_path.c_str()); } -void -FileSpec::AppendPathComponent(const FileSpec &new_path) -{ - return AppendPathComponent(new_path.GetPath(false)); +void FileSpec::AppendPathComponent(const FileSpec &new_path) { + return AppendPathComponent(new_path.GetPath(false)); } -void -FileSpec::RemoveLastPathComponent () -{ - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - { - SetFile("",resolve); - return; - } - if (m_directory.IsEmpty()) - { - SetFile("",resolve); - return; +void FileSpec::RemoveLastPathComponent() { + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) { + SetFile("", resolve); + return; + } + if (m_directory.IsEmpty()) { + SetFile("", resolve); + return; + } + if (m_filename.IsEmpty()) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + + // check for obvious cases before doing the full thing + if (!last_slash_ptr) { + SetFile("", resolve); + return; } - if (m_filename.IsEmpty()) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - - // check for obvious cases before doing the full thing - if (!last_slash_ptr) - { - SetFile("",resolve); - return; - } - if (last_slash_ptr == dir_cstr) - { - SetFile("/",resolve); - return; - } - size_t last_slash_pos = last_slash_ptr - dir_cstr+1; - ConstString new_path(dir_cstr,last_slash_pos); - SetFile(new_path.GetCString(),resolve); + if (last_slash_ptr == dir_cstr) { + SetFile("/", resolve); + return; } - else - SetFile(m_directory.GetCString(),resolve); + size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; + ConstString new_path(dir_cstr, last_slash_pos); + SetFile(new_path.GetCString(), resolve); + } else + SetFile(m_directory.GetCString(), resolve); } //------------------------------------------------------------------ /// Returns true if the filespec represents an implementation source @@ -1619,57 +1420,45 @@ FileSpec::RemoveLastPathComponent () /// \b true if the filespec represents an implementation source /// file, \b false otherwise. //------------------------------------------------------------------ -bool -FileSpec::IsSourceImplementationFile () const -{ - ConstString extension (GetFileNameExtension()); - if (extension) - { - static RegularExpression g_source_file_regex ("^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])$"); - return g_source_file_regex.Execute (extension.GetCString()); - } - return false; -} - -bool -FileSpec::IsRelative() const -{ - const char *dir = m_directory.GetCString(); - llvm::StringRef directory(dir ? dir : ""); - - if (directory.size() > 0) - { - if (PathSyntaxIsPosix(m_syntax)) - { - // If the path doesn't start with '/' or '~', return true - switch (directory[0]) - { - case '/': - case '~': - return false; - default: - return true; - } - } - else - { - if (directory.size() >= 2 && directory[1] == ':') - return false; - if (directory[0] == '/') - return false; - return true; - } - } - else if (m_filename) - { - // No directory, just a basename, return true +bool FileSpec::IsSourceImplementationFile() const { + ConstString extension(GetFileNameExtension()); + if (extension) { + static RegularExpression g_source_file_regex( + "^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[" + "cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][" + "rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])" + "$"); + return g_source_file_regex.Execute(extension.GetCString()); + } + return false; +} + +bool FileSpec::IsRelative() const { + const char *dir = m_directory.GetCString(); + llvm::StringRef directory(dir ? dir : ""); + + if (directory.size() > 0) { + if (PathSyntaxIsPosix(m_syntax)) { + // If the path doesn't start with '/' or '~', return true + switch (directory[0]) { + case '/': + case '~': + return false; + default: return true; + } + } else { + if (directory.size() >= 2 && directory[1] == ':') + return false; + if (directory[0] == '/') + return false; + return true; } - return false; + } else if (m_filename) { + // No directory, just a basename, return true + return true; + } + return false; } -bool -FileSpec::IsAbsolute() const -{ - return !FileSpec::IsRelative(); -} +bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); } diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp index 5a5dbc79fe1..c865bf3b3e0 100644 --- a/lldb/source/Host/common/FileSystem.cpp +++ b/lldb/source/Host/common/FileSystem.cpp @@ -20,84 +20,73 @@ using namespace lldb_private; namespace { -bool -CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, llvm::MD5::MD5Result &md5_result) -{ - llvm::MD5 md5_hash; - std::ifstream file(file_spec.GetPath(), std::ios::binary); - if (!file.is_open()) - return false; - - if (offset > 0) - file.seekg(offset, file.beg); - - std::vector read_buf(4096); - uint64_t total_read_bytes = 0; - while (!file.eof()) - { - const uint64_t to_read = (length > 0) ? - std::min(static_cast(read_buf.size()), length - total_read_bytes) : - read_buf.size(); - if (to_read == 0) - break; - - file.read(&read_buf[0], to_read); - const auto read_bytes = file.gcount(); - if (read_bytes == 0) - break; - - md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes)); - total_read_bytes += read_bytes; - } - - md5_hash.final(md5_result); - return true; +bool CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, + llvm::MD5::MD5Result &md5_result) { + llvm::MD5 md5_hash; + std::ifstream file(file_spec.GetPath(), std::ios::binary); + if (!file.is_open()) + return false; + + if (offset > 0) + file.seekg(offset, file.beg); + + std::vector read_buf(4096); + uint64_t total_read_bytes = 0; + while (!file.eof()) { + const uint64_t to_read = + (length > 0) ? std::min(static_cast(read_buf.size()), + length - total_read_bytes) + : read_buf.size(); + if (to_read == 0) + break; + + file.read(&read_buf[0], to_read); + const auto read_bytes = file.gcount(); + if (read_bytes == 0) + break; + + md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes)); + total_read_bytes += read_bytes; + } + + md5_hash.final(md5_result); + return true; } -} // namespace +} // namespace -bool -FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high) -{ - return CalculateMD5(file_spec, 0, 0, low, high); +bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, + uint64_t &high) { + return CalculateMD5(file_spec, 0, 0, low, high); } -bool -FileSystem::CalculateMD5(const FileSpec &file_spec, - uint64_t offset, - uint64_t length, - uint64_t &low, - uint64_t &high) -{ - llvm::MD5::MD5Result md5_result; - if (!CalcMD5(file_spec, offset, length, md5_result)) - return false; - - const auto uint64_res = reinterpret_cast(md5_result); - high = uint64_res[0]; - low = uint64_res[1]; - - return true; +bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset, + uint64_t length, uint64_t &low, uint64_t &high) { + llvm::MD5::MD5Result md5_result; + if (!CalcMD5(file_spec, offset, length, md5_result)) + return false; + + const auto uint64_res = reinterpret_cast(md5_result); + high = uint64_res[0]; + low = uint64_res[1]; + + return true; } -bool -FileSystem::CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str) -{ - return CalculateMD5AsString(file_spec, 0, 0, digest_str); +bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, + std::string &digest_str) { + return CalculateMD5AsString(file_spec, 0, 0, digest_str); } -bool -FileSystem::CalculateMD5AsString(const FileSpec &file_spec, - uint64_t offset, - uint64_t length, - std::string& digest_str) -{ - llvm::MD5::MD5Result md5_result; - if (!CalcMD5(file_spec, offset, length, md5_result)) - return false; - - llvm::SmallString<32> result_str; - llvm::MD5::stringifyResult(md5_result, result_str); - digest_str = result_str.c_str(); - return true; +bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, + uint64_t offset, uint64_t length, + std::string &digest_str) { + llvm::MD5::MD5Result md5_result; + if (!CalcMD5(file_spec, offset, length, md5_result)) + return false; + + llvm::SmallString<32> result_str; + llvm::MD5::stringifyResult(md5_result, result_str); + digest_str = result_str.c_str(); + return true; } diff --git a/lldb/source/Host/common/GetOptInc.cpp b/lldb/source/Host/common/GetOptInc.cpp index 7689f36c815..231e9916a9d 100644 --- a/lldb/source/Host/common/GetOptInc.cpp +++ b/lldb/source/Host/common/GetOptInc.cpp @@ -1,6 +1,7 @@ #include "lldb/Host/common/GetOptInc.h" -#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || defined(REPLACE_GETOPT_LONG_ONLY) +#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || \ + defined(REPLACE_GETOPT_LONG_ONLY) // getopt.cpp #include @@ -8,32 +9,32 @@ #include #if defined(REPLACE_GETOPT) -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ #endif #define PRINT_ERROR ((opterr) && (*options != ':')) -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 -#define EMSG "" +#define EMSG "" -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); +static int getopt_internal(int, char *const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char *const *, const char *, + const struct option *, int *, int); static int gcd(int, int); -static void permute_args(int, int, int, char * const *); +static void permute_args(int, int, int, char *const *); static const char *place = EMSG; /* option letter processing */ @@ -44,19 +45,17 @@ static int nonopt_end = -1; /* first option after non options (for permute) */ /* * Compute the greatest common divisor of a and b. */ -static int -gcd(int a, int b) -{ - int c; +static int gcd(int a, int b) { + int c; + c = a % b; + while (c != 0) { + a = b; + b = c; c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } + } - return (b); + return (b); } static void pass() {} @@ -67,36 +66,34 @@ static void pass() {} * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */ -static void -permute_args(int panonopt_start, int panonopt_end, int opt_end, -char * const *nargv) -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end + i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **)nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } +static void permute_args(int panonopt_start, int panonopt_end, int opt_end, + char *const *nargv) { + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end + i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **)nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; } + } } /* @@ -104,318 +101,297 @@ char * const *nargv) * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ -static int -parse_long_options(char * const *nargv, const char *options, -const struct option *long_options, int *idx, int short_too) -{ - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; - - current_argv = const_cast(place); - match = -1; - - optind++; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; +static int parse_long_options(char *const *nargv, const char *options, + const struct option *long_options, int *idx, + int short_too) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = const_cast(place); + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; } - else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - break; - } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == required_argument) { /* - * If this is a known short option, don't allow - * a partial match of a single character. + * optional argument doesn't use next nargv */ - if (short_too && current_argv_len == 1) - continue; - - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } + optarg = nargv[optind++]; + } } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } - else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); + if ((long_options[match].has_arg == required_argument) && + (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else optopt = 0; - return (BADCH); + --optind; + return (BADARG); } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); } - else - return (long_options[match].val); + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); } /* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx, int flags) -{ - const char *oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; - - if (options == NULL) - return (-1); - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ - if (posixly_correct == -1 || optreset) - posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); - if (*options == '-') - flags |= FLAG_ALLARGS; - else if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - if (*options == '+' || *options == '-') - options++; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; +static int getopt_internal(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx, + int flags) { + const char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1 || optreset) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { /* - * If we have "-" do nothing, if "--" we are done. + * If no permutation wanted, stop parsing + * at first non-option. */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + nonopt_start = optind - (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() + * If we have "-" do nothing, if "--" we are done. */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); } + } - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = const_cast(place); + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; if (PRINT_ERROR) - warnx(illoptchar, optchar); + warnx(recargchar, optchar); optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } - else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; + return (BADARG); + } else + optarg = nargv[optind]; } - else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = const_cast(place); - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } - else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); } /* @@ -425,19 +401,17 @@ start: * [eventually this will replace the BSD getopt] */ #if defined(REPLACE_GETOPT) -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +int getopt(int nargc, char *const *nargv, const char *options) { + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } #endif @@ -446,12 +420,10 @@ getopt(int nargc, char * const *nargv, const char *options) * Parse argc/argv argument vector. */ #if defined(REPLACE_GETOPT_LONG) -int -getopt_long(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx) -{ - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); +int getopt_long(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx) { + return ( + getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE)); } #endif @@ -460,13 +432,11 @@ const struct option *long_options, int *idx) * Parse argc/argv argument vector. */ #if defined(REPLACE_GETOPT_LONG_ONLY) -int -getopt_long_only(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx) -{ +int getopt_long_only(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE | FLAG_LONGONLY)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE | FLAG_LONGONLY)); } #endif diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index c5dd105a59b..bd85c9819e8 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -13,29 +13,30 @@ #include #include #ifndef _WIN32 -#include #include #include #include #include #include +#include #endif -#if defined (__APPLE__) -#include -#include +#if defined(__APPLE__) #include +#include +#include #endif -#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) #include #endif -#include #include +#include #endif -#if defined (__FreeBSD__) +#if defined(__FreeBSD__) #include #endif @@ -44,25 +45,25 @@ // Other libraries and framework includes // Project includes -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/lldb-private-forward.h" -#include "llvm/Support/FileSystem.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/CleanUp.h" +#include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" #if defined(_WIN32) #include "lldb/Host/windows/ProcessLauncherWindows.h" @@ -72,15 +73,14 @@ #include "lldb/Host/posix/ProcessLauncherPosix.h" #endif -#if defined (__APPLE__) +#if defined(__APPLE__) #ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif -extern "C" -{ - int __pthread_chdir(const char *path); - int __pthread_fchdir (int fildes); +extern "C" { +int __pthread_chdir(const char *path); +int __pthread_fchdir(int fildes); } #endif @@ -88,30 +88,30 @@ extern "C" using namespace lldb; using namespace lldb_private; -#if !defined (__APPLE__) && !defined (_WIN32) -struct MonitorInfo -{ - lldb::pid_t pid; // The process ID to monitor - Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals - bool monitor_signals; // If true, call the callback when "pid" gets signaled. +#if !defined(__APPLE__) && !defined(_WIN32) +struct MonitorInfo { + lldb::pid_t pid; // The process ID to monitor + Host::MonitorChildProcessCallback + callback; // The callback function to call when "pid" exits or signals + bool monitor_signals; // If true, call the callback when "pid" gets signaled. }; -static thread_result_t -MonitorChildProcessThreadFunction (void *arg); +static thread_result_t MonitorChildProcessThreadFunction(void *arg); -HostThread -Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, - bool monitor_signals) -{ - MonitorInfo * info_ptr = new MonitorInfo(); - - info_ptr->pid = pid; - info_ptr->callback = callback; - info_ptr->monitor_signals = monitor_signals; - - char thread_name[256]; - ::snprintf(thread_name, sizeof(thread_name), "", pid); - return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); +HostThread Host::StartMonitoringChildProcess( + const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, + bool monitor_signals) { + MonitorInfo *info_ptr = new MonitorInfo(); + + info_ptr->pid = pid; + info_ptr->callback = callback; + info_ptr->monitor_signals = monitor_signals; + + char thread_name[256]; + ::snprintf(thread_name, sizeof(thread_name), + "", pid); + return ThreadLauncher::LaunchThread( + thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); } #ifndef __linux__ @@ -120,26 +120,24 @@ Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callb // constructed, and exception safely restore the previous value it // when it goes out of scope. //------------------------------------------------------------------ -class ScopedPThreadCancelDisabler -{ +class ScopedPThreadCancelDisabler { public: - ScopedPThreadCancelDisabler() - { - // Disable the ability for this thread to be cancelled - int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); - if (err != 0) - m_old_state = -1; - } + ScopedPThreadCancelDisabler() { + // Disable the ability for this thread to be cancelled + int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m_old_state); + if (err != 0) + m_old_state = -1; + } + + ~ScopedPThreadCancelDisabler() { + // Restore the ability for this thread to be cancelled to what it + // previously was. + if (m_old_state != -1) + ::pthread_setcancelstate(m_old_state, 0); + } - ~ScopedPThreadCancelDisabler() - { - // Restore the ability for this thread to be cancelled to what it - // previously was. - if (m_old_state != -1) - ::pthread_setcancelstate (m_old_state, 0); - } private: - int m_old_state; // Save the old cancelability state. + int m_old_state; // Save the old cancelability state. }; #endif // __linux__ @@ -150,279 +148,275 @@ static __thread volatile sig_atomic_t g_usr1_called; static thread_local volatile sig_atomic_t g_usr1_called; #endif -static void -SigUsr1Handler (int) -{ - g_usr1_called = 1; -} +static void SigUsr1Handler(int) { g_usr1_called = 1; } #endif // __linux__ -static bool -CheckForMonitorCancellation() -{ +static bool CheckForMonitorCancellation() { #ifdef __linux__ - if (g_usr1_called) - { - g_usr1_called = 0; - return true; - } + if (g_usr1_called) { + g_usr1_called = 0; + return true; + } #else - ::pthread_testcancel (); + ::pthread_testcancel(); #endif - return false; + return false; } -static thread_result_t -MonitorChildProcessThreadFunction (void *arg) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - const char *function = __FUNCTION__; - if (log) - log->Printf ("%s (arg = %p) thread starting...", function, arg); +static thread_result_t MonitorChildProcessThreadFunction(void *arg) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + const char *function = __FUNCTION__; + if (log) + log->Printf("%s (arg = %p) thread starting...", function, arg); - MonitorInfo *info = (MonitorInfo *)arg; + MonitorInfo *info = (MonitorInfo *)arg; - const Host::MonitorChildProcessCallback callback = info->callback; - const bool monitor_signals = info->monitor_signals; + const Host::MonitorChildProcessCallback callback = info->callback; + const bool monitor_signals = info->monitor_signals; - assert (info->pid <= UINT32_MAX); - const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; + assert(info->pid <= UINT32_MAX); + const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; - delete info; + delete info; - int status = -1; -#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) - #define __WALL 0 + int status = -1; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#define __WALL 0 #endif - const int options = __WALL; + const int options = __WALL; #ifdef __linux__ - // This signal is only used to interrupt the thread from waitpid - struct sigaction sigUsr1Action; - memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); - sigUsr1Action.sa_handler = SigUsr1Handler; - ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); -#endif // __linux__ - - while (1) - { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); + // This signal is only used to interrupt the thread from waitpid + struct sigaction sigUsr1Action; + memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); + sigUsr1Action.sa_handler = SigUsr1Handler; + ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); +#endif // __linux__ - if (CheckForMonitorCancellation ()) - break; + while (1) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", + function, pid, options); - // Get signals from all children with same process group of pid - const ::pid_t wait_pid = ::waitpid (pid, &status, options); + if (CheckForMonitorCancellation()) + break; - if (CheckForMonitorCancellation ()) - break; + // Get signals from all children with same process group of pid + const ::pid_t wait_pid = ::waitpid(pid, &status, options); - if (wait_pid == -1) - { - if (errno == EINTR) - continue; - else - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno)); - break; - } + if (CheckForMonitorCancellation()) + break; + + if (wait_pid == -1) { + if (errno == EINTR) + continue; + else { + if (log) + log->Printf( + "%s (arg = %p) thread exiting because waitpid failed (%s)...", + __FUNCTION__, arg, strerror(errno)); + break; + } + } else if (wait_pid > 0) { + bool exited = false; + int signal = 0; + int exit_status = 0; + const char *status_cstr = NULL; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + status_cstr = "STOPPED"; + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + status_cstr = "EXITED"; + exited = true; + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + status_cstr = "SIGNALED"; + if (wait_pid == abs(pid)) { + exited = true; + exit_status = -1; } - else if (wait_pid > 0) - { - bool exited = false; - int signal = 0; - int exit_status = 0; - const char *status_cstr = NULL; - if (WIFSTOPPED(status)) - { - signal = WSTOPSIG(status); - status_cstr = "STOPPED"; - } - else if (WIFEXITED(status)) - { - exit_status = WEXITSTATUS(status); - status_cstr = "EXITED"; - exited = true; - } - else if (WIFSIGNALED(status)) - { - signal = WTERMSIG(status); - status_cstr = "SIGNALED"; - if (wait_pid == abs(pid)) { - exited = true; - exit_status = -1; - } - } - else - { - status_cstr = "(\?\?\?)"; - } - - // Scope for pthread_cancel_disabler - { + } else { + status_cstr = "(\?\?\?)"; + } + + // Scope for pthread_cancel_disabler + { #ifndef __linux__ - ScopedPThreadCancelDisabler pthread_cancel_disabler; + ScopedPThreadCancelDisabler pthread_cancel_disabler; #endif - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", - function, - pid, - options, - wait_pid, - status, - status_cstr, - signal, - exit_status); - - if (exited || (signal != 0 && monitor_signals)) - { - bool callback_return = false; - if (callback) - callback_return = callback(wait_pid, exited, signal, exit_status); - - // If our process exited, then this thread should exit - if (exited && wait_pid == abs(pid)) - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg); - break; - } - // If the callback returns true, it means this process should - // exit - if (callback_return) - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg); - break; - } - } - } + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s ::waitpid (pid = %" PRIi32 + ", &status, options = %i) => pid = %" PRIi32 + ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", + function, pid, options, wait_pid, status, status_cstr, + signal, exit_status); + + if (exited || (signal != 0 && monitor_signals)) { + bool callback_return = false; + if (callback) + callback_return = callback(wait_pid, exited, signal, exit_status); + + // If our process exited, then this thread should exit + if (exited && wait_pid == abs(pid)) { + if (log) + log->Printf("%s (arg = %p) thread exiting because pid received " + "exit signal...", + __FUNCTION__, arg); + break; + } + // If the callback returns true, it means this process should + // exit + if (callback_return) { + if (log) + log->Printf("%s (arg = %p) thread exiting because callback " + "returned true...", + __FUNCTION__, arg); + break; + } } + } } + } - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg); - return NULL; + return NULL; } #endif // #if !defined (__APPLE__) && !defined (_WIN32) -#if !defined (__APPLE__) +#if !defined(__APPLE__) -void -Host::SystemLog (SystemLogType type, const char *format, va_list args) -{ - vfprintf (stderr, format, args); +void Host::SystemLog(SystemLogType type, const char *format, va_list args) { + vfprintf(stderr, format, args); } #endif -void -Host::SystemLog (SystemLogType type, const char *format, ...) -{ - va_list args; - va_start (args, format); - SystemLog (type, format, args); - va_end (args); +void Host::SystemLog(SystemLogType type, const char *format, ...) { + va_list args; + va_start(args, format); + SystemLog(type, format, args); + va_end(args); } -lldb::pid_t -Host::GetCurrentProcessID() -{ - return ::getpid(); -} +lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); } #ifndef _WIN32 -lldb::tid_t -Host::GetCurrentThreadID() -{ -#if defined (__APPLE__) - // Calling "mach_thread_self()" bumps the reference count on the thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the ref - // count. - thread_port_t thread_self = mach_thread_self(); - mach_port_deallocate(mach_task_self(), thread_self); - return thread_self; +lldb::tid_t Host::GetCurrentThreadID() { +#if defined(__APPLE__) + // Calling "mach_thread_self()" bumps the reference count on the thread + // port, so we need to deallocate it. mach_task_self() doesn't bump the ref + // count. + thread_port_t thread_self = mach_thread_self(); + mach_port_deallocate(mach_task_self(), thread_self); + return thread_self; #elif defined(__FreeBSD__) - return lldb::tid_t(pthread_getthreadid_np()); + return lldb::tid_t(pthread_getthreadid_np()); #elif defined(__ANDROID_NDK__) - return lldb::tid_t(gettid()); + return lldb::tid_t(gettid()); #elif defined(__linux__) - return lldb::tid_t(syscall(SYS_gettid)); + return lldb::tid_t(syscall(SYS_gettid)); #else - return lldb::tid_t(pthread_self()); + return lldb::tid_t(pthread_self()); #endif } -lldb::thread_t -Host::GetCurrentThread () -{ - return lldb::thread_t(pthread_self()); +lldb::thread_t Host::GetCurrentThread() { + return lldb::thread_t(pthread_self()); } -const char * -Host::GetSignalAsCString (int signo) -{ - switch (signo) - { - case SIGHUP: return "SIGHUP"; // 1 hangup - case SIGINT: return "SIGINT"; // 2 interrupt - case SIGQUIT: return "SIGQUIT"; // 3 quit - case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) - case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) - case SIGABRT: return "SIGABRT"; // 6 abort() -#if defined(SIGPOLL) +const char *Host::GetSignalAsCString(int signo) { + switch (signo) { + case SIGHUP: + return "SIGHUP"; // 1 hangup + case SIGINT: + return "SIGINT"; // 2 interrupt + case SIGQUIT: + return "SIGQUIT"; // 3 quit + case SIGILL: + return "SIGILL"; // 4 illegal instruction (not reset when caught) + case SIGTRAP: + return "SIGTRAP"; // 5 trace trap (not reset when caught) + case SIGABRT: + return "SIGABRT"; // 6 abort() +#if defined(SIGPOLL) #if !defined(SIGIO) || (SIGPOLL != SIGIO) -// Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to -// fail with 'multiple define cases with same value' - case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) -#endif -#endif -#if defined(SIGEMT) - case SIGEMT: return "SIGEMT"; // 7 EMT instruction -#endif - case SIGFPE: return "SIGFPE"; // 8 floating point exception - case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) - case SIGBUS: return "SIGBUS"; // 10 bus error - case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation - case SIGSYS: return "SIGSYS"; // 12 bad argument to system call - case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it - case SIGALRM: return "SIGALRM"; // 14 alarm clock - case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill - case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel - case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty - case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty - case SIGCONT: return "SIGCONT"; // 19 continue a stopped process - case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit - case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read - case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) -#if defined(SIGIO) - case SIGIO: return "SIGIO"; // 23 input/output possible signal -#endif - case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit - case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit - case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm - case SIGPROF: return "SIGPROF"; // 27 profiling time alarm -#if defined(SIGWINCH) - case SIGWINCH: return "SIGWINCH"; // 28 window size changes -#endif -#if defined(SIGINFO) - case SIGINFO: return "SIGINFO"; // 29 information request -#endif - case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 - case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 - default: - break; - } - return NULL; + // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to + // fail with 'multiple define cases with same value' + case SIGPOLL: + return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) +#endif +#endif +#if defined(SIGEMT) + case SIGEMT: + return "SIGEMT"; // 7 EMT instruction +#endif + case SIGFPE: + return "SIGFPE"; // 8 floating point exception + case SIGKILL: + return "SIGKILL"; // 9 kill (cannot be caught or ignored) + case SIGBUS: + return "SIGBUS"; // 10 bus error + case SIGSEGV: + return "SIGSEGV"; // 11 segmentation violation + case SIGSYS: + return "SIGSYS"; // 12 bad argument to system call + case SIGPIPE: + return "SIGPIPE"; // 13 write on a pipe with no one to read it + case SIGALRM: + return "SIGALRM"; // 14 alarm clock + case SIGTERM: + return "SIGTERM"; // 15 software termination signal from kill + case SIGURG: + return "SIGURG"; // 16 urgent condition on IO channel + case SIGSTOP: + return "SIGSTOP"; // 17 sendable stop signal not from tty + case SIGTSTP: + return "SIGTSTP"; // 18 stop signal from tty + case SIGCONT: + return "SIGCONT"; // 19 continue a stopped process + case SIGCHLD: + return "SIGCHLD"; // 20 to parent on child stop or exit + case SIGTTIN: + return "SIGTTIN"; // 21 to readers pgrp upon background tty read + case SIGTTOU: + return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) +#if defined(SIGIO) + case SIGIO: + return "SIGIO"; // 23 input/output possible signal +#endif + case SIGXCPU: + return "SIGXCPU"; // 24 exceeded CPU time limit + case SIGXFSZ: + return "SIGXFSZ"; // 25 exceeded file size limit + case SIGVTALRM: + return "SIGVTALRM"; // 26 virtual time alarm + case SIGPROF: + return "SIGPROF"; // 27 profiling time alarm +#if defined(SIGWINCH) + case SIGWINCH: + return "SIGWINCH"; // 28 window size changes +#endif +#if defined(SIGINFO) + case SIGINFO: + return "SIGINFO"; // 29 information request +#endif + case SIGUSR1: + return "SIGUSR1"; // 30 user defined signal 1 + case SIGUSR2: + return "SIGUSR2"; // 31 user defined signal 2 + default: + break; + } + return NULL; } #endif @@ -430,84 +424,63 @@ Host::GetSignalAsCString (int signo) #ifndef _WIN32 lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) -{ - pthread_key_t key; - ::pthread_key_create (&key, callback); - return key; +Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { + pthread_key_t key; + ::pthread_key_create(&key, callback); + return key; } -void* -Host::ThreadLocalStorageGet(lldb::thread_key_t key) -{ - return ::pthread_getspecific (key); +void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { + return ::pthread_getspecific(key); } -void -Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) -{ - ::pthread_setspecific (key, value); +void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { + ::pthread_setspecific(key, value); } #endif -#if !defined (__APPLE__) // see Host.mm +#if !defined(__APPLE__) // see Host.mm -bool -Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) -{ - bundle.Clear(); - return false; +bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) { + bundle.Clear(); + return false; } -bool -Host::ResolveExecutableInBundle (FileSpec &file) -{ - return false; -} +bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; } #endif #ifndef _WIN32 -FileSpec -Host::GetModuleFileSpecForHostAddress (const void *host_addr) -{ - FileSpec module_filespec; +FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { + FileSpec module_filespec; #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) - Dl_info info; - if (::dladdr (host_addr, &info)) - { - if (info.dli_fname) - module_filespec.SetFile(info.dli_fname, true); - } + Dl_info info; + if (::dladdr(host_addr, &info)) { + if (info.dli_fname) + module_filespec.SetFile(info.dli_fname, true); + } #endif - return module_filespec; + return module_filespec; } #endif #if !defined(__linux__) -bool -Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) -{ - return false; +bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { + return false; } #endif -struct ShellInfo -{ - ShellInfo () : - process_reaped (false), - pid (LLDB_INVALID_PROCESS_ID), - signo(-1), - status(-1) - { - } +struct ShellInfo { + ShellInfo() + : process_reaped(false), pid(LLDB_INVALID_PROCESS_ID), signo(-1), + status(-1) {} - lldb_private::Predicate process_reaped; - lldb::pid_t pid; - int signo; - int status; + lldb_private::Predicate process_reaped; + lldb::pid_t pid; + int signo; + int status; }; static bool @@ -516,540 +489,524 @@ MonitorShellCommand(std::shared_ptr shell_info, lldb::pid_t pid, int signo, // Zero for no signal int status) // Exit value of process if signal is zero { - shell_info->pid = pid; - shell_info->signo = signo; - shell_info->status = status; - // Let the thread running Host::RunShellCommand() know that the process - // exited and that ShellInfo has been filled in by broadcasting to it - shell_info->process_reaped.SetValue(true, eBroadcastAlways); - return true; + shell_info->pid = pid; + shell_info->signo = signo; + shell_info->status = status; + // Let the thread running Host::RunShellCommand() know that the process + // exited and that ShellInfo has been filled in by broadcasting to it + shell_info->process_reaped.SetValue(true, eBroadcastAlways); + return true; } -Error -Host::RunShellCommand(const char *command, - const FileSpec &working_dir, - int *status_ptr, - int *signo_ptr, - std::string *command_output_ptr, - uint32_t timeout_sec, - bool run_in_default_shell) -{ - return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, command_output_ptr, timeout_sec, run_in_default_shell); +Error Host::RunShellCommand(const char *command, const FileSpec &working_dir, + int *status_ptr, int *signo_ptr, + std::string *command_output_ptr, + uint32_t timeout_sec, bool run_in_default_shell) { + return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, + command_output_ptr, timeout_sec, run_in_default_shell); } -Error -Host::RunShellCommand(const Args &args, - const FileSpec &working_dir, - int *status_ptr, - int *signo_ptr, - std::string *command_output_ptr, - uint32_t timeout_sec, - bool run_in_default_shell) -{ - Error error; - ProcessLaunchInfo launch_info; - launch_info.SetArchitecture(HostInfo::GetArchitecture()); - if (run_in_default_shell) - { - // Run the command in a shell - launch_info.SetShell(HostInfo::GetDefaultShell()); - launch_info.GetArguments().AppendArguments(args); - const bool localhost = true; - const bool will_debug = false; - const bool first_arg_is_full_shell_command = false; - launch_info.ConvertArgumentsForLaunchingInShell (error, - localhost, - will_debug, - first_arg_is_full_shell_command, - 0); - } - else - { - // No shell, just run it - const bool first_arg_is_executable = true; - launch_info.SetArguments(args, first_arg_is_executable); +Error Host::RunShellCommand(const Args &args, const FileSpec &working_dir, + int *status_ptr, int *signo_ptr, + std::string *command_output_ptr, + uint32_t timeout_sec, bool run_in_default_shell) { + Error error; + ProcessLaunchInfo launch_info; + launch_info.SetArchitecture(HostInfo::GetArchitecture()); + if (run_in_default_shell) { + // Run the command in a shell + launch_info.SetShell(HostInfo::GetDefaultShell()); + launch_info.GetArguments().AppendArguments(args); + const bool localhost = true; + const bool will_debug = false; + const bool first_arg_is_full_shell_command = false; + launch_info.ConvertArgumentsForLaunchingInShell( + error, localhost, will_debug, first_arg_is_full_shell_command, 0); + } else { + // No shell, just run it + const bool first_arg_is_executable = true; + launch_info.SetArguments(args, first_arg_is_executable); + } + + if (working_dir) + launch_info.SetWorkingDirectory(working_dir); + llvm::SmallString output_file_path; + + if (command_output_ptr) { + // Create a temporary file to get the stdout/stderr and redirect the + // output of the command into this file. We will later read this file + // if all goes well and fill the data into "command_output_ptr" + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { + tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), + output_file_path); + } else { + llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", + output_file_path); } - - if (working_dir) - launch_info.SetWorkingDirectory(working_dir); - llvm::SmallString output_file_path; - - if (command_output_ptr) - { - // Create a temporary file to get the stdout/stderr and redirect the - // output of the command into this file. We will later read this file - // if all goes well and fill the data into "command_output_ptr" - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); - llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path); - } - else - { - llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path); + } + + FileSpec output_file_spec{output_file_path.c_str(), false}; + + launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); + if (output_file_spec) { + launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, + true); + launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); + } else { + launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); + launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); + } + + std::shared_ptr shell_info_sp(new ShellInfo()); + const bool monitor_signals = false; + launch_info.SetMonitorProcessCallback( + std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4), + monitor_signals); + + error = LaunchProcess(launch_info); + const lldb::pid_t pid = launch_info.GetProcessID(); + + if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) + error.SetErrorString("failed to get process ID"); + + if (error.Success()) { + bool timed_out = false; + shell_info_sp->process_reaped.WaitForValueEqualTo( + true, std::chrono::seconds(timeout_sec), &timed_out); + if (timed_out) { + error.SetErrorString("timed out waiting for shell command to complete"); + + // Kill the process since it didn't complete within the timeout specified + Kill(pid, SIGKILL); + // Wait for the monitor callback to get the message + timed_out = false; + shell_info_sp->process_reaped.WaitForValueEqualTo( + true, std::chrono::seconds(1), &timed_out); + } else { + if (status_ptr) + *status_ptr = shell_info_sp->status; + + if (signo_ptr) + *signo_ptr = shell_info_sp->signo; + + if (command_output_ptr) { + command_output_ptr->clear(); + uint64_t file_size = output_file_spec.GetByteSize(); + if (file_size > 0) { + if (file_size > command_output_ptr->max_size()) { + error.SetErrorStringWithFormat( + "shell command output is too large to fit into a std::string"); + } else { + std::vector command_output(file_size); + output_file_spec.ReadFileContents(0, command_output.data(), + file_size, &error); + if (error.Success()) + command_output_ptr->assign(command_output.data(), file_size); + } } + } } + } - FileSpec output_file_spec{output_file_path.c_str(), false}; - - launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); - if (output_file_spec) - { - launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true); - launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); - } - else - { - launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); - launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); - } - - std::shared_ptr shell_info_sp(new ShellInfo()); - const bool monitor_signals = false; - launch_info.SetMonitorProcessCallback(std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4), - monitor_signals); - - error = LaunchProcess (launch_info); - const lldb::pid_t pid = launch_info.GetProcessID(); - - if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) - error.SetErrorString("failed to get process ID"); - - if (error.Success()) - { - bool timed_out = false; - shell_info_sp->process_reaped.WaitForValueEqualTo(true, std::chrono::seconds(timeout_sec), &timed_out); - if (timed_out) - { - error.SetErrorString("timed out waiting for shell command to complete"); - - // Kill the process since it didn't complete within the timeout specified - Kill (pid, SIGKILL); - // Wait for the monitor callback to get the message - timed_out = false; - shell_info_sp->process_reaped.WaitForValueEqualTo(true, std::chrono::seconds(1), &timed_out); - } - else - { - if (status_ptr) - *status_ptr = shell_info_sp->status; - - if (signo_ptr) - *signo_ptr = shell_info_sp->signo; - - if (command_output_ptr) - { - command_output_ptr->clear(); - uint64_t file_size = output_file_spec.GetByteSize(); - if (file_size > 0) - { - if (file_size > command_output_ptr->max_size()) - { - error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); - } - else - { - std::vector command_output(file_size); - output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error); - if (error.Success()) - command_output_ptr->assign(command_output.data(), file_size); - } - } - } - } - } - - if (FileSystem::GetFileExists(output_file_spec)) - FileSystem::Unlink(output_file_spec); - return error; + if (FileSystem::GetFileExists(output_file_spec)) + FileSystem::Unlink(output_file_spec); + return error; } // LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC // systems -#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || \ + defined(__GLIBC__) || defined(__NetBSD__) #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) // this method needs to be visible to macosx/Host.cpp and // common/Host.cpp. -short -Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) -{ - short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - -#if defined (__APPLE__) - if (launch_info.GetFlags().Test (eLaunchFlagExec)) - flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test (eLaunchFlagDebug)) - flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) - flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag - - if (launch_info.GetLaunchInSeparateProcessGroup()) - flags |= POSIX_SPAWN_SETPGROUP; - +short Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { + short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + +#if defined(__APPLE__) + if (launch_info.GetFlags().Test(eLaunchFlagExec)) + flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) + flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag + + if (launch_info.GetLaunchInSeparateProcessGroup()) + flags |= POSIX_SPAWN_SETPGROUP; + #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT -#if defined (__APPLE__) && (defined (__x86_64__) || defined (__i386__)) - static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; - if (g_use_close_on_exec_flag == eLazyBoolCalculate) - { - g_use_close_on_exec_flag = eLazyBoolNo; - - uint32_t major, minor, update; - if (HostInfo::GetOSVersion(major, minor, update)) - { - // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier - if (major > 10 || (major == 10 && minor > 7)) - { - // Only enable for 10.8 and later OS versions - g_use_close_on_exec_flag = eLazyBoolYes; - } - } +#if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) + static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; + if (g_use_close_on_exec_flag == eLazyBoolCalculate) { + g_use_close_on_exec_flag = eLazyBoolNo; + + uint32_t major, minor, update; + if (HostInfo::GetOSVersion(major, minor, update)) { + // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or + // earlier + if (major > 10 || (major == 10 && minor > 7)) { + // Only enable for 10.8 and later OS versions + g_use_close_on_exec_flag = eLazyBoolYes; + } } + } #else - static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; + static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; #endif - // Close all files exception those with file actions if this is supported. - if (g_use_close_on_exec_flag == eLazyBoolYes) - flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; + // Close all files exception those with file actions if this is supported. + if (g_use_close_on_exec_flag == eLazyBoolYes) + flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; #endif #endif // #if defined (__APPLE__) - return flags; + return flags; } -Error -Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) -{ - Error error; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); +Error Host::LaunchProcessPosixSpawn(const char *exe_path, + const ProcessLaunchInfo &launch_info, + lldb::pid_t &pid) { + Error error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); - posix_spawnattr_t attr; - error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); + posix_spawnattr_t attr; + error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); - if (error.Fail()) - return error; + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); + if (error.Fail()) + return error; - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset (&no_signals); - sigfillset (&all_signals); - ::posix_spawnattr_setsigmask(&attr, &no_signals); -#if defined (__linux__) || defined (__FreeBSD__) - ::posix_spawnattr_setsigdefault(&attr, &no_signals); + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp posix_spawnattr_cleanup( + &attr, posix_spawnattr_destroy); + + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + ::posix_spawnattr_setsigmask(&attr, &no_signals); +#if defined(__linux__) || defined(__FreeBSD__) + ::posix_spawnattr_setsigdefault(&attr, &no_signals); #else - ::posix_spawnattr_setsigdefault(&attr, &all_signals); + ::posix_spawnattr_setsigdefault(&attr, &all_signals); #endif - short flags = GetPosixspawnFlags(launch_info); + short flags = GetPosixspawnFlags(launch_info); - error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); - if (error.Fail()) - return error; + error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", + flags); + if (error.Fail()) + return error; - // posix_spawnattr_setbinpref_np appears to be an Apple extension per: - // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ -#if defined (__APPLE__) && !defined (__arm__) - - // Don't set the binpref if a shell was provided. After all, that's only going to affect what version of the shell - // is launched, not what fork of the binary is launched. We insert "arch --arch as part of the shell invocation - // to do that job on OSX. - - if (launch_info.GetShell() == nullptr) +// posix_spawnattr_setbinpref_np appears to be an Apple extension per: +// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ +#if defined(__APPLE__) && !defined(__arm__) + + // Don't set the binpref if a shell was provided. After all, that's only + // going to affect what version of the shell + // is launched, not what fork of the binary is launched. We insert "arch + // --arch as part of the shell invocation + // to do that job on OSX. + + if (launch_info.GetShell() == nullptr) { + // We don't need to do this for ARM, and we really shouldn't now that we + // have multiple CPU subtypes and no posix_spawnattr call that allows us + // to set which CPU subtype to launch... + const ArchSpec &arch_spec = launch_info.GetArchitecture(); + cpu_type_t cpu = arch_spec.GetMachOCPUType(); + cpu_type_t sub = arch_spec.GetMachOCPUSubType(); + if (cpu != 0 && cpu != static_cast(UINT32_MAX) && + cpu != static_cast(LLDB_INVALID_CPUTYPE) && + !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try + // to set the CPU type or we will fail { - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - cpu_type_t cpu = arch_spec.GetMachOCPUType(); - cpu_type_t sub = arch_spec.GetMachOCPUSubType(); - if (cpu != 0 && - cpu != static_cast(UINT32_MAX) && - cpu != static_cast(LLDB_INVALID_CPUTYPE) && - !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail - { - size_t ocount = 0; - error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); - - if (error.Fail() || ocount != 1) - return error; - } + size_t ocount = 0; + error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, " + "cpu_type = 0x%8.8x, count => %llu )", + cpu, (uint64_t)ocount); + + if (error.Fail() || ocount != 1) + return error; } - -#endif - - const char *tmp_argv[2]; - char * const *argv = const_cast(launch_info.GetArguments().GetConstArgumentVector()); - char * const *envp = const_cast(launch_info.GetEnvironmentEntries().GetConstArgumentVector()); - if (argv == NULL) - { - // posix_spawn gets very unhappy if it doesn't have at least the program - // name in argv[0]. One of the side affects I have noticed is the environment - // variables don't make it into the child process if "argv == NULL"!!! - tmp_argv[0] = exe_path; - tmp_argv[1] = NULL; - argv = const_cast(tmp_argv); + } + +#endif + + const char *tmp_argv[2]; + char *const *argv = const_cast( + launch_info.GetArguments().GetConstArgumentVector()); + char *const *envp = const_cast( + launch_info.GetEnvironmentEntries().GetConstArgumentVector()); + if (argv == NULL) { + // posix_spawn gets very unhappy if it doesn't have at least the program + // name in argv[0]. One of the side affects I have noticed is the + // environment + // variables don't make it into the child process if "argv == NULL"!!! + tmp_argv[0] = exe_path; + tmp_argv[1] = NULL; + argv = const_cast(tmp_argv); + } + +#if !defined(__APPLE__) + // manage the working directory + char current_dir[PATH_MAX]; + current_dir[0] = '\0'; +#endif + + FileSpec working_dir{launch_info.GetWorkingDirectory()}; + if (working_dir) { +#if defined(__APPLE__) + // Set the working directory on this thread only + if (__pthread_chdir(working_dir.GetCString()) < 0) { + if (errno == ENOENT) { + error.SetErrorStringWithFormat("No such file or directory: %s", + working_dir.GetCString()); + } else if (errno == ENOTDIR) { + error.SetErrorStringWithFormat("Path doesn't name a directory: %s", + working_dir.GetCString()); + } else { + error.SetErrorStringWithFormat("An unknown error occurred when " + "changing directory for process " + "execution."); + } + return error; } - -#if !defined (__APPLE__) - // manage the working directory - char current_dir[PATH_MAX]; - current_dir[0] = '\0'; -#endif - - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir) - { -#if defined (__APPLE__) - // Set the working directory on this thread only - if (__pthread_chdir(working_dir.GetCString()) < 0) { - if (errno == ENOENT) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - } else if (errno == ENOTDIR) { - error.SetErrorStringWithFormat("Path doesn't name a directory: %s", - working_dir.GetCString()); - } else { - error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution."); - } - return error; - } #else - if (::getcwd(current_dir, sizeof(current_dir)) == NULL) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to save the current directory"); - return error; - } - - if (::chdir(working_dir.GetCString()) == -1) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to change working directory to %s", - working_dir.GetCString()); - return error; - } -#endif + if (::getcwd(current_dir, sizeof(current_dir)) == NULL) { + error.SetError(errno, eErrorTypePOSIX); + error.LogIfError(log, "unable to save the current directory"); + return error; } - ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; - const size_t num_file_actions = launch_info.GetNumFileActions (); - if (num_file_actions > 0) - { - posix_spawn_file_actions_t file_actions; - error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); - if (error.Fail()) - return error; - - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy); - - for (size_t i=0; i 0) { + posix_spawn_file_actions_t file_actions; + error.SetError(::posix_spawn_file_actions_init(&file_actions), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); + if (error.Fail()) + return error; - if (error.Fail() || log) - { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid, - exe_path, static_cast(&file_actions), static_cast(&attr), reinterpret_cast(argv), - reinterpret_cast(envp)); - if (log) - { - for (int ii=0; argv[ii]; ++ii) - log->Printf("argv[%i] = '%s'", ii, argv[ii]); - } - } + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp + posix_spawn_file_actions_cleanup(&file_actions, + posix_spawn_file_actions_destroy); + + for (size_t i = 0; i < num_file_actions; ++i) { + const FileAction *launch_file_action = + launch_info.GetFileActionAtIndex(i); + if (launch_file_action) { + if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, + error)) + return error; + } + } + error.SetError( + ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail() || log) { + error.PutToLog( + log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, " + "attr = %p, argv = %p, envp = %p )", + result_pid, exe_path, static_cast(&file_actions), + static_cast(&attr), reinterpret_cast(argv), + reinterpret_cast(envp)); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + log->Printf("argv[%i] = '%s'", ii, argv[ii]); + } } - else - { - error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX); - if (error.Fail() || log) - { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", - result_pid, exe_path, static_cast(&attr), reinterpret_cast(argv), - reinterpret_cast(envp)); - if (log) - { - for (int ii=0; argv[ii]; ++ii) - log->Printf("argv[%i] = '%s'", ii, argv[ii]); - } - } + } else { + error.SetError( + ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail() || log) { + error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', " + "file_actions = NULL, attr = %p, argv = %p, envp = " + "%p )", + result_pid, exe_path, static_cast(&attr), + reinterpret_cast(argv), + reinterpret_cast(envp)); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + log->Printf("argv[%i] = '%s'", ii, argv[ii]); + } } - pid = result_pid; + } + pid = result_pid; - if (working_dir) - { -#if defined (__APPLE__) - // No more thread specific current working directory - __pthread_fchdir (-1); + if (working_dir) { +#if defined(__APPLE__) + // No more thread specific current working directory + __pthread_fchdir(-1); #else - if (::chdir(current_dir) == -1 && error.Success()) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to change current directory back to %s", - current_dir); - } -#endif + if (::chdir(current_dir) == -1 && error.Success()) { + error.SetError(errno, eErrorTypePOSIX); + error.LogIfError(log, "unable to change current directory back to %s", + current_dir); } +#endif + } - return error; + return error; } -bool -Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) -{ - if (info == NULL) - return false; - - posix_spawn_file_actions_t *file_actions = reinterpret_cast(_file_actions); - - switch (info->GetAction()) - { - case FileAction::eFileActionNone: - error.Clear(); - break; - - case FileAction::eFileActionClose: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)"); - else - { - error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); - if (log && (error.Fail() || log)) - error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)", - static_cast(file_actions), info->GetFD()); - } - break; - - case FileAction::eFileActionDuplicate: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)"); - else if (info->GetActionArgument() == -1) - error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); - else - { - error.SetError( - ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), - eErrorTypePOSIX); - if (log && (error.Fail() || log)) - error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", - static_cast(file_actions), info->GetFD(), info->GetActionArgument()); - } - break; +bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, + Log *log, Error &error) { + if (info == NULL) + return false; - case FileAction::eFileActionOpen: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)"); - else - { - int oflag = info->GetActionArgument(); - - mode_t mode = 0; - - if (oflag & O_CREAT) - mode = 0640; - - error.SetError( - ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode), - eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, - "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)", - static_cast(file_actions), info->GetFD(), info->GetPath(), oflag, mode); - } - break; + posix_spawn_file_actions_t *file_actions = + reinterpret_cast(_file_actions); + + switch (info->GetAction()) { + case FileAction::eFileActionNone: + error.Clear(); + break; + + case FileAction::eFileActionClose: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_addclose(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), + eErrorTypePOSIX); + if (log && (error.Fail() || log)) + error.PutToLog(log, + "posix_spawn_file_actions_addclose (action=%p, fd=%i)", + static_cast(file_actions), info->GetFD()); + } + break; + + case FileAction::eFileActionDuplicate: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_adddup2(...)"); + else if (info->GetActionArgument() == -1) + error.SetErrorString( + "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), + info->GetActionArgument()), + eErrorTypePOSIX); + if (log && (error.Fail() || log)) + error.PutToLog( + log, + "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", + static_cast(file_actions), info->GetFD(), + info->GetActionArgument()); + } + break; + + case FileAction::eFileActionOpen: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd in posix_spawn_file_actions_addopen(...)"); + else { + int oflag = info->GetActionArgument(); + + mode_t mode = 0; + + if (oflag & O_CREAT) + mode = 0640; + + error.SetError( + ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), + info->GetPath(), oflag, mode), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "posix_spawn_file_actions_addopen (action=%p, " + "fd=%i, path='%s', oflag=%i, mode=%i)", + static_cast(file_actions), info->GetFD(), + info->GetPath(), oflag, mode); } - return error.Success(); + break; + } + return error.Success(); } #endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__) -#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) +#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || + // defined (__GLIBC__) || defined(__NetBSD__) -#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || \ + defined(__NetBSD__) || defined(_WIN32) // The functions below implement process launching via posix_spawn() for Linux, // FreeBSD and NetBSD. -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - std::unique_ptr delegate_launcher; +Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) { + std::unique_ptr delegate_launcher; #if defined(_WIN32) - delegate_launcher.reset(new ProcessLauncherWindows()); + delegate_launcher.reset(new ProcessLauncherWindows()); #elif defined(__linux__) - delegate_launcher.reset(new ProcessLauncherLinux()); + delegate_launcher.reset(new ProcessLauncherLinux()); #else - delegate_launcher.reset(new ProcessLauncherPosix()); + delegate_launcher.reset(new ProcessLauncherPosix()); #endif - MonitoringProcessLauncher launcher(std::move(delegate_launcher)); + MonitoringProcessLauncher launcher(std::move(delegate_launcher)); - Error error; - HostProcess process = launcher.LaunchProcess(launch_info, error); + Error error; + HostProcess process = launcher.LaunchProcess(launch_info, error); - // TODO(zturner): It would be better if the entire HostProcess were returned instead of writing - // it into this structure. - launch_info.SetProcessID(process.GetProcessId()); + // TODO(zturner): It would be better if the entire HostProcess were returned + // instead of writing + // it into this structure. + launch_info.SetProcessID(process.GetProcessId()); - return error; + return error; } #endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) #ifndef _WIN32 -void -Host::Kill(lldb::pid_t pid, int signo) -{ - ::kill(pid, signo); -} +void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); } #endif -#if !defined (__APPLE__) -bool -Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) -{ - return false; +#if !defined(__APPLE__) +bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, + uint32_t line_no) { + return false; } -void -Host::SetCrashDescriptionWithFormat (const char *format, ...) -{ -} +void Host::SetCrashDescriptionWithFormat(const char *format, ...) {} -void -Host::SetCrashDescription (const char *description) -{ -} +void Host::SetCrashDescription(const char *description) {} #endif -const UnixSignalsSP & -Host::GetUnixSignals() -{ - static const auto s_unix_signals_sp = UnixSignals::Create(HostInfo::GetArchitecture()); - return s_unix_signals_sp; +const UnixSignalsSP &Host::GetUnixSignals() { + static const auto s_unix_signals_sp = + UnixSignals::Create(HostInfo::GetArchitecture()); + return s_unix_signals_sp; } diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index 3fcd31e08f9..01ac87047c5 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -24,405 +24,372 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" -#include #include // std::once +#include using namespace lldb; using namespace lldb_private; -namespace -{ - //---------------------------------------------------------------------- - // The HostInfoBaseFields is a work around for windows not supporting - // static variables correctly in a thread safe way. Really each of the - // variables in HostInfoBaseFields should live in the functions in which - // they are used and each one should be static, but the work around is - // in place to avoid this restriction. Ick. - //---------------------------------------------------------------------- - - struct HostInfoBaseFields - { - ~HostInfoBaseFields() - { - if (m_lldb_process_tmp_dir.Exists()) - { - // Remove the LLDB temporary directory if we have one. Set "recurse" to - // true to all files that were created for the LLDB process can be cleaned up. - FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true); - } - } - - uint32_t m_number_cpus; - std::string m_vendor_string; - std::string m_os_string; - std::string m_host_triple; - - ArchSpec m_host_arch_32; - ArchSpec m_host_arch_64; - - FileSpec m_lldb_so_dir; - FileSpec m_lldb_support_exe_dir; - FileSpec m_lldb_headers_dir; - FileSpec m_lldb_python_dir; - FileSpec m_lldb_clang_resource_dir; - FileSpec m_lldb_system_plugin_dir; - FileSpec m_lldb_user_plugin_dir; - FileSpec m_lldb_process_tmp_dir; - FileSpec m_lldb_global_tmp_dir; - }; - - HostInfoBaseFields *g_fields = nullptr; +namespace { +//---------------------------------------------------------------------- +// The HostInfoBaseFields is a work around for windows not supporting +// static variables correctly in a thread safe way. Really each of the +// variables in HostInfoBaseFields should live in the functions in which +// they are used and each one should be static, but the work around is +// in place to avoid this restriction. Ick. +//---------------------------------------------------------------------- + +struct HostInfoBaseFields { + ~HostInfoBaseFields() { + if (m_lldb_process_tmp_dir.Exists()) { + // Remove the LLDB temporary directory if we have one. Set "recurse" to + // true to all files that were created for the LLDB process can be cleaned + // up. + FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true); + } + } + + uint32_t m_number_cpus; + std::string m_vendor_string; + std::string m_os_string; + std::string m_host_triple; + + ArchSpec m_host_arch_32; + ArchSpec m_host_arch_64; + + FileSpec m_lldb_so_dir; + FileSpec m_lldb_support_exe_dir; + FileSpec m_lldb_headers_dir; + FileSpec m_lldb_python_dir; + FileSpec m_lldb_clang_resource_dir; + FileSpec m_lldb_system_plugin_dir; + FileSpec m_lldb_user_plugin_dir; + FileSpec m_lldb_process_tmp_dir; + FileSpec m_lldb_global_tmp_dir; +}; + +HostInfoBaseFields *g_fields = nullptr; } -void -HostInfoBase::Initialize() -{ - g_fields = new HostInfoBaseFields(); +void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } + +void HostInfoBase::Terminate() { + delete g_fields; + g_fields = nullptr; } -void -HostInfoBase::Terminate() -{ - delete g_fields; - g_fields = nullptr; +uint32_t HostInfoBase::GetNumberCPUS() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_number_cpus = std::thread::hardware_concurrency(); + }); + return g_fields->m_number_cpus; } -uint32_t -HostInfoBase::GetNumberCPUS() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_number_cpus = std::thread::hardware_concurrency(); - }); - return g_fields->m_number_cpus; +uint32_t HostInfoBase::GetMaxThreadNameLength() { return 0; } + +llvm::StringRef HostInfoBase::GetVendorString() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_vendor_string = + HostInfo::GetArchitecture().GetTriple().getVendorName().str(); + }); + return g_fields->m_vendor_string; } -uint32_t -HostInfoBase::GetMaxThreadNameLength() -{ - return 0; +llvm::StringRef HostInfoBase::GetOSString() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_os_string = + std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); + }); + return g_fields->m_os_string; } -llvm::StringRef -HostInfoBase::GetVendorString() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_vendor_string = HostInfo::GetArchitecture().GetTriple().getVendorName().str(); - }); - return g_fields->m_vendor_string; +llvm::StringRef HostInfoBase::GetTargetTriple() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_host_triple = + HostInfo::GetArchitecture().GetTriple().getTriple(); + }); + return g_fields->m_host_triple; } -llvm::StringRef -HostInfoBase::GetOSString() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); - }); - return g_fields->m_os_string; +const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, + g_fields->m_host_arch_64); + }); + + // If an explicit 32 or 64-bit architecture was requested, return that. + if (arch_kind == eArchKind32) + return g_fields->m_host_arch_32; + if (arch_kind == eArchKind64) + return g_fields->m_host_arch_64; + + // Otherwise prefer the 64-bit architecture if it is valid. + return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 + : g_fields->m_host_arch_32; } -llvm::StringRef -HostInfoBase::GetTargetTriple() -{ +bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { + file_spec.Clear(); + +#if defined(LLDB_DISABLE_PYTHON) + if (type == lldb::ePathTypePythonDir) + return false; +#endif + + FileSpec *result = nullptr; + switch (type) { + case lldb::ePathTypeLLDBShlibDir: { static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple(); + static bool success = false; + std::call_once(g_once_flag, []() { + success = + HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", + g_fields->m_lldb_so_dir.GetPath().c_str()); }); - return g_fields->m_host_triple; -} - -const ArchSpec & -HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) -{ + if (success) + result = &g_fields->m_lldb_so_dir; + } break; + case lldb::ePathTypeSupportExecutableDir: { static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSupportExeDirectory( + g_fields->m_lldb_support_exe_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", + g_fields->m_lldb_support_exe_dir.GetPath().c_str()); }); + if (success) + result = &g_fields->m_lldb_support_exe_dir; + } break; + case lldb::ePathTypeHeaderDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", + g_fields->m_lldb_headers_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_headers_dir; + } break; + case lldb::ePathTypePythonDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", + g_fields->m_lldb_python_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_python_dir; + } break; + case lldb::ePathTypeClangDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = + HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", + g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_clang_resource_dir; + } break; + case lldb::ePathTypeLLDBSystemPlugins: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSystemPluginsDirectory( + g_fields->m_lldb_system_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", + g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_system_plugin_dir; + } break; + case lldb::ePathTypeLLDBUserPlugins: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeUserPluginsDirectory( + g_fields->m_lldb_user_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", + g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_user_plugin_dir; + } break; + case lldb::ePathTypeLLDBTempSystemDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeProcessTempFileDirectory( + g_fields->m_lldb_process_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", + g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_process_tmp_dir; + } break; + case lldb::ePathTypeGlobalLLDBTempSystemDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeGlobalTempFileDirectory( + g_fields->m_lldb_global_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(" + "ePathTypeGlobalLLDBTempSystemDir) => '%s'", + g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_global_tmp_dir; + } break; + } - // If an explicit 32 or 64-bit architecture was requested, return that. - if (arch_kind == eArchKind32) - return g_fields->m_host_arch_32; - if (arch_kind == eArchKind64) - return g_fields->m_host_arch_64; - - // Otherwise prefer the 64-bit architecture if it is valid. - return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32; + if (!result) + return false; + file_spec = *result; + return true; } -bool -HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) -{ - file_spec.Clear(); +bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { + // To get paths related to LLDB we get the path to the executable that + // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", + // on linux this is assumed to be the "lldb" main executable. If LLDB on + // linux is actually in a shared library (liblldb.so) then this function will + // need to be modified to "do the right thing". -#if defined(LLDB_DISABLE_PYTHON) - if (type == lldb::ePathTypePythonDir) - return false; -#endif + FileSpec lldb_file_spec( + Host::GetModuleFileSpecForHostAddress(reinterpret_cast( + reinterpret_cast(HostInfoBase::GetLLDBPath)))); - FileSpec *result = nullptr; - switch (type) - { - case lldb::ePathTypeLLDBShlibDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_so_dir; - } - break; - case lldb::ePathTypeSupportExecutableDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", - g_fields->m_lldb_support_exe_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_support_exe_dir; - } - break; - case lldb::ePathTypeHeaderDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_headers_dir; - } - break; - case lldb::ePathTypePythonDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_python_dir; - } - break; - case lldb::ePathTypeClangDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_clang_resource_dir; - } - break; - case lldb::ePathTypeLLDBSystemPlugins: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", - g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_system_plugin_dir; - } - break; - case lldb::ePathTypeLLDBUserPlugins: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", - g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_user_plugin_dir; - } - break; - case lldb::ePathTypeLLDBTempSystemDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeProcessTempFileDirectory (g_fields->m_lldb_process_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_process_tmp_dir; - } - break; - case lldb::ePathTypeGlobalLLDBTempSystemDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeGlobalTempFileDirectory (g_fields->m_lldb_global_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_global_tmp_dir; - } - break; - } + // This is necessary because when running the testsuite the shlib might be a + // symbolic link inside the Python resource dir. + FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); - if (!result) - return false; - file_spec = *result; - return true; -} + // Remove the filename so that this FileSpec only represents the directory. + file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); -bool -HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) -{ - // To get paths related to LLDB we get the path to the executable that - // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", - // on linux this is assumed to be the "lldb" main executable. If LLDB on - // linux is actually in a shared library (liblldb.so) then this function will - // need to be modified to "do the right thing". - - FileSpec lldb_file_spec( - Host::GetModuleFileSpecForHostAddress(reinterpret_cast(reinterpret_cast(HostInfoBase::GetLLDBPath)))); - - // This is necessary because when running the testsuite the shlib might be a symbolic link inside the Python resource dir. - FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); - - // Remove the filename so that this FileSpec only represents the directory. - file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); - - return (bool)file_spec.GetDirectory(); + return (bool)file_spec.GetDirectory(); } -bool -HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); +bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { + return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); } -bool -HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) -{ - FileSpec temp_file_spec; - if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) - return false; +bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { + FileSpec temp_file_spec; + if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) + return false; - std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; - temp_file_spec.AppendPathComponent(pid_str); - if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success()) - return false; + std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; + temp_file_spec.AppendPathComponent(pid_str); + if (!FileSystem::MakeDirectory(temp_file_spec, + eFilePermissionsDirectoryDefault) + .Success()) + return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); - return true; + file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + return true; } -bool -HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) -{ - llvm::SmallVector tmpdir; - llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); - file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); - return true; +bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + llvm::SmallVector tmpdir; + llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); + file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); + return true; } -bool -HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) -{ - file_spec.Clear(); +bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { + file_spec.Clear(); - FileSpec temp_file_spec; - if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) - return false; + FileSpec temp_file_spec; + if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) + return false; - temp_file_spec.AppendPathComponent("lldb"); - if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success()) - return false; + temp_file_spec.AppendPathComponent("lldb"); + if (!FileSystem::MakeDirectory(temp_file_spec, + eFilePermissionsDirectoryDefault) + .Success()) + return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); - return true; + file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + return true; } -bool -HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the header directory for all platforms. - return false; +bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the header directory for all + // platforms. + return false; } -bool -HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the system plugins directory for all platforms. - return false; +bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the system plugins directory for + // all platforms. + return false; } -bool -HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) -{ - return false; -} +bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; } -bool -HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the user plugins directory for all platforms. - return false; +bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the user plugins directory for all + // platforms. + return false; } -void -HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - llvm::Triple triple(llvm::sys::getProcessTriple()); - - arch_32.Clear(); - arch_64.Clear(); - - switch (triple.getArch()) - { - default: - arch_32.SetTriple(triple); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::ppc64: - case llvm::Triple::x86_64: - arch_64.SetTriple(triple); - arch_32.SetTriple(triple.get32BitArchVariant()); - break; - - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::sparcv9: - case llvm::Triple::systemz: - arch_64.SetTriple(triple); - break; - } +void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + llvm::Triple triple(llvm::sys::getProcessTriple()); + + arch_32.Clear(); + arch_64.Clear(); + + switch (triple.getArch()) { + default: + arch_32.SetTriple(triple); + break; + + case llvm::Triple::aarch64: + case llvm::Triple::ppc64: + case llvm::Triple::x86_64: + arch_64.SetTriple(triple); + arch_32.SetTriple(triple.get32BitArchVariant()); + break; + + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::sparcv9: + case llvm::Triple::systemz: + arch_64.SetTriple(triple); + break; + } } diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index 9fea54d1e3f..c1a09e19823 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/HostNativeThreadBase.h" #include "lldb/Core/Log.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/HostNativeThreadBase.h" #include "lldb/Host/ThisThread.h" #include "lldb/Host/ThreadLauncher.h" #include "llvm/ADT/StringExtras.h" @@ -18,65 +18,50 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD) - , m_result(0) -{ -} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread) - , m_result(0) -{ -} + : m_thread(thread), m_result(0) {} -lldb::thread_t -HostNativeThreadBase::GetSystemHandle() const -{ - return m_thread; +lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { + return m_thread; } -lldb::thread_result_t -HostNativeThreadBase::GetResult() const -{ - return m_result; +lldb::thread_result_t HostNativeThreadBase::GetResult() const { + return m_result; } -bool -HostNativeThreadBase::IsJoinable() const -{ - return m_thread != LLDB_INVALID_HOST_THREAD; +bool HostNativeThreadBase::IsJoinable() const { + return m_thread != LLDB_INVALID_HOST_THREAD; } -void -HostNativeThreadBase::Reset() -{ - m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; +void HostNativeThreadBase::Reset() { + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; } -lldb::thread_t -HostNativeThreadBase::Release() -{ - lldb::thread_t result = m_thread; - m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; +lldb::thread_t HostNativeThreadBase::Release() { + lldb::thread_t result = m_thread; + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; - return result; + return result; } lldb::thread_result_t -HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) -{ - ThreadLauncher::HostThreadCreateInfo *info = (ThreadLauncher::HostThreadCreateInfo *)arg; - ThisThread::SetName(info->thread_name.c_str(), HostInfo::GetMaxThreadNameLength()); +HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) { + ThreadLauncher::HostThreadCreateInfo *info = + (ThreadLauncher::HostThreadCreateInfo *)arg; + ThisThread::SetName(info->thread_name.c_str(), + HostInfo::GetMaxThreadNameLength()); - thread_func_t thread_fptr = info->thread_fptr; - thread_arg_t thread_arg = info->thread_arg; + thread_func_t thread_fptr = info->thread_fptr; + thread_arg_t thread_arg = info->thread_arg; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("thread created"); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("thread created"); - delete info; - return thread_fptr(thread_arg); + delete info; + return thread_fptr(thread_arg); } diff --git a/lldb/source/Host/common/HostProcess.cpp b/lldb/source/Host/common/HostProcess.cpp index 0262e1c03c2..2d99d8e1fc9 100644 --- a/lldb/source/Host/common/HostProcess.cpp +++ b/lldb/source/Host/common/HostProcess.cpp @@ -7,59 +7,42 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeProcess.h" #include "lldb/Host/HostProcess.h" +#include "lldb/Host/HostNativeProcess.h" #include "lldb/Host/HostThread.h" using namespace lldb; using namespace lldb_private; -HostProcess::HostProcess() - : m_native_process(new HostNativeProcess) -{ -} +HostProcess::HostProcess() : m_native_process(new HostNativeProcess) {} HostProcess::HostProcess(lldb::process_t process) - : m_native_process(new HostNativeProcess(process)) -{ -} + : m_native_process(new HostNativeProcess(process)) {} -HostProcess::~HostProcess() -{ -} +HostProcess::~HostProcess() {} -Error HostProcess::Terminate() -{ - return m_native_process->Terminate(); -} +Error HostProcess::Terminate() { return m_native_process->Terminate(); } -Error HostProcess::GetMainModule(FileSpec &file_spec) const -{ - return m_native_process->GetMainModule(file_spec); +Error HostProcess::GetMainModule(FileSpec &file_spec) const { + return m_native_process->GetMainModule(file_spec); } -lldb::pid_t HostProcess::GetProcessId() const -{ - return m_native_process->GetProcessId(); +lldb::pid_t HostProcess::GetProcessId() const { + return m_native_process->GetProcessId(); } -bool HostProcess::IsRunning() const -{ - return m_native_process->IsRunning(); -} +bool HostProcess::IsRunning() const { return m_native_process->IsRunning(); } HostThread -HostProcess::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - return m_native_process->StartMonitoring(callback, monitor_signals); +HostProcess::StartMonitoring(const Host::MonitorChildProcessCallback &callback, + bool monitor_signals) { + return m_native_process->StartMonitoring(callback, monitor_signals); } -HostNativeProcessBase &HostProcess::GetNativeProcess() -{ - return *m_native_process; +HostNativeProcessBase &HostProcess::GetNativeProcess() { + return *m_native_process; } -const HostNativeProcessBase &HostProcess::GetNativeProcess() const -{ - return *m_native_process; +const HostNativeProcessBase &HostProcess::GetNativeProcess() const { + return *m_native_process; } diff --git a/lldb/source/Host/common/HostThread.cpp b/lldb/source/Host/common/HostThread.cpp index 7757477126c..738b7ef72f1 100644 --- a/lldb/source/Host/common/HostThread.cpp +++ b/lldb/source/Host/common/HostThread.cpp @@ -7,72 +7,41 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/HostNativeThread.h" using namespace lldb; using namespace lldb_private; -HostThread::HostThread() - : m_native_thread(new HostNativeThread) -{ -} +HostThread::HostThread() : m_native_thread(new HostNativeThread) {} HostThread::HostThread(lldb::thread_t thread) - : m_native_thread(new HostNativeThread(thread)) -{ -} + : m_native_thread(new HostNativeThread(thread)) {} -Error -HostThread::Join(lldb::thread_result_t *result) -{ - return m_native_thread->Join(result); +Error HostThread::Join(lldb::thread_result_t *result) { + return m_native_thread->Join(result); } -Error -HostThread::Cancel() -{ - return m_native_thread->Cancel(); -} +Error HostThread::Cancel() { return m_native_thread->Cancel(); } -void -HostThread::Reset() -{ - return m_native_thread->Reset(); -} +void HostThread::Reset() { return m_native_thread->Reset(); } -lldb::thread_t -HostThread::Release() -{ - return m_native_thread->Release(); -} +lldb::thread_t HostThread::Release() { return m_native_thread->Release(); } -bool -HostThread::IsJoinable() const -{ - return m_native_thread->IsJoinable(); -} +bool HostThread::IsJoinable() const { return m_native_thread->IsJoinable(); } -HostNativeThread & -HostThread::GetNativeThread() -{ - return static_cast(*m_native_thread); +HostNativeThread &HostThread::GetNativeThread() { + return static_cast(*m_native_thread); } -const HostNativeThread & -HostThread::GetNativeThread() const -{ - return static_cast(*m_native_thread); +const HostNativeThread &HostThread::GetNativeThread() const { + return static_cast(*m_native_thread); } -lldb::thread_result_t -HostThread::GetResult() const -{ - return m_native_thread->GetResult(); +lldb::thread_result_t HostThread::GetResult() const { + return m_native_thread->GetResult(); } -bool -HostThread::EqualsThread(lldb::thread_t thread) const -{ - return m_native_thread->GetSystemHandle() == thread; +bool HostThread::EqualsThread(lldb::thread_t thread) const { + return m_native_thread->GetSystemHandle() == thread; } diff --git a/lldb/source/Host/common/LockFileBase.cpp b/lldb/source/Host/common/LockFileBase.cpp index f7469456118..b30acc5d504 100644 --- a/lldb/source/Host/common/LockFileBase.cpp +++ b/lldb/source/Host/common/LockFileBase.cpp @@ -12,113 +12,71 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error -AlreadyLocked () -{ - return Error ("Already locked"); -} - -Error -NotLocked () -{ - return Error ("Not locked"); -} +Error AlreadyLocked() { return Error("Already locked"); } +Error NotLocked() { return Error("Not locked"); } } -LockFileBase::LockFileBase (int fd) : - m_fd (fd), - m_locked (false), - m_start (0), - m_len (0) -{ - -} +LockFileBase::LockFileBase(int fd) + : m_fd(fd), m_locked(false), m_start(0), m_len(0) {} -bool -LockFileBase::IsLocked () const -{ - return m_locked; -} +bool LockFileBase::IsLocked() const { return m_locked; } -Error -LockFileBase::WriteLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoWriteLock (start, len); - }, start, len); +Error LockFileBase::WriteLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoWriteLock(start, len); }, + start, len); } -Error -LockFileBase::TryWriteLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoTryWriteLock (start, len); - }, start, len); +Error LockFileBase::TryWriteLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoTryWriteLock(start, len); }, + start, len); } -Error -LockFileBase::ReadLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoReadLock (start, len); - }, start, len); +Error LockFileBase::ReadLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoReadLock(start, len); }, + start, len); } -Error -LockFileBase::TryReadLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoTryReadLock (start, len); - }, start, len); - +Error LockFileBase::TryReadLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoTryReadLock(start, len); }, + start, len); } -Error -LockFileBase::Unlock () -{ - if (!IsLocked ()) - return NotLocked (); - - const auto error = DoUnlock (); - if (error.Success ()) - { - m_locked = false; - m_start = 0; - m_len = 0; - } - return error; +Error LockFileBase::Unlock() { + if (!IsLocked()) + return NotLocked(); + + const auto error = DoUnlock(); + if (error.Success()) { + m_locked = false; + m_start = 0; + m_len = 0; + } + return error; } -bool -LockFileBase::IsValidFile () const -{ - return m_fd != -1; -} +bool LockFileBase::IsValidFile() const { return m_fd != -1; } -Error -LockFileBase::DoLock (const Locker &locker, const uint64_t start, const uint64_t len) -{ - if (!IsValidFile ()) - return Error("File is invalid"); +Error LockFileBase::DoLock(const Locker &locker, const uint64_t start, + const uint64_t len) { + if (!IsValidFile()) + return Error("File is invalid"); - if (IsLocked ()) - return AlreadyLocked (); + if (IsLocked()) + return AlreadyLocked(); - const auto error = locker (start, len); - if (error.Success ()) - { - m_locked = true; - m_start = start; - m_len = len; - } + const auto error = locker(start, len); + if (error.Success()) { + m_locked = true; + m_start = start; + m_len = len; + } - return error; + return error; } diff --git a/lldb/source/Host/common/MonitoringProcessLauncher.cpp b/lldb/source/Host/common/MonitoringProcessLauncher.cpp index 2845155987e..cb342e71cec 100644 --- a/lldb/source/Host/common/MonitoringProcessLauncher.cpp +++ b/lldb/source/Host/common/MonitoringProcessLauncher.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" @@ -20,81 +20,73 @@ using namespace lldb; using namespace lldb_private; -MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr delegate_launcher) - : m_delegate_launcher(std::move(delegate_launcher)) -{ -} +MonitoringProcessLauncher::MonitoringProcessLauncher( + std::unique_ptr delegate_launcher) + : m_delegate_launcher(std::move(delegate_launcher)) {} HostProcess -MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - ProcessLaunchInfo resolved_info(launch_info); +MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + ProcessLaunchInfo resolved_info(launch_info); - error.Clear(); - char exe_path[PATH_MAX]; + error.Clear(); + char exe_path[PATH_MAX]; - PlatformSP host_platform_sp(Platform::GetHostPlatform()); + PlatformSP host_platform_sp(Platform::GetHostPlatform()); - const ArchSpec &arch_spec = resolved_info.GetArchitecture(); + const ArchSpec &arch_spec = resolved_info.GetArchitecture(); - FileSpec exe_spec(resolved_info.GetExecutableFile()); + FileSpec exe_spec(resolved_info.GetExecutableFile()); - FileSpec::FileType file_type = exe_spec.GetFileType(); - if (file_type != FileSpec::eFileTypeRegular) - { - ModuleSpec module_spec(exe_spec, arch_spec); - lldb::ModuleSP exe_module_sp; - error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); + FileSpec::FileType file_type = exe_spec.GetFileType(); + if (file_type != FileSpec::eFileTypeRegular) { + ModuleSpec module_spec(exe_spec, arch_spec); + lldb::ModuleSP exe_module_sp; + error = + host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); - if (error.Fail()) - return HostProcess(); + if (error.Fail()) + return HostProcess(); - if (exe_module_sp) - exe_spec = exe_module_sp->GetFileSpec(); - } + if (exe_module_sp) + exe_spec = exe_module_sp->GetFileSpec(); + } - if (exe_spec.Exists()) - { - exe_spec.GetPath(exe_path, sizeof(exe_path)); - } - else - { - resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); - return HostProcess(); - } - - resolved_info.SetExecutableFile(exe_spec, false); - assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); + if (exe_spec.Exists()) { + exe_spec.GetPath(exe_path, sizeof(exe_path)); + } else { + resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + return HostProcess(); + } - HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); + resolved_info.SetExecutableFile(exe_spec, false); + assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); - if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + HostProcess process = + m_delegate_launcher->LaunchProcess(resolved_info, error); - Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); + if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - bool monitor_signals = false; - if (callback) - { - // If the ProcessLaunchInfo specified a callback, use that. - monitor_signals = launch_info.GetMonitorSignals(); - } - else - { - callback = Process::SetProcessExitStatus; - } + Host::MonitorChildProcessCallback callback = + launch_info.GetMonitorProcessCallback(); - process.StartMonitoring(callback, monitor_signals); - if (log) - log->PutCString("started monitoring child process."); + bool monitor_signals = false; + if (callback) { + // If the ProcessLaunchInfo specified a callback, use that. + monitor_signals = launch_info.GetMonitorSignals(); + } else { + callback = Process::SetProcessExitStatus; } - else - { - // Invalid process ID, something didn't go well - if (error.Success()) - error.SetErrorString("process launch failed for unknown reasons"); - } - return process; + + process.StartMonitoring(callback, monitor_signals); + if (log) + log->PutCString("started monitoring child process."); + } else { + // Invalid process ID, something didn't go well + if (error.Success()) + error.SetErrorString("process launch failed for unknown reasons"); + } + return process; } diff --git a/lldb/source/Host/common/NativeBreakpoint.cpp b/lldb/source/Host/common/NativeBreakpoint.cpp index 622b4eab172..d61a2f531ac 100644 --- a/lldb/source/Host/common/NativeBreakpoint.cpp +++ b/lldb/source/Host/common/NativeBreakpoint.cpp @@ -9,108 +9,101 @@ #include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/lldb-defines.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/lldb-defines.h" using namespace lldb_private; -NativeBreakpoint::NativeBreakpoint (lldb::addr_t addr) : - m_addr (addr), - m_ref_count (1), - m_enabled (true) -{ - assert (addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address"); +NativeBreakpoint::NativeBreakpoint(lldb::addr_t addr) + : m_addr(addr), m_ref_count(1), m_enabled(true) { + assert(addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address"); } -NativeBreakpoint::~NativeBreakpoint () -{ -} +NativeBreakpoint::~NativeBreakpoint() {} -void -NativeBreakpoint::AddRef () -{ - ++m_ref_count; +void NativeBreakpoint::AddRef() { + ++m_ref_count; - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " bumped up, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " bumped up, new ref count %" PRIu32, + __FUNCTION__, m_addr, m_ref_count); } -int32_t -NativeBreakpoint::DecRef () -{ - --m_ref_count; +int32_t NativeBreakpoint::DecRef() { + --m_ref_count; - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " ref count decremented, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " ref count decremented, new ref count %" PRIu32, + __FUNCTION__, m_addr, m_ref_count); - return m_ref_count; + return m_ref_count; } -Error -NativeBreakpoint::Enable () -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - - if (m_enabled) - { - // We're already enabled. Just log and exit. - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already enabled, ignoring.", __FUNCTION__, m_addr); - return Error (); - } +Error NativeBreakpoint::Enable() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // Log and enable. + if (m_enabled) { + // We're already enabled. Just log and exit. if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", __FUNCTION__, m_addr); - - Error error = DoEnable (); - if (error.Success ()) - { - m_enabled = true; - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", __FUNCTION__, m_addr); - } - else - { - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ()); - } - - return error; -} + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " already enabled, ignoring.", + __FUNCTION__, m_addr); + return Error(); + } + + // Log and enable. + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", + __FUNCTION__, m_addr); + + Error error = DoEnable(); + if (error.Success()) { + m_enabled = true; + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", + __FUNCTION__, m_addr); + } else { + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", + __FUNCTION__, m_addr, error.AsCString()); + } -Error -NativeBreakpoint::Disable () -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + return error; +} - if (!m_enabled) - { - // We're already disabled. Just log and exit. - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already disabled, ignoring.", __FUNCTION__, m_addr); - return Error (); - } +Error NativeBreakpoint::Disable() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // Log and disable. + if (!m_enabled) { + // We're already disabled. Just log and exit. if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", __FUNCTION__, m_addr); - - Error error = DoDisable (); - if (error.Success ()) - { - m_enabled = false; - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", __FUNCTION__, m_addr); - } - else - { - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ()); - } - - return error; + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " already disabled, ignoring.", + __FUNCTION__, m_addr); + return Error(); + } + + // Log and disable. + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", + __FUNCTION__, m_addr); + + Error error = DoDisable(); + if (error.Success()) { + m_enabled = false; + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", + __FUNCTION__, m_addr); + } else { + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", + __FUNCTION__, m_addr, error.AsCString()); + } + + return error; } diff --git a/lldb/source/Host/common/NativeBreakpointList.cpp b/lldb/source/Host/common/NativeBreakpointList.cpp index 67873a06dd2..a76d72ff708 100644 --- a/lldb/source/Host/common/NativeBreakpointList.cpp +++ b/lldb/source/Host/common/NativeBreakpointList.cpp @@ -17,204 +17,213 @@ using namespace lldb; using namespace lldb_private; -NativeBreakpointList::NativeBreakpointList() : m_mutex() -{ -} +NativeBreakpointList::NativeBreakpointList() : m_mutex() {} + +Error NativeBreakpointList::AddRef(lldb::addr_t addr, size_t size_hint, + bool hardware, + CreateBreakpointFunc create_func) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + std::lock_guard guard(m_mutex); + + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find(addr); + if (iter != m_breakpoints.end()) { + // Yes - bump up ref count. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- already enabled, upping ref count", + __FUNCTION__, addr); -Error -NativeBreakpointList::AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + iter->second->AddRef(); + return Error(); + } + + // Create a new breakpoint using the given create func. + if (log) + log->Printf( + "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + NativeBreakpointSP breakpoint_sp; + Error error = create_func(addr, size_hint, hardware, breakpoint_sp); + if (error.Fail()) { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + log->Printf( + "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s -- FAILED: %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false", + error.AsCString()); + return error; + } - std::lock_guard guard(m_mutex); + // Remember the breakpoint. + assert(breakpoint_sp && "NativeBreakpoint create function succeeded but " + "returned NULL breakpoint"); + m_breakpoints.insert(BreakpointMap::value_type(addr, breakpoint_sp)); - // Check if the breakpoint is already set. - auto iter = m_breakpoints.find (addr); - if (iter != m_breakpoints.end ()) - { - // Yes - bump up ref count. - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already enabled, upping ref count", __FUNCTION__, addr); + return error; +} - iter->second->AddRef (); - return Error (); - } +Error NativeBreakpointList::DecRef(lldb::addr_t addr) { + Error error; - // Create a new breakpoint using the given create func. - if (log) - log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - NativeBreakpointSP breakpoint_sp; - Error error = create_func (addr, size_hint, hardware, breakpoint_sp); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s -- FAILED: %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false", error.AsCString ()); - return error; - } + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - // Remember the breakpoint. - assert (breakpoint_sp && "NativeBreakpoint create function succeeded but returned NULL breakpoint"); - m_breakpoints.insert (BreakpointMap::value_type (addr, breakpoint_sp)); + std::lock_guard guard(m_mutex); + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + error.SetErrorString("breakpoint not found"); return error; -} + } -Error -NativeBreakpointList::DecRef (lldb::addr_t addr) -{ - Error error; + // Decrement ref count. + const int32_t new_ref_count = iter->second->DecRef(); + assert(new_ref_count >= 0 && "NativeBreakpoint ref count went negative"); - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (new_ref_count > 0) { + // Still references to this breakpoint. Leave it alone. if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard guard(m_mutex); - - // Check if the breakpoint is already set. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - error.SetErrorString ("breakpoint not found"); - return error; - } - - // Decrement ref count. - const int32_t new_ref_count = iter->second->DecRef (); - assert (new_ref_count >= 0 && "NativeBreakpoint ref count went negative"); + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- new breakpoint ref count %" PRIu32, + __FUNCTION__, addr, new_ref_count); + return error; + } - if (new_ref_count > 0) - { - // Still references to this breakpoint. Leave it alone. - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- new breakpoint ref count %" PRIu32, __FUNCTION__, addr, new_ref_count); - return error; - } + // Breakpoint has no more references. Disable it if it's not + // already disabled. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removing due to no remaining references", + __FUNCTION__, addr); - // Breakpoint has no more references. Disable it if it's not - // already disabled. + // If it's enabled, we need to disable it. + if (iter->second->IsEnabled()) { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", __FUNCTION__, addr); - - // If it's enabled, we need to disable it. - if (iter->second->IsEnabled ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- currently enabled, now disabling", __FUNCTION__, addr); - error = iter->second->Disable (); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removal FAILED: %s", __FUNCTION__, addr, error.AsCString ()); - // Continue since we still want to take it out of the breakpoint list. - } - } - else - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already disabled, nothing to do", __FUNCTION__, addr); + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- currently enabled, now disabling", + __FUNCTION__, addr); + error = iter->second->Disable(); + if (error.Fail()) { + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removal FAILED: %s", + __FUNCTION__, addr, error.AsCString()); + // Continue since we still want to take it out of the breakpoint list. } - - // Take the breakpoint out of the list. + } else { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removed from breakpoint map", __FUNCTION__, addr); - - m_breakpoints.erase (iter); - return error; + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- already disabled, nothing to do", + __FUNCTION__, addr); + } + + // Take the breakpoint out of the list. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removed from breakpoint map", + __FUNCTION__, addr); + + m_breakpoints.erase(iter); + return error; } -Error -NativeBreakpointList::EnableBreakpoint (lldb::addr_t addr) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard guard(m_mutex); - - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - return Error ("breakpoint not found"); - } +Error NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - // Enable it. - return iter->second->Enable (); -} + std::lock_guard guard(m_mutex); -Error -NativeBreakpointList::DisableBreakpoint (lldb::addr_t addr) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard guard(m_mutex); - - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - return Error ("breakpoint not found"); - } + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + return Error("breakpoint not found"); + } - // Disable it. - return iter->second->Disable (); + // Enable it. + return iter->second->Enable(); } -Error -NativeBreakpointList::GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); +Error NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - std::lock_guard guard(m_mutex); + std::lock_guard guard(m_mutex); - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - breakpoint_sp.reset (); - return Error ("breakpoint not found"); - } + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + return Error("breakpoint not found"); + } - // Disable it. - breakpoint_sp = iter->second; - return Error (); + // Disable it. + return iter->second->Disable(); } -Error -NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const -{ - for (const auto &map : m_breakpoints) - { - lldb::addr_t bp_addr = map.first; - // Breapoint not in range, ignore - if (bp_addr < addr || addr + size <= bp_addr) - continue; - const auto &bp_sp = map.second; - // Not software breakpoint, ignore - if (!bp_sp->IsSoftwareBreakpoint()) - continue; - auto software_bp_sp = std::static_pointer_cast(bp_sp); - auto opcode_addr = static_cast(buf) + bp_addr - addr; - auto saved_opcodes = software_bp_sp->m_saved_opcodes; - auto opcode_size = software_bp_sp->m_opcode_size; - ::memcpy(opcode_addr, saved_opcodes, opcode_size); - } - return Error(); +Error NativeBreakpointList::GetBreakpoint(lldb::addr_t addr, + NativeBreakpointSP &breakpoint_sp) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); + + std::lock_guard guard(m_mutex); + + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + breakpoint_sp.reset(); + return Error("breakpoint not found"); + } + + // Disable it. + breakpoint_sp = iter->second; + return Error(); +} + +Error NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, + size_t size) const { + for (const auto &map : m_breakpoints) { + lldb::addr_t bp_addr = map.first; + // Breapoint not in range, ignore + if (bp_addr < addr || addr + size <= bp_addr) + continue; + const auto &bp_sp = map.second; + // Not software breakpoint, ignore + if (!bp_sp->IsSoftwareBreakpoint()) + continue; + auto software_bp_sp = std::static_pointer_cast(bp_sp); + auto opcode_addr = static_cast(buf) + bp_addr - addr; + auto saved_opcodes = software_bp_sp->m_saved_opcodes; + auto opcode_size = software_bp_sp->m_opcode_size; + ::memcpy(opcode_addr, saved_opcodes, opcode_size); + } + return Error(); } diff --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp index bdc58fb8b43..d77b8b2e974 100644 --- a/lldb/source/Host/common/NativeProcessProtocol.cpp +++ b/lldb/source/Host/common/NativeProcessProtocol.cpp @@ -9,7 +9,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/lldb-enumerations.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" @@ -21,6 +20,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -30,458 +30,403 @@ using namespace lldb_private; // ----------------------------------------------------------------------------- NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) - : m_pid(pid), - m_threads(), - m_current_thread_id(LLDB_INVALID_THREAD_ID), - m_threads_mutex(), - m_state(lldb::eStateInvalid), - m_state_mutex(), - m_exit_type(eExitTypeInvalid), - m_exit_status(0), - m_exit_description(), - m_delegates_mutex(), - m_delegates(), - m_breakpoint_list(), - m_watchpoint_list(), - m_terminal_fd(-1), - m_stop_id(0) -{ -} - -lldb_private::Error -NativeProcessProtocol::Interrupt () -{ - Error error; -#if !defined (SIGSTOP) - error.SetErrorString ("local host does not support signaling"); - return error; + : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), + m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), + m_exit_type(eExitTypeInvalid), m_exit_status(0), m_exit_description(), + m_delegates_mutex(), m_delegates(), m_breakpoint_list(), + m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} + +lldb_private::Error NativeProcessProtocol::Interrupt() { + Error error; +#if !defined(SIGSTOP) + error.SetErrorString("local host does not support signaling"); + return error; #else - return Signal (SIGSTOP); + return Signal(SIGSTOP); #endif } lldb_private::Error -NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) -{ - // Default: not implemented. - return Error ("not implemented"); +NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + // Default: not implemented. + return Error("not implemented"); } -bool -NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description) -{ - if (m_state == lldb::eStateExited) - { - *exit_type = m_exit_type; - *status = m_exit_status; - exit_description = m_exit_description; - return true; - } +bool NativeProcessProtocol::GetExitStatus(ExitType *exit_type, int *status, + std::string &exit_description) { + if (m_state == lldb::eStateExited) { + *exit_type = m_exit_type; + *status = m_exit_status; + exit_description = m_exit_description; + return true; + } - *status = 0; - return false; + *status = 0; + return false; } -bool -NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange) -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called", - __FUNCTION__, - exit_type, - status, +bool NativeProcessProtocol::SetExitStatus(ExitType exit_type, int status, + const char *exit_description, + bool bNotifyStateChange) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessProtocol::%s(%d, %d, %s, %s) called", + __FUNCTION__, exit_type, status, exit_description ? exit_description : "nullptr", bNotifyStateChange ? "true" : "false"); - // Exit status already set - if (m_state == lldb::eStateExited) - { - if (log) - log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status); - return false; - } + // Exit status already set + if (m_state == lldb::eStateExited) { + if (log) + log->Printf("NativeProcessProtocol::%s exit status already set to %d, " + "ignoring new set to %d", + __FUNCTION__, m_exit_status, status); + return false; + } - m_state = lldb::eStateExited; + m_state = lldb::eStateExited; - m_exit_type = exit_type; - m_exit_status = status; - if (exit_description && exit_description[0]) - m_exit_description = exit_description; - else - m_exit_description.clear(); + m_exit_type = exit_type; + m_exit_status = status; + if (exit_description && exit_description[0]) + m_exit_description = exit_description; + else + m_exit_description.clear(); - if (bNotifyStateChange) - SynchronouslyNotifyProcessStateChanged (lldb::eStateExited); + if (bNotifyStateChange) + SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); - return true; + return true; } -NativeThreadProtocolSP -NativeProcessProtocol::GetThreadAtIndex (uint32_t idx) -{ - std::lock_guard guard(m_threads_mutex); - if (idx < m_threads.size ()) - return m_threads[idx]; - return NativeThreadProtocolSP (); +NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { + std::lock_guard guard(m_threads_mutex); + if (idx < m_threads.size()) + return m_threads[idx]; + return NativeThreadProtocolSP(); } NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByIDUnlocked (lldb::tid_t tid) -{ - for (auto thread_sp : m_threads) - { - if (thread_sp->GetID() == tid) - return thread_sp; - } - return NativeThreadProtocolSP (); +NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { + for (auto thread_sp : m_threads) { + if (thread_sp->GetID() == tid) + return thread_sp; + } + return NativeThreadProtocolSP(); } -NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) -{ - std::lock_guard guard(m_threads_mutex); - return GetThreadByIDUnlocked (tid); +NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { + std::lock_guard guard(m_threads_mutex); + return GetThreadByIDUnlocked(tid); } -bool -NativeProcessProtocol::IsAlive () const -{ - return m_state != eStateDetached - && m_state != eStateExited - && m_state != eStateInvalid - && m_state != eStateUnloaded; +bool NativeProcessProtocol::IsAlive() const { + return m_state != eStateDetached && m_state != eStateExited && + m_state != eStateInvalid && m_state != eStateUnloaded; } -bool -NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const -{ - ArchSpec process_arch; - if (!GetArchitecture (process_arch)) - return false; - byte_order = process_arch.GetByteOrder (); - return true; +bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { + ArchSpec process_arch; + if (!GetArchitecture(process_arch)) + return false; + byte_order = process_arch.GetByteOrder(); + return true; } -const NativeWatchpointList::WatchpointMap& -NativeProcessProtocol::GetWatchpointMap () const -{ - return m_watchpoint_list.GetWatchpointMap(); +const NativeWatchpointList::WatchpointMap & +NativeProcessProtocol::GetWatchpointMap() const { + return m_watchpoint_list.GetWatchpointMap(); } -uint32_t -NativeProcessProtocol::GetMaxWatchpoints () const -{ - // This default implementation will return the number of - // *hardware* breakpoints available. MacOSX and other OS - // implementations that support software breakpoints will want to - // override this correctly for their implementation. - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - // get any thread - NativeThreadProtocolSP thread_sp (const_cast (this)->GetThreadAtIndex (0)); - if (!thread_sp) - { - if (log) - log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__); - return 0; - } +uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { + // This default implementation will return the number of + // *hardware* breakpoints available. MacOSX and other OS + // implementations that support software breakpoints will want to + // override this correctly for their implementation. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // get any thread + NativeThreadProtocolSP thread_sp( + const_cast(this)->GetThreadAtIndex(0)); + if (!thread_sp) { + if (log) + log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " + "grab a NativeRegisterContext!", + __FUNCTION__); + return 0; + } + + NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); + if (!reg_ctx_sp) { + if (log) + log->Warning("NativeProcessProtocol::%s (): failed to get a " + "RegisterContextNativeProcess from the first thread!", + __FUNCTION__); + return 0; + } + + return reg_ctx_sp->NumSupportedHardwareWatchpoints(); +} - NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ()); - if (!reg_ctx_sp) - { +Error NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, + bool hardware) { + // This default implementation assumes setting the watchpoint for + // the process will require setting the watchpoint for each of the + // threads. Furthermore, it will track watchpoints set for the + // process and will add them to each thread that is attached to + // via the (FIXME implement) OnThreadAttached () method. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Update the thread list + UpdateThreads(); + + // Keep track of the threads we successfully set the watchpoint + // for. If one of the thread watchpoint setting operations fails, + // back off and remove the watchpoint for all the threads that + // were successfully set so we get back to a consistent state. + std::vector watchpoint_established_threads; + + // Tell each thread to set a watchpoint. In the event that + // hardware watchpoints are requested but the SetWatchpoint fails, + // try to set a software watchpoint as a fallback. It's + // conceivable that if there are more threads than hardware + // watchpoints available, some of the threads will fail to set + // hardware watchpoints while software ones may be available. + std::lock_guard guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + Error thread_error = + thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); + if (thread_error.Fail() && hardware) { + // Try software watchpoints since we failed on hardware watchpoint setting + // and we may have just run out of hardware watchpoints. + thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); + if (thread_error.Success()) { if (log) - log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__); - return 0; + log->Warning( + "hardware watchpoint requested but software watchpoint set"); + } } - return reg_ctx_sp->NumSupportedHardwareWatchpoints (); -} - -Error -NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) -{ - // This default implementation assumes setting the watchpoint for - // the process will require setting the watchpoint for each of the - // threads. Furthermore, it will track watchpoints set for the - // process and will add them to each thread that is attached to - // via the (FIXME implement) OnThreadAttached () method. - - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - // Update the thread list - UpdateThreads (); - - // Keep track of the threads we successfully set the watchpoint - // for. If one of the thread watchpoint setting operations fails, - // back off and remove the watchpoint for all the threads that - // were successfully set so we get back to a consistent state. - std::vector watchpoint_established_threads; - - // Tell each thread to set a watchpoint. In the event that - // hardware watchpoints are requested but the SetWatchpoint fails, - // try to set a software watchpoint as a fallback. It's - // conceivable that if there are more threads than hardware - // watchpoints available, some of the threads will fail to set - // hardware watchpoints while software ones may be available. - std::lock_guard guard(m_threads_mutex); - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware); - if (thread_error.Fail () && hardware) - { - // Try software watchpoints since we failed on hardware watchpoint setting - // and we may have just run out of hardware watchpoints. - thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false); - if (thread_error.Success ()) - { - if (log) - log->Warning ("hardware watchpoint requested but software watchpoint set"); - } + if (thread_error.Success()) { + // Remember that we set this watchpoint successfully in + // case we need to clear it later. + watchpoint_established_threads.push_back(thread_sp); + } else { + // Unset the watchpoint for each thread we successfully + // set so that we get back to a consistent state of "not + // set" for the watchpoint. + for (auto unwatch_thread_sp : watchpoint_established_threads) { + Error remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); + if (remove_error.Fail() && log) { + log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " + "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", + __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), + remove_error.AsCString()); } + } - if (thread_error.Success ()) - { - // Remember that we set this watchpoint successfully in - // case we need to clear it later. - watchpoint_established_threads.push_back (thread_sp); - } - else - { - // Unset the watchpoint for each thread we successfully - // set so that we get back to a consistent state of "not - // set" for the watchpoint. - for (auto unwatch_thread_sp : watchpoint_established_threads) - { - Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr); - if (remove_error.Fail () && log) - { - log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ()); - } - } - - return thread_error; - } + return thread_error; } - return m_watchpoint_list.Add (addr, size, watch_flags, hardware); + } + return m_watchpoint_list.Add(addr, size, watch_flags, hardware); } -Error -NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) -{ - // Update the thread list - UpdateThreads (); - - Error overall_error; - - std::lock_guard guard(m_threads_mutex); - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - const Error thread_error = thread_sp->RemoveWatchpoint (addr); - if (thread_error.Fail ()) - { - // Keep track of the first thread error if any threads - // fail. We want to try to remove the watchpoint from - // every thread, though, even if one or more have errors. - if (!overall_error.Fail ()) - overall_error = thread_error; - } - } - const Error error = m_watchpoint_list.Remove(addr); - return overall_error.Fail() ? overall_error : error; -} +Error NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { + // Update the thread list + UpdateThreads(); -bool -NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate) -{ - std::lock_guard guard(m_delegates_mutex); - if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ()) - return false; + Error overall_error; - m_delegates.push_back (&native_delegate); - native_delegate.InitializeDelegate (this); - return true; + std::lock_guard guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + const Error thread_error = thread_sp->RemoveWatchpoint(addr); + if (thread_error.Fail()) { + // Keep track of the first thread error if any threads + // fail. We want to try to remove the watchpoint from + // every thread, though, even if one or more have errors. + if (!overall_error.Fail()) + overall_error = thread_error; + } + } + const Error error = m_watchpoint_list.Remove(addr); + return overall_error.Fail() ? overall_error : error; } -bool -NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate) -{ - std::lock_guard guard(m_delegates_mutex); - - const auto initial_size = m_delegates.size (); - m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ()); +bool NativeProcessProtocol::RegisterNativeDelegate( + NativeDelegate &native_delegate) { + std::lock_guard guard(m_delegates_mutex); + if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != + m_delegates.end()) + return false; - // We removed the delegate if the count of delegates shrank after - // removing all copies of the given native_delegate from the vector. - return m_delegates.size () < initial_size; + m_delegates.push_back(&native_delegate); + native_delegate.InitializeDelegate(this); + return true; } -void -NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); +bool NativeProcessProtocol::UnregisterNativeDelegate( + NativeDelegate &native_delegate) { + std::lock_guard guard(m_delegates_mutex); - std::lock_guard guard(m_delegates_mutex); - for (auto native_delegate: m_delegates) - native_delegate->ProcessStateChanged (this, state); + const auto initial_size = m_delegates.size(); + m_delegates.erase( + remove(m_delegates.begin(), m_delegates.end(), &native_delegate), + m_delegates.end()); - if (log) - { - if (!m_delegates.empty ()) - { - log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64, - __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); - } - else - { - log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates", - __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); - } - } + // We removed the delegate if the count of delegates shrank after + // removing all copies of the given native_delegate from the vector. + return m_delegates.size() < initial_size; } -void -NativeProcessProtocol::NotifyDidExec () -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); - - { - std::lock_guard guard(m_delegates_mutex); - for (auto native_delegate: m_delegates) - native_delegate->DidExec (this); +void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( + lldb::StateType state) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + std::lock_guard guard(m_delegates_mutex); + for (auto native_delegate : m_delegates) + native_delegate->ProcessStateChanged(this, state); + + if (log) { + if (!m_delegates.empty()) { + log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " + "from process %" PRIu64, + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); + } else { + log->Printf("NativeProcessProtocol::%s: would send state notification " + "[%s] from process %" PRIu64 ", but no delegates", + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } + } } +void NativeProcessProtocol::NotifyDidExec() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessProtocol::%s - preparing to call delegates", + __FUNCTION__); -Error -NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + { + std::lock_guard guard(m_delegates_mutex); + for (auto native_delegate : m_delegates) + native_delegate->DidExec(this); + } +} - return m_breakpoint_list.AddRef (addr, size_hint, false, - [this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error - { return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); }); +Error NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, + uint32_t size_hint) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); + + return m_breakpoint_list.AddRef( + addr, size_hint, false, + [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, + NativeBreakpointSP &breakpoint_sp) -> Error { + return SoftwareBreakpoint::CreateSoftwareBreakpoint( + *this, addr, size_hint, breakpoint_sp); + }); } -Error -NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.DecRef (addr); +Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.DecRef(addr); } -Error -NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.EnableBreakpoint (addr); +Error NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.EnableBreakpoint(addr); } -Error -NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.DisableBreakpoint (addr); +Error NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.DisableBreakpoint(addr); } -lldb::StateType -NativeProcessProtocol::GetState () const -{ - std::lock_guard guard(m_state_mutex); - return m_state; +lldb::StateType NativeProcessProtocol::GetState() const { + std::lock_guard guard(m_state_mutex); + return m_state; } -void -NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates) -{ - std::lock_guard guard(m_state_mutex); +void NativeProcessProtocol::SetState(lldb::StateType state, + bool notify_delegates) { + std::lock_guard guard(m_state_mutex); - if (state == m_state) - return; + if (state == m_state) + return; - m_state = state; + m_state = state; - if (StateIsStoppedState (state, false)) - { - ++m_stop_id; + if (StateIsStoppedState(state, false)) { + ++m_stop_id; - // Give process a chance to do any stop id bump processing, such as - // clearing cached data that is invalidated each time the process runs. - // Note if/when we support some threads running, we'll end up needing - // to manage this per thread and per process. - DoStopIDBumped (m_stop_id); - } + // Give process a chance to do any stop id bump processing, such as + // clearing cached data that is invalidated each time the process runs. + // Note if/when we support some threads running, we'll end up needing + // to manage this per thread and per process. + DoStopIDBumped(m_stop_id); + } - // Optionally notify delegates of the state change. - if (notify_delegates) - SynchronouslyNotifyProcessStateChanged (state); + // Optionally notify delegates of the state change. + if (notify_delegates) + SynchronouslyNotifyProcessStateChanged(state); } -uint32_t NativeProcessProtocol::GetStopID () const -{ - std::lock_guard guard(m_state_mutex); - return m_stop_id; +uint32_t NativeProcessProtocol::GetStopID() const { + std::lock_guard guard(m_state_mutex); + return m_stop_id; } -void -NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */) -{ - // Default implementation does nothing. +void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { + // Default implementation does nothing. } -Error -NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, - ArchSpec &arch) -{ - // Grab process info for the running process. - ProcessInstanceInfo process_info; - if (!Host::GetProcessInfo(pid, process_info)) - return Error("failed to get process info"); - - // Resolve the executable module. - ModuleSpecList module_specs; - if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), - 0, 0, module_specs)) - return Error("failed to get module specifications"); - lldbassert(module_specs.GetSize() == 1); - - arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); - if (arch.IsValid()) - return Error(); - else - return Error("failed to retrieve a valid architecture from the exe module"); +Error NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, + ArchSpec &arch) { + // Grab process info for the running process. + ProcessInstanceInfo process_info; + if (!Host::GetProcessInfo(pid, process_info)) + return Error("failed to get process info"); + + // Resolve the executable module. + ModuleSpecList module_specs; + if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, + 0, module_specs)) + return Error("failed to get module specifications"); + lldbassert(module_specs.GetSize() == 1); + + arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); + if (arch.IsValid()) + return Error(); + else + return Error("failed to retrieve a valid architecture from the exe module"); } #ifndef __linux__ -// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are +// These need to be implemented to support lldb-gdb-server on a given platform. +// Stubs are // provided to make the rest of the code link on non-supported platforms. -Error -NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) -{ - llvm_unreachable("Platform has no NativeProcessProtocol support"); +Error NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop, + NativeProcessProtocolSP &process_sp) { + llvm_unreachable("Platform has no NativeProcessProtocol support"); } -Error -NativeProcessProtocol::Attach (lldb::pid_t pid, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) -{ - llvm_unreachable("Platform has no NativeProcessProtocol support"); +Error NativeProcessProtocol::Attach(lldb::pid_t pid, + NativeDelegate &native_delegate, + MainLoop &mainloop, + NativeProcessProtocolSP &process_sp) { + llvm_unreachable("Platform has no NativeProcessProtocol support"); } #endif diff --git a/lldb/source/Host/common/NativeRegisterContext.cpp b/lldb/source/Host/common/NativeRegisterContext.cpp index 5ed0a436233..e143b9a9ce2 100644 --- a/lldb/source/Host/common/NativeRegisterContext.cpp +++ b/lldb/source/Host/common/NativeRegisterContext.cpp @@ -12,25 +12,21 @@ #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" +#include "lldb/Host/PosixApi.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Host/PosixApi.h" using namespace lldb; using namespace lldb_private; -NativeRegisterContext::NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx) : - m_thread (thread), - m_concrete_frame_idx (concrete_frame_idx) -{ -} +NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread, + uint32_t concrete_frame_idx) + : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -NativeRegisterContext::~NativeRegisterContext() -{ -} +NativeRegisterContext::~NativeRegisterContext() {} // FIXME revisit invalidation, process stop ids, etc. Right now we don't // support caching in NativeRegisterContext. We can do this later by @@ -59,459 +55,385 @@ NativeRegisterContext::~NativeRegisterContext() // } // } - const RegisterInfo * -NativeRegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx) -{ - if (reg_name && reg_name[0]) - { - const uint32_t num_registers = GetRegisterCount(); - for (uint32_t reg = start_idx; reg < num_registers; ++reg) - { - const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); - - if ((reg_info->name != nullptr && ::strcasecmp (reg_info->name, reg_name) == 0) || - (reg_info->alt_name != nullptr && ::strcasecmp (reg_info->alt_name, reg_name) == 0)) - { - return reg_info; - } - } +NativeRegisterContext::GetRegisterInfoByName(const char *reg_name, + uint32_t start_idx) { + if (reg_name && reg_name[0]) { + const uint32_t num_registers = GetRegisterCount(); + for (uint32_t reg = start_idx; reg < num_registers; ++reg) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + + if ((reg_info->name != nullptr && + ::strcasecmp(reg_info->name, reg_name) == 0) || + (reg_info->alt_name != nullptr && + ::strcasecmp(reg_info->alt_name, reg_name) == 0)) { + return reg_info; + } } + } + return nullptr; +} + +const RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind, + uint32_t num) { + const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); + if (reg_num == LLDB_INVALID_REGNUM) return nullptr; + return GetRegisterInfoAtIndex(reg_num); } -const RegisterInfo * -NativeRegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num) -{ - const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); - if (reg_num == LLDB_INVALID_REGNUM) - return nullptr; - return GetRegisterInfoAtIndex (reg_num); +const char *NativeRegisterContext::GetRegisterName(uint32_t reg) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info) + return reg_info->name; + return nullptr; } -const char * -NativeRegisterContext::GetRegisterName (uint32_t reg) -{ - const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info) - return reg_info->name; +const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex( + uint32_t reg_index) const { + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) return nullptr; -} -const char* -NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const -{ - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - return nullptr; - - for (uint32_t set_index = 0; set_index < GetRegisterSetCount (); ++set_index) - { - const RegisterSet *const reg_set = GetRegisterSet (set_index); - if (!reg_set) - continue; - - for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; ++reg_num_index) - { - const uint32_t reg_num = reg_set->registers[reg_num_index]; - // FIXME double check we're checking the right register kind here. - if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) - { - // The given register is a member of this register set. Return the register set name. - return reg_set->name; - } - } + for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) { + const RegisterSet *const reg_set = GetRegisterSet(set_index); + if (!reg_set) + continue; + + for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; + ++reg_num_index) { + const uint32_t reg_num = reg_set->registers[reg_num_index]; + // FIXME double check we're checking the right register kind here. + if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) { + // The given register is a member of this register set. Return the + // register set name. + return reg_set->name; + } } + } - // Didn't find it. - return nullptr; + // Didn't find it. + return nullptr; } -lldb::addr_t -NativeRegisterContext::GetPC (lldb::addr_t fail_value) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); +lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - if (log) - log->Printf ("NativeRegisterContext::%s using reg index %" PRIu32 " (default %" PRIu64 ")", __FUNCTION__, reg, fail_value); + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + if (log) + log->Printf("NativeRegisterContext::%s using reg index %" PRIu32 + " (default %" PRIu64 ")", + __FUNCTION__, reg, fail_value); - const uint64_t retval = ReadRegisterAsUnsigned (reg, fail_value); + const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value); - if (log) - log->Printf ("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, __FUNCTION__, retval); + if (log) + log->Printf("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, + __FUNCTION__, retval); - return retval; + return retval; } lldb::addr_t -NativeRegisterContext::GetPCfromBreakpointLocation (lldb::addr_t fail_value) -{ - return GetPC (fail_value); +NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) { + return GetPC(fail_value); } -Error -NativeRegisterContext::SetPC (lldb::addr_t pc) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - return WriteRegisterFromUnsigned (reg, pc); +Error NativeRegisterContext::SetPC(lldb::addr_t pc) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + return WriteRegisterFromUnsigned(reg, pc); } -lldb::addr_t -NativeRegisterContext::GetSP (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP); + return ReadRegisterAsUnsigned(reg, fail_value); } -Error -NativeRegisterContext::SetSP (lldb::addr_t sp) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - return WriteRegisterFromUnsigned (reg, sp); +Error NativeRegisterContext::SetSP(lldb::addr_t sp) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP); + return WriteRegisterFromUnsigned(reg, sp); } -lldb::addr_t -NativeRegisterContext::GetFP (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FP); + return ReadRegisterAsUnsigned(reg, fail_value); } -Error -NativeRegisterContext::SetFP (lldb::addr_t fp) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - return WriteRegisterFromUnsigned (reg, fp); +Error NativeRegisterContext::SetFP(lldb::addr_t fp) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FP); + return WriteRegisterFromUnsigned(reg, fp); } -lldb::addr_t -NativeRegisterContext::GetReturnAddress (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA); + return ReadRegisterAsUnsigned(reg, fail_value); } -lldb::addr_t -NativeRegisterContext::GetFlags (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS); + return ReadRegisterAsUnsigned(reg, fail_value); } - lldb::addr_t -NativeRegisterContext::ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value) -{ - if (reg != LLDB_INVALID_REGNUM) - return ReadRegisterAsUnsigned (GetRegisterInfoAtIndex (reg), fail_value); - return fail_value; +NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg, + lldb::addr_t fail_value) { + if (reg != LLDB_INVALID_REGNUM) + return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value); + return fail_value; } uint64_t -NativeRegisterContext::ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - - if (reg_info) - { - RegisterValue value; - Error error = ReadRegister (reg_info, value); - if (error.Success ()) - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() succeeded, value %" PRIu64, __FUNCTION__, value.GetAsUInt64()); - return value.GetAsUInt64(); - } - else - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() failed, error %s", __FUNCTION__, error.AsCString ()); - } - } - else - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() null reg_info", __FUNCTION__); +NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, + lldb::addr_t fail_value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + if (reg_info) { + RegisterValue value; + Error error = ReadRegister(reg_info, value); + if (error.Success()) { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() succeeded, value " + "%" PRIu64, + __FUNCTION__, value.GetAsUInt64()); + return value.GetAsUInt64(); + } else { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() failed, error %s", + __FUNCTION__, error.AsCString()); } - return fail_value; + } else { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() null reg_info", + __FUNCTION__); + } + return fail_value; } -Error -NativeRegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval) -{ - if (reg == LLDB_INVALID_REGNUM) - return Error ("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__); - return WriteRegisterFromUnsigned (GetRegisterInfoAtIndex (reg), uval); +Error NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg, + uint64_t uval) { + if (reg == LLDB_INVALID_REGNUM) + return Error("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__); + return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval); } -Error -NativeRegisterContext::WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval) -{ - assert (reg_info); - if (!reg_info) - return Error ("reg_info is nullptr"); +Error NativeRegisterContext::WriteRegisterFromUnsigned( + const RegisterInfo *reg_info, uint64_t uval) { + assert(reg_info); + if (!reg_info) + return Error("reg_info is nullptr"); - RegisterValue value; - if (!value.SetUInt(uval, reg_info->byte_size)) - return Error ("RegisterValue::SetUInt () failed"); + RegisterValue value; + if (!value.SetUInt(uval, reg_info->byte_size)) + return Error("RegisterValue::SetUInt () failed"); - return WriteRegister (reg_info, value); + return WriteRegister(reg_info, value); } -lldb::tid_t -NativeRegisterContext::GetThreadID() const -{ - return m_thread.GetID(); +lldb::tid_t NativeRegisterContext::GetThreadID() const { + return m_thread.GetID(); } -uint32_t -NativeRegisterContext::NumSupportedHardwareBreakpoints () -{ - return 0; -} +uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; } -uint32_t -NativeRegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - return LLDB_INVALID_INDEX32; +uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + return LLDB_INVALID_INDEX32; } -bool -NativeRegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx) -{ - return false; +bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { + return false; } +uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; } -uint32_t -NativeRegisterContext::NumSupportedHardwareWatchpoints () -{ - return 0; +uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, + uint32_t watch_flags) { + return LLDB_INVALID_INDEX32; } -uint32_t -NativeRegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - return LLDB_INVALID_INDEX32; +bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) { + return false; } -bool -NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index) -{ - return false; +Error NativeRegisterContext::ClearAllHardwareWatchpoints() { + return Error("not implemented"); } -Error -NativeRegisterContext::ClearAllHardwareWatchpoints () -{ - return Error ("not implemented"); +Error NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { + is_hit = false; + return Error("not implemented"); } -Error -NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) -{ - is_hit = false; - return Error ("not implemented"); +Error NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) { + wp_index = LLDB_INVALID_INDEX32; + return Error("not implemented"); } -Error -NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - wp_index = LLDB_INVALID_INDEX32; - return Error ("not implemented"); +Error NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + is_vacant = false; + return Error("not implemented"); } -Error -NativeRegisterContext::IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) -{ - is_vacant = false; - return Error ("not implemented"); +lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) { + return LLDB_INVALID_ADDRESS; } -lldb::addr_t -NativeRegisterContext::GetWatchpointAddress (uint32_t wp_index) -{ - return LLDB_INVALID_ADDRESS; +lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) { + return LLDB_INVALID_ADDRESS; } -lldb::addr_t -NativeRegisterContext::GetWatchpointHitAddress (uint32_t wp_index) -{ - return LLDB_INVALID_ADDRESS; -} +bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; } -bool -NativeRegisterContext::HardwareSingleStep (bool enable) -{ - return false; -} +Error NativeRegisterContext::ReadRegisterValueFromMemory( + const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len, + RegisterValue ®_value) { + Error error; + if (reg_info == nullptr) { + error.SetErrorString("invalid register info argument."); + return error; + } + + // Moving from addr into a register + // + // Case 1: src_len == dst_len + // + // |AABBCCDD| Address contents + // |AABBCCDD| Register contents + // + // Case 2: src_len > dst_len + // + // Error! (The register should always be big enough to hold the data) + // + // Case 3: src_len < dst_len + // + // |AABB| Address contents + // |AABB0000| Register contents [on little-endian hardware] + // |0000AABB| Register contents [on big-endian hardware] + if (src_len > RegisterValue::kMaxRegisterByteSize) { + error.SetErrorString("register too small to receive memory data"); + return error; + } -Error -NativeRegisterContext::ReadRegisterValueFromMemory ( - const RegisterInfo *reg_info, - lldb::addr_t src_addr, - size_t src_len, - RegisterValue ®_value) -{ - Error error; - if (reg_info == nullptr) - { - error.SetErrorString ("invalid register info argument."); - return error; - } + const size_t dst_len = reg_info->byte_size; + if (src_len > dst_len) { + error.SetErrorStringWithFormat( + "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 + " bytes)", + static_cast(src_len), reg_info->name, + static_cast(dst_len)); + return error; + } - // Moving from addr into a register - // - // Case 1: src_len == dst_len - // - // |AABBCCDD| Address contents - // |AABBCCDD| Register contents - // - // Case 2: src_len > dst_len - // - // Error! (The register should always be big enough to hold the data) - // - // Case 3: src_len < dst_len - // - // |AABB| Address contents - // |AABB0000| Register contents [on little-endian hardware] - // |0000AABB| Register contents [on big-endian hardware] - if (src_len > RegisterValue::kMaxRegisterByteSize) - { - error.SetErrorString ("register too small to receive memory data"); - return error; - } + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (!process_sp) { + error.SetErrorString("invalid process"); + return error; + } - const size_t dst_len = reg_info->byte_size; + uint8_t src[RegisterValue::kMaxRegisterByteSize]; - if (src_len > dst_len) - { - error.SetErrorStringWithFormat("%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 " bytes)", - static_cast(src_len), reg_info->name, static_cast(dst_len)); - return error; - } + // Read the memory + size_t bytes_read; + error = process_sp->ReadMemory(src_addr, src, src_len, bytes_read); + if (error.Fail()) + return error; - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString("invalid process"); - return error; - } + // Make sure the memory read succeeded... + if (bytes_read != src_len) { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", + static_cast(bytes_read), + static_cast(src_len)); + return error; + } + + // We now have a memory buffer that contains the part or all of the register + // value. Set the register value using this memory data. + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder(byte_order)) { + error.SetErrorString("NativeProcessProtocol::GetByteOrder () failed"); + return error; + } - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Read the memory - size_t bytes_read; - error = process_sp->ReadMemory (src_addr, src, src_len, bytes_read); - if (error.Fail ()) - return error; - - // Make sure the memory read succeeded... - if (bytes_read != src_len) - { - // This might happen if we read _some_ bytes but not all - error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", - static_cast(bytes_read), static_cast(src_len)); - return error; - } + reg_value.SetFromMemoryData(reg_info, src, src_len, byte_order, error); - // We now have a memory buffer that contains the part or all of the register - // value. Set the register value using this memory data. - // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are assuming - // they are the same. - lldb::ByteOrder byte_order; - if (!process_sp->GetByteOrder (byte_order)) - { - error.SetErrorString ( "NativeProcessProtocol::GetByteOrder () failed"); - return error; - } + return error; +} - reg_value.SetFromMemoryData ( - reg_info, - src, - src_len, - byte_order, - error); +Error NativeRegisterContext::WriteRegisterValueToMemory( + const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, + const RegisterValue ®_value) { - return error; -} + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + Error error; -Error -NativeRegisterContext::WriteRegisterValueToMemory ( - const RegisterInfo *reg_info, - lldb::addr_t dst_addr, - size_t dst_len, - const RegisterValue ®_value) -{ - - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - Error error; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (process_sp) - { - - // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are assuming - // they are the same. - lldb::ByteOrder byte_order; - if (!process_sp->GetByteOrder (byte_order)) - return Error ("NativeProcessProtocol::GetByteOrder () failed"); - - const size_t bytes_copied = reg_value.GetAsMemoryData ( - reg_info, - dst, - dst_len, - byte_order, - error); - - if (error.Success()) - { - if (bytes_copied == 0) - { - error.SetErrorString("byte copy failed."); - } - else - { - size_t bytes_written; - error = process_sp->WriteMemory(dst_addr, dst, bytes_copied, bytes_written); - if (error.Fail ()) - return error; - - if (bytes_written != bytes_copied) - { - // This might happen if we read _some_ bytes but not all - error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 " bytes", - static_cast(bytes_written), static_cast(bytes_copied)); - } - } + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (process_sp) { + + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are + // assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder(byte_order)) + return Error("NativeProcessProtocol::GetByteOrder () failed"); + + const size_t bytes_copied = + reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error); + + if (error.Success()) { + if (bytes_copied == 0) { + error.SetErrorString("byte copy failed."); + } else { + size_t bytes_written; + error = + process_sp->WriteMemory(dst_addr, dst, bytes_copied, bytes_written); + if (error.Fail()) + return error; + + if (bytes_written != bytes_copied) { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 + " bytes", + static_cast(bytes_written), + static_cast(bytes_copied)); } + } } - else - error.SetErrorString("invalid process"); + } else + error.SetErrorString("invalid process"); - return error; + return error; } uint32_t -NativeRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const -{ - const uint32_t num_regs = GetRegisterCount(); +NativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) const { + const uint32_t num_regs = GetRegisterCount(); - assert (kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); - if (reg_info->kinds[kind] == num) - return reg_idx; - } + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } - - diff --git a/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp b/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp index 0d7c6eced75..3590c681010 100644 --- a/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp +++ b/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp @@ -7,44 +7,37 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-types.h" -#include "lldb/lldb-private-forward.h" #include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-types.h" using namespace lldb_private; -NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info_interface) : - NativeRegisterContext (thread, concrete_frame_idx), - m_register_info_interface_up (register_info_interface) -{ - assert (register_info_interface && "null register_info_interface"); +NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( + NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface) + : NativeRegisterContext(thread, concrete_frame_idx), + m_register_info_interface_up(register_info_interface) { + assert(register_info_interface && "null register_info_interface"); } -uint32_t -NativeRegisterContextRegisterInfo::GetRegisterCount () const -{ - return m_register_info_interface_up->GetRegisterCount (); +uint32_t NativeRegisterContextRegisterInfo::GetRegisterCount() const { + return m_register_info_interface_up->GetRegisterCount(); } -uint32_t -NativeRegisterContextRegisterInfo::GetUserRegisterCount () const -{ - return m_register_info_interface_up->GetUserRegisterCount (); +uint32_t NativeRegisterContextRegisterInfo::GetUserRegisterCount() const { + return m_register_info_interface_up->GetUserRegisterCount(); } -const RegisterInfo * -NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const -{ - if (reg_index <= GetRegisterCount ()) - return m_register_info_interface_up->GetRegisterInfo () + reg_index; - else - return nullptr; +const RegisterInfo *NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex( + uint32_t reg_index) const { + if (reg_index <= GetRegisterCount()) + return m_register_info_interface_up->GetRegisterInfo() + reg_index; + else + return nullptr; } -const RegisterInfoInterface& -NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const -{ - return *m_register_info_interface_up; +const RegisterInfoInterface & +NativeRegisterContextRegisterInfo::GetRegisterInfoInterface() const { + return *m_register_info_interface_up; } diff --git a/lldb/source/Host/common/NativeThreadProtocol.cpp b/lldb/source/Host/common/NativeThreadProtocol.cpp index ea406e9ef2c..2e76cff0d67 100644 --- a/lldb/source/Host/common/NativeThreadProtocol.cpp +++ b/lldb/source/Host/common/NativeThreadProtocol.cpp @@ -16,60 +16,53 @@ using namespace lldb; using namespace lldb_private; -NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) : - m_process_wp (process->shared_from_this ()), - m_tid (tid) -{ -} +NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol *process, + lldb::tid_t tid) + : m_process_wp(process->shared_from_this()), m_tid(tid) {} -Error -NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); +Error NativeThreadProtocol::ReadRegister(uint32_t reg, + RegisterValue ®_value) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); + const RegisterInfo *const reg_info = + register_context_sp->GetRegisterInfoAtIndex(reg); + if (!reg_info) + return Error("no register info for reg num %" PRIu32, reg); - return register_context_sp->ReadRegister (reg_info, reg_value);; + return register_context_sp->ReadRegister(reg_info, reg_value); + ; } -Error -NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); +Error NativeThreadProtocol::WriteRegister(uint32_t reg, + const RegisterValue ®_value) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); + const RegisterInfo *const reg_info = + register_context_sp->GetRegisterInfoAtIndex(reg); + if (!reg_info) + return Error("no register info for reg num %" PRIu32, reg); - return register_context_sp->WriteRegister (reg_info, reg_value); + return register_context_sp->WriteRegister(reg_info, reg_value); } -Error -NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->WriteAllRegisterValues (data_sp); +Error NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); + return register_context_sp->WriteAllRegisterValues(data_sp); } -Error -NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->ReadAllRegisterValues (data_sp); +Error NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); + return register_context_sp->ReadAllRegisterValues(data_sp); } -NativeProcessProtocolSP -NativeThreadProtocol::GetProcess () -{ - return m_process_wp.lock (); +NativeProcessProtocolSP NativeThreadProtocol::GetProcess() { + return m_process_wp.lock(); } diff --git a/lldb/source/Host/common/NativeWatchpointList.cpp b/lldb/source/Host/common/NativeWatchpointList.cpp index 209d213b8e5..5948adf3c8d 100644 --- a/lldb/source/Host/common/NativeWatchpointList.cpp +++ b/lldb/source/Host/common/NativeWatchpointList.cpp @@ -14,22 +14,18 @@ using namespace lldb; using namespace lldb_private; -Error -NativeWatchpointList::Add (addr_t addr, size_t size, uint32_t watch_flags, bool hardware) -{ - m_watchpoints[addr] = {addr, size, watch_flags, hardware}; - return Error (); +Error NativeWatchpointList::Add(addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) { + m_watchpoints[addr] = {addr, size, watch_flags, hardware}; + return Error(); } -Error -NativeWatchpointList::Remove (addr_t addr) -{ - m_watchpoints.erase(addr); - return Error (); +Error NativeWatchpointList::Remove(addr_t addr) { + m_watchpoints.erase(addr); + return Error(); } -const NativeWatchpointList::WatchpointMap& -NativeWatchpointList::GetWatchpointMap () const -{ - return m_watchpoints; +const NativeWatchpointList::WatchpointMap & +NativeWatchpointList::GetWatchpointMap() const { + return m_watchpoints; } diff --git a/lldb/source/Host/common/OptionParser.cpp b/lldb/source/Host/common/OptionParser.cpp index 16a29a1583d..053179c19ee 100644 --- a/lldb/source/Host/common/OptionParser.cpp +++ b/lldb/source/Host/common/OptionParser.cpp @@ -15,102 +15,67 @@ using namespace lldb_private; -void -OptionParser::Prepare(std::unique_lock &lock) -{ - static std::mutex g_mutex; - lock = std::unique_lock(g_mutex); +void OptionParser::Prepare(std::unique_lock &lock) { + static std::mutex g_mutex; + lock = std::unique_lock(g_mutex); #ifdef __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif } -void -OptionParser::EnableError(bool error) -{ - opterr = error ? 1 : 0; -} +void OptionParser::EnableError(bool error) { opterr = error ? 1 : 0; } -int -OptionParser::Parse (int argc, - char * const argv [], - const char *optstring, - const Option *longopts, - int *longindex) -{ - std::vector