diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Host | |
parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) | |
download | src-94994d372d014ce4c8758b9605d63fae651bd8aa.tar.gz src-94994d372d014ce4c8758b9605d63fae651bd8aa.zip |
Vendor import of lldb trunk r351319 (just before the release_80 branchvendor/lldb/lldb-trunk-r351319
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=343181
svn path=/vendor/lldb/lldb-trunk-r351319/; revision=343182; tag=vendor/lldb/lldb-trunk-r351319
Diffstat (limited to 'source/Host')
50 files changed, 1175 insertions, 1184 deletions
diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index 5a92447edf30..333f109a9a26 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -11,7 +11,9 @@ endmacro() # Objective-C++ files in lldb (which slows down the build process). macro(remove_module_flags) string(REGEX REPLACE "-fmodules-cache-path=[^ ]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "-fmodules-local-submodule-visibility" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REGEX REPLACE "-fmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "-gmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REGEX REPLACE "-fcxx-modules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endmacro() @@ -28,8 +30,6 @@ add_host_subdirectory(common common/LockFileBase.cpp common/MainLoop.cpp common/MonitoringProcessLauncher.cpp - common/NativeBreakpoint.cpp - common/NativeBreakpointList.cpp common/NativeWatchpointList.cpp common/NativeProcessProtocol.cpp common/NativeRegisterContext.cpp @@ -40,7 +40,6 @@ add_host_subdirectory(common common/PseudoTerminal.cpp common/Socket.cpp common/SocketAddress.cpp - common/SoftwareBreakpoint.cpp common/StringConvert.cpp common/Symbols.cpp common/TaskPool.cpp @@ -92,7 +91,7 @@ else() include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) add_subdirectory(macosx/objcxx) set(LLDBObjCLibs lldbHostMacOSXObjCXX) - add_host_subdirectory(maqcosx + add_host_subdirectory(macosx macosx/Symbols.cpp macosx/cfcpp/CFCBundle.cpp macosx/cfcpp/CFCData.cpp @@ -156,7 +155,7 @@ if (HAVE_LIBDL) list(APPEND EXTRA_LIBS ${CMAKE_DL_LIBS}) endif() if (NOT LLDB_DISABLE_LIBEDIT) - list(APPEND EXTRA_LIBS edit) + list(APPEND EXTRA_LIBS ${libedit_LIBRARIES}) endif() add_lldb_library(lldbHost @@ -174,3 +173,7 @@ add_lldb_library(lldbHost Object Support ) + +if (NOT LLDB_DISABLE_LIBEDIT) + target_include_directories(lldbHost PUBLIC ${libedit_INCLUDE_DIRS}) +endif() diff --git a/source/Host/android/HostInfoAndroid.cpp b/source/Host/android/HostInfoAndroid.cpp index a96033283212..3dea01f8240d 100644 --- a/source/Host/android/HostInfoAndroid.cpp +++ b/source/Host/android/HostInfoAndroid.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/android/HostInfoAndroid.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/linux/HostInfoLinux.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -28,7 +29,7 @@ void HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, } FileSpec HostInfoAndroid::GetDefaultShell() { - return FileSpec("/system/bin/sh", false); + return FileSpec("/system/bin/sh"); } FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path, @@ -39,8 +40,11 @@ FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path, 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); + if (module_path.empty() || module_path[0] == '/') { + FileSpec file_spec(module_path.c_str()); + FileSystem::Instance().Resolve(file_spec); + return file_spec; + } SmallVector<StringRef, 4> ld_paths; @@ -65,10 +69,11 @@ FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path, ld_paths.push_back(StringRef(*it)); for (const StringRef &path : ld_paths) { - FileSpec file_candidate(path.str().c_str(), true); + FileSpec file_candidate(path.str().c_str()); + FileSystem::Instance().Resolve(file_candidate); file_candidate.AppendPathComponent(module_path.c_str()); - if (file_candidate.Exists()) + if (FileSystem::Instance().Exists(file_candidate)) return file_candidate; } @@ -83,8 +88,8 @@ bool HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) { // 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 (!success || !FileSystem::Instance().Exists(file_spec)) + file_spec = FileSpec("/data/local/tmp"); - return file_spec.Exists(); + return FileSystem::Instance().Exists(file_spec); } diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index 329c0c1f3b70..f7ba4b5822ff 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -13,6 +13,7 @@ #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Editline.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBAssert.h" @@ -172,7 +173,8 @@ private: const char *GetHistoryFilePath() { if (m_path.empty() && m_history && !m_prefix.empty()) { - FileSpec parent_path{"~/.lldb", true}; + FileSpec parent_path("~/.lldb"); + FileSystem::Instance().Resolve(parent_path); char history_path[PATH_MAX]; if (!llvm::sys::fs::create_directory(parent_path.GetPath())) { snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history", @@ -181,7 +183,9 @@ private: snprintf(history_path, sizeof(history_path), "~/%s-widehistory", m_prefix.c_str()); } - m_path = FileSpec(history_path, true).GetPath(); + auto file_spec = FileSpec(history_path); + FileSystem::Instance().Resolve(file_spec); + m_path = file_spec.GetPath(); } if (m_path.empty()) return NULL; @@ -426,7 +430,7 @@ unsigned char Editline::RecallHistory(bool earlier) { // Treat moving from the "live" entry differently if (!m_in_history) { - if (earlier == false) + if (!earlier) return CC_ERROR; // Can't go newer than the "live" entry if (history_w(pHistory, &history_event, H_FIRST) == -1) return CC_ERROR; @@ -439,7 +443,7 @@ unsigned char Editline::RecallHistory(bool earlier) { m_live_history_lines = m_input_lines; m_in_history = true; } else { - if (history_w(pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) { + if (history_w(pHistory, &history_event, earlier ? H_PREV : H_NEXT) == -1) { // Can't move earlier than the earliest entry if (earlier) return CC_ERROR; @@ -526,7 +530,7 @@ int Editline::GetCharacter(EditLineGetCharType *c) { break; case lldb::eConnectionStatusInterrupted: - lldbassert(0 && "Interrupts should have been handled above."); + llvm_unreachable("Interrupts should have been handled above."); case lldb::eConnectionStatusError: // Check GetError() for details case lldb::eConnectionStatusTimedOut: // Request timed out @@ -853,19 +857,45 @@ unsigned char Editline::BufferEndCommand(int ch) { return CC_NEWLINE; } +//------------------------------------------------------------------------------ +/// Prints completions and their descriptions to the given file. Only the +/// completions in the interval [start, end) are printed. +//------------------------------------------------------------------------------ +static void PrintCompletion(FILE *output_file, size_t start, size_t end, + StringList &completions, StringList &descriptions) { + // This is an 'int' because of printf. + int max_len = 0; + + for (size_t i = start; i < end; i++) { + const char *completion_str = completions.GetStringAtIndex(i); + max_len = std::max((int)strlen(completion_str), max_len); + } + + for (size_t i = start; i < end; i++) { + const char *completion_str = completions.GetStringAtIndex(i); + const char *description_str = descriptions.GetStringAtIndex(i); + + fprintf(output_file, "\n\t%-*s", max_len, completion_str); + + // Print the description if we got one. + if (strlen(description_str)) + fprintf(output_file, " -- %s", description_str); + } +} + unsigned char Editline::TabCommand(int ch) { if (m_completion_callback == nullptr) return CC_ERROR; const LineInfo *line_info = el_line(m_editline); - StringList completions; + StringList completions, descriptions; 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); + completions, descriptions, m_completion_callback_baton); if (num_completions == 0) return CC_ERROR; @@ -893,10 +923,8 @@ unsigned char Editline::TabCommand(int ch) { 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); - } + PrintCompletion(m_output_file, 1, num_elements, completions, + descriptions); fprintf(m_output_file, "\n"); } else { int cur_pos = 1; @@ -906,10 +934,10 @@ unsigned char Editline::TabCommand(int ch) { 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); - } + + PrintCompletion(m_output_file, cur_pos, endpoint, completions, + descriptions); + cur_pos = endpoint; if (cur_pos >= num_elements) { fprintf(m_output_file, "\n"); diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 3c3d55df2207..810c15588402 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -27,9 +27,10 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() +#include "llvm/Support/Process.h" #include "lldb/Host/Config.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" @@ -71,26 +72,6 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) { 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) - -{ - if (filespec) { - Open(filespec.GetPath().c_str(), options, permissions); - } -} - File::~File() { Close(); } int File::GetDescriptor() const { @@ -159,108 +140,6 @@ void File::SetStream(FILE *fh, bool transfer_ownership) { m_own_stream = transfer_ownership; } -static int DoOpen(const char *path, int flags, int mode) { -#ifdef _MSC_VER - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - return -1; - int result; - ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode); - return result; -#else - return ::open(path, flags, mode); -#endif -} - -Status File::Open(const char *path, uint32_t options, uint32_t permissions) { - Status 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; -#endif - } - -#ifndef _WIN32 - if (options & eOpenOptionNonBlocking) - oflag |= O_NONBLOCK; - if (options & eOpenOptionCloseOnExec) - oflag |= O_CLOEXEC; -#else - 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; - } - - m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode); - if (!DescriptorIsValid()) - error.SetErrorToErrno(); - else { - m_should_close_fd = true; - m_options = options; - } - - return error; -} - -uint32_t File::GetPermissions(const FileSpec &file_spec, Status &error) { - if (file_spec) { - error.Clear(); - auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath()); - if (Perms) - return *Perms; - error = Status(Perms.getError()); - return 0; - } else - error.SetErrorString("empty file spec"); - return 0; -} - uint32_t File::GetPermissions(Status &error) const { int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { @@ -315,7 +194,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const { if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) error.SetErrorToErrno(); else - file_spec.SetFile(path, false, FileSpec::Style::native); + file_spec.SetFile(path, FileSpec::Style::native); } else { error.SetErrorString("invalid file handle"); } @@ -330,7 +209,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const { error.SetErrorToErrno(); else { path[len] = '\0'; - file_spec.SetFile(path, false, FileSpec::Style::native); + file_spec.SetFile(path, FileSpec::Style::native); } } #else @@ -806,6 +685,9 @@ void File::CalculateInteractiveAndTerminal() { if (_isatty(fd)) { m_is_interactive = eLazyBoolYes; m_is_real_terminal = eLazyBoolYes; +#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) + m_supports_colors = eLazyBoolYes; +#endif } #else if (isatty(fd)) { diff --git a/source/Host/common/FileCache.cpp b/source/Host/common/FileCache.cpp index b4629255c852..17833ef2cbb3 100644 --- a/source/Host/common/FileCache.cpp +++ b/source/Host/common/FileCache.cpp @@ -10,6 +10,7 @@ #include "lldb/Host/FileCache.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileSystem.h" using namespace lldb; using namespace lldb_private; @@ -25,14 +26,13 @@ FileCache &FileCache::GetInstance() { lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, uint32_t mode, Status &error) { - std::string path(file_spec.GetPath()); - if (path.empty()) { + if (!file_spec) { 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) + error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode); + if (!file_sp->IsValid()) return UINT64_MAX; lldb::user_id_t fd = file_sp->GetDescriptor(); m_cache[fd] = file_sp; diff --git a/source/Host/common/FileSystem.cpp b/source/Host/common/FileSystem.cpp index 4472aece1daa..7191c9db9b2e 100644 --- a/source/Host/common/FileSystem.cpp +++ b/source/Host/common/FileSystem.cpp @@ -9,7 +9,29 @@ #include "lldb/Host/FileSystem.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/TildeExpressionResolver.h" + +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Threading.h" + +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> + +#ifdef _WIN32 +#include "lldb/Host/windows/windows.h" +#else +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <termios.h> +#include <unistd.h> +#endif #include <algorithm> #include <fstream> @@ -17,12 +39,366 @@ using namespace lldb; using namespace lldb_private; +using namespace llvm; + +FileSystem &FileSystem::Instance() { return *InstanceImpl(); } + +void FileSystem::Initialize() { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(); +} + +void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(fs); +} + +void FileSystem::Terminate() { + lldbassert(InstanceImpl() && "Already terminated."); + InstanceImpl().reset(); +} + +Optional<FileSystem> &FileSystem::InstanceImpl() { + static Optional<FileSystem> g_fs; + return g_fs; +} + +vfs::directory_iterator FileSystem::DirBegin(const FileSpec &file_spec, + std::error_code &ec) { + return DirBegin(file_spec.GetPath(), ec); +} + +vfs::directory_iterator FileSystem::DirBegin(const Twine &dir, + std::error_code &ec) { + return m_fs->dir_begin(dir, ec); +} + +llvm::ErrorOr<vfs::Status> +FileSystem::GetStatus(const FileSpec &file_spec) const { + return GetStatus(file_spec.GetPath()); +} + +llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(const Twine &path) const { + return m_fs->status(path); +} + +sys::TimePoint<> +FileSystem::GetModificationTime(const FileSpec &file_spec) const { + return GetModificationTime(file_spec.GetPath()); +} + +sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const { + ErrorOr<vfs::Status> status = m_fs->status(path); + if (!status) + return sys::TimePoint<>(); + return status->getLastModificationTime(); +} + +uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const { + return GetByteSize(file_spec.GetPath()); +} + +uint64_t FileSystem::GetByteSize(const Twine &path) const { + ErrorOr<vfs::Status> status = m_fs->status(path); + if (!status) + return 0; + return status->getSize(); +} + +uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const { + return GetPermissions(file_spec.GetPath()); +} + +uint32_t FileSystem::GetPermissions(const FileSpec &file_spec, + std::error_code &ec) const { + return GetPermissions(file_spec.GetPath(), ec); +} + +uint32_t FileSystem::GetPermissions(const Twine &path) const { + std::error_code ec; + return GetPermissions(path, ec); +} + +uint32_t FileSystem::GetPermissions(const Twine &path, + std::error_code &ec) const { + ErrorOr<vfs::Status> status = m_fs->status(path); + if (!status) { + ec = status.getError(); + return sys::fs::perms::perms_not_known; + } + return status->getPermissions(); +} + +bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); } + +bool FileSystem::Exists(const FileSpec &file_spec) const { + return Exists(file_spec.GetPath()); +} + +bool FileSystem::Readable(const Twine &path) const { + return GetPermissions(path) & sys::fs::perms::all_read; +} + +bool FileSystem::Readable(const FileSpec &file_spec) const { + return Readable(file_spec.GetPath()); +} + +bool FileSystem::IsDirectory(const Twine &path) const { + ErrorOr<vfs::Status> status = m_fs->status(path); + if (!status) + return false; + return status->isDirectory(); +} + +bool FileSystem::IsDirectory(const FileSpec &file_spec) const { + return IsDirectory(file_spec.GetPath()); +} + +bool FileSystem::IsLocal(const Twine &path) const { + bool b = false; + m_fs->isLocal(path, b); + return b; +} + +bool FileSystem::IsLocal(const FileSpec &file_spec) const { + return IsLocal(file_spec.GetPath()); +} + +void FileSystem::EnumerateDirectory(Twine path, bool find_directories, + bool find_files, bool find_other, + EnumerateDirectoryCallbackType callback, + void *callback_baton) { + std::error_code EC; + vfs::recursive_directory_iterator Iter(*m_fs, path, EC); + vfs::recursive_directory_iterator End; + for (; Iter != End && !EC; Iter.increment(EC)) { + const auto &Item = *Iter; + ErrorOr<vfs::Status> Status = m_fs->status(Item.path()); + if (!Status) + break; + if (!find_files && Status->isRegularFile()) + continue; + if (!find_directories && Status->isDirectory()) + continue; + if (!find_other && Status->isOther()) + continue; + + auto Result = callback(callback_baton, Status->getType(), Item.path()); + if (Result == eEnumerateDirectoryResultQuit) + return; + if (Result == eEnumerateDirectoryResultNext) { + // Default behavior is to recurse. Opt out if the callback doesn't want + // this behavior. + Iter.no_push(); + } + } +} + +std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const { + return m_fs->makeAbsolute(path); +} + +std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const { + SmallString<128> path; + file_spec.GetPath(path, false); + + auto EC = MakeAbsolute(path); + if (EC) + return EC; + + FileSpec new_file_spec(path, file_spec.GetPathStyle()); + file_spec = new_file_spec; + return {}; +} + +std::error_code FileSystem::GetRealPath(const Twine &path, + SmallVectorImpl<char> &output) const { + return m_fs->getRealPath(path, output); +} + +void FileSystem::Resolve(SmallVectorImpl<char> &path) { + if (path.empty()) + return; + + // Resolve tilde. + SmallString<128> original_path(path.begin(), path.end()); + StandardTildeExpressionResolver Resolver; + Resolver.ResolveFullPath(original_path, path); + + // Try making the path absolute if it exists. + SmallString<128> absolute_path(path.begin(), path.end()); + MakeAbsolute(path); + if (!Exists(path)) { + path.clear(); + path.append(original_path.begin(), original_path.end()); + } +} + +void FileSystem::Resolve(FileSpec &file_spec) { + // Extract path from the FileSpec. + SmallString<128> path; + file_spec.GetPath(path); + + // Resolve the path. + Resolve(path); + + // Update the FileSpec with the resolved path. + file_spec.SetPath(path); + file_spec.SetIsResolved(true); +} + +std::shared_ptr<DataBufferLLVM> +FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size, + uint64_t offset) { + const bool is_volatile = !IsLocal(path); + + std::unique_ptr<llvm::WritableMemoryBuffer> buffer; + if (size == 0) { + auto buffer_or_error = + llvm::WritableMemoryBuffer::getFile(path, -1, is_volatile); + if (!buffer_or_error) + return nullptr; + buffer = std::move(*buffer_or_error); + } else { + auto buffer_or_error = llvm::WritableMemoryBuffer::getFileSlice( + path, size, offset, is_volatile); + if (!buffer_or_error) + return nullptr; + buffer = std::move(*buffer_or_error); + } + return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer))); +} + +std::shared_ptr<DataBufferLLVM> +FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size, + uint64_t offset) { + return CreateDataBuffer(file_spec.GetPath(), size, offset); +} + +bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) { + // If the directory is set there's nothing to do. + const ConstString &directory = file_spec.GetDirectory(); + if (directory) + return false; + + // We cannot look for a file if there's no file name. + const ConstString &filename = file_spec.GetFilename(); + if (!filename) + return false; + + // Search for the file on the host. + const std::string filename_str(filename.GetCString()); + llvm::ErrorOr<std::string> error_or_path = + llvm::sys::findProgramByName(filename_str); + if (!error_or_path) + return false; + + // findProgramByName returns "." if it can't find the file. + llvm::StringRef path = *error_or_path; + llvm::StringRef parent = llvm::sys::path::parent_path(path); + if (parent.empty() || parent == ".") + return false; + + // Make sure that the result exists. + FileSpec result(*error_or_path); + if (!Exists(result)) + return false; + + file_spec = result; + return true; +} + +static int OpenWithFS(const FileSystem &fs, const char *path, int flags, + int mode) { + return const_cast<FileSystem &>(fs).Open(path, flags, mode); +} + +static int GetOpenFlags(uint32_t options) { + const bool read = options & File::eOpenOptionRead; + const bool write = options & File::eOpenOptionWrite; + + int open_flags = 0; + if (write) { + if (read) + open_flags |= O_RDWR; + else + open_flags |= O_WRONLY; + + if (options & File::eOpenOptionAppend) + open_flags |= O_APPEND; + + if (options & File::eOpenOptionTruncate) + open_flags |= O_TRUNC; + + if (options & File::eOpenOptionCanCreate) + open_flags |= O_CREAT; + + if (options & File::eOpenOptionCanCreateNewOnly) + open_flags |= O_CREAT | O_EXCL; + } else if (read) { + open_flags |= O_RDONLY; + +#ifndef _WIN32 + if (options & File::eOpenOptionDontFollowSymlinks) + open_flags |= O_NOFOLLOW; +#endif + } + +#ifndef _WIN32 + if (options & File::eOpenOptionNonBlocking) + open_flags |= O_NONBLOCK; + if (options & File::eOpenOptionCloseOnExec) + open_flags |= O_CLOEXEC; +#else + open_flags |= O_BINARY; +#endif + + return open_flags; +} + +static mode_t GetOpenMode(uint32_t permissions) { + mode_t mode = 0; + 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; + return mode; +} + +Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options, + uint32_t permissions) { + if (File.IsValid()) + File.Close(); + + const int open_flags = GetOpenFlags(options); + const mode_t open_mode = + (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0; + const std::string path = file_spec.GetPath(); + + int descriptor = llvm::sys::RetryAfterSignal( + -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode); -llvm::sys::TimePoint<> -FileSystem::GetModificationTime(const FileSpec &file_spec) { - llvm::sys::fs::file_status status; - std::error_code ec = llvm::sys::fs::status(file_spec.GetPath(), status); - if (ec) - return llvm::sys::TimePoint<>(); - return status.getLastModificationTime(); + Status error; + if (!File::DescriptorIsValid(descriptor)) { + File.SetDescriptor(descriptor, false); + error.SetErrorToErrno(); + } else { + File.SetDescriptor(descriptor, true); + File.SetOptions(options); + } + return error; } diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index d2848254779e..62b936aadef1 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -45,14 +45,13 @@ #include <lwp.h> #endif -// C++ Includes #include <csignal> +#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/Host/posix/ConnectionFileDescriptorPosix.h" @@ -62,6 +61,7 @@ #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Predicate.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" @@ -419,8 +419,10 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { #if !defined(__ANDROID__) Dl_info info; if (::dladdr(host_addr, &info)) { - if (info.dli_fname) - module_filespec.SetFile(info.dli_fname, true, FileSpec::Style::native); + if (info.dli_fname) { + module_filespec.SetFile(info.dli_fname, FileSpec::Style::native); + FileSystem::Instance().Resolve(module_filespec); + } } #endif return module_filespec; @@ -494,7 +496,7 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, if (working_dir) launch_info.SetWorkingDirectory(working_dir); - llvm::SmallString<PATH_MAX> output_file_path; + llvm::SmallString<64> output_file_path; if (command_output_ptr) { // Create a temporary file to get the stdout/stderr and redirect the output @@ -510,7 +512,7 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, } } - FileSpec output_file_spec{output_file_path.c_str(), false}; + FileSpec output_file_spec(output_file_path.c_str()); launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); if (output_file_spec) { @@ -554,14 +556,15 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, if (command_output_ptr) { command_output_ptr->clear(); - uint64_t file_size = output_file_spec.GetByteSize(); + uint64_t file_size = + FileSystem::Instance().GetByteSize(output_file_spec); 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 { auto Buffer = - DataBufferLLVM::CreateFromPath(output_file_spec.GetPath()); + FileSystem::Instance().CreateDataBuffer(output_file_spec); if (error.Success()) command_output_ptr->assign(Buffer->GetChars(), Buffer->GetByteSize()); diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index 4de6953a91e3..34c362efc9e0 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -42,7 +42,7 @@ namespace { struct HostInfoBaseFields { ~HostInfoBaseFields() { - if (m_lldb_process_tmp_dir.Exists()) { + if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) { // 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. @@ -226,7 +226,7 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { // 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); + FileSystem::Instance().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(); @@ -256,7 +256,8 @@ bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { llvm::SmallVector<char, 16> tmpdir; llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); - file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); + file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size())); + FileSystem::Instance().Resolve(file_spec); return true; } diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp index 402d3caacfcb..25c8066bb1a3 100644 --- a/source/Host/common/HostNativeThreadBase.cpp +++ b/source/Host/common/HostNativeThreadBase.cpp @@ -41,6 +41,10 @@ void HostNativeThreadBase::Reset() { m_result = 0; } +bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { + return m_thread == thread; +} + lldb::thread_t HostNativeThreadBase::Release() { lldb::thread_t result = m_thread; m_thread = LLDB_INVALID_HOST_THREAD; diff --git a/source/Host/common/HostThread.cpp b/source/Host/common/HostThread.cpp index 02882c523908..2bf6f0a933d8 100644 --- a/source/Host/common/HostThread.cpp +++ b/source/Host/common/HostThread.cpp @@ -43,5 +43,5 @@ lldb::thread_result_t HostThread::GetResult() const { } bool HostThread::EqualsThread(lldb::thread_t thread) const { - return m_native_thread->GetSystemHandle() == thread; + return m_native_thread->EqualsThread(thread); } diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 65158c942934..39c353e6717e 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -309,7 +309,7 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { g_signal_flags[signo] = 0; // Even if using kqueue, the signal handler will still be invoked, so it's - // important to replace it with our "bening" handler. + // important to replace it with our "benign" handler. int ret = sigaction(signo, &new_action, &info.old_action); assert(ret == 0 && "sigaction failed"); @@ -321,7 +321,7 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { #endif // If we're using kqueue, the signal needs to be unblocked in order to - // recieve it. If using pselect/ppoll, we need to block it, and later unblock + // receive it. If using pselect/ppoll, we need to block it, and later unblock // it as a part of the system call. ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK, &new_action.sa_mask, &old_set); diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp index 76c11454f573..f6f772cb3679 100644 --- a/source/Host/common/MonitoringProcessLauncher.cpp +++ b/source/Host/common/MonitoringProcessLauncher.cpp @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/HostProcess.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" #include "llvm/Support/FileSystem.h" @@ -29,20 +29,16 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, error.Clear(); + FileSystem &fs = FileSystem::Instance(); FileSpec exe_spec(resolved_info.GetExecutableFile()); - llvm::sys::fs::file_status stats; - status(exe_spec.GetPath(), stats); - if (!exists(stats)) { - exe_spec.ResolvePath(); - status(exe_spec.GetPath(), stats); - } - if (!exists(stats)) { - exe_spec.ResolveExecutableLocation(); - status(exe_spec.GetPath(), stats); - } + if (!fs.Exists(exe_spec)) + FileSystem::Instance().Resolve(exe_spec); + + if (!fs.Exists(exe_spec)) + FileSystem::Instance().ResolveExecutableLocation(exe_spec); - if (!exists(stats)) { + if (!fs.Exists(exe_spec)) { error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'", exe_spec); return HostProcess(); diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp deleted file mode 100644 index 5eee3de482c1..000000000000 --- a/source/Host/common/NativeBreakpoint.cpp +++ /dev/null @@ -1,109 +0,0 @@ -//===-- NativeBreakpoint.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/common/NativeBreakpoint.h" - -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.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() {} - -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); -} - -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); - - return m_ref_count; -} - -Status 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 Status(); - } - - // Log and enable. - if (log) - log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", - __FUNCTION__, m_addr); - - Status 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; -} - -Status NativeBreakpoint::Disable() { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - - 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 Status(); - } - - // Log and disable. - if (log) - log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", - __FUNCTION__, m_addr); - - Status 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/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp deleted file mode 100644 index cfcbe0831064..000000000000 --- a/source/Host/common/NativeBreakpointList.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/common/NativeBreakpointList.h" - -#include "lldb/Utility/Log.h" - -#include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" - -using namespace lldb; -using namespace lldb_private; - -NativeBreakpointList::NativeBreakpointList() : m_mutex() {} - -Status 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 = %zu, hardware = %s", - __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - std::lock_guard<std::recursive_mutex> 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); - - iter->second->AddRef(); - return Status(); - } - - // Create a new breakpoint using the given create func. - if (log) - log->Printf( - "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 - ", size_hint = %zu, hardware = %s", - __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - NativeBreakpointSP breakpoint_sp; - Status 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 = %zu, hardware = %s -- FAILED: %s", - __FUNCTION__, addr, size_hint, hardware ? "true" : "false", - error.AsCString()); - return error; - } - - // Remember the breakpoint. - assert(breakpoint_sp && "NativeBreakpoint create function succeeded but " - "returned NULL breakpoint"); - m_breakpoints.insert(BreakpointMap::value_type(addr, breakpoint_sp)); - - return error; -} - -Status NativeBreakpointList::DecRef(lldb::addr_t addr) { - Status error; - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, - addr); - - std::lock_guard<std::recursive_mutex> 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"); - - 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); - - // 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); - } - - // 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; -} - -Status 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<std::recursive_mutex> 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 Status("breakpoint not found"); - } - - // Enable it. - return iter->second->Enable(); -} - -Status 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<std::recursive_mutex> 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 Status("breakpoint not found"); - } - - // Disable it. - return iter->second->Disable(); -} - -Status 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<std::recursive_mutex> 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 Status("breakpoint not found"); - } - - // Disable it. - breakpoint_sp = iter->second; - return Status(); -} - -Status 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<SoftwareBreakpoint>(bp_sp); - auto opcode_addr = static_cast<char *>(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 Status(); -} diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 3e8648f81473..e3c81f6c147b 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Core/State.h" #include "lldb/Host/Host.h" +#include "lldb/Host/common/NativeBreakpointList.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" #include "lldb/lldb-enumerations.h" using namespace lldb; @@ -359,17 +359,271 @@ void NativeProcessProtocol::NotifyDidExec() { Status 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); + LLDB_LOG(log, "addr = {0:x}, size_hint = {1}", addr, size_hint); + + auto it = m_software_breakpoints.find(addr); + if (it != m_software_breakpoints.end()) { + ++it->second.ref_count; + return Status(); + } + auto expected_bkpt = EnableSoftwareBreakpoint(addr, size_hint); + if (!expected_bkpt) + return Status(expected_bkpt.takeError()); + + m_software_breakpoints.emplace(addr, std::move(*expected_bkpt)); + return Status(); +} + +Status NativeProcessProtocol::RemoveSoftwareBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + LLDB_LOG(log, "addr = {0:x}", addr); + auto it = m_software_breakpoints.find(addr); + if (it == m_software_breakpoints.end()) + return Status("Breakpoint not found."); + assert(it->second.ref_count > 0); + if (--it->second.ref_count > 0) + return Status(); + + // This is the last reference. Let's remove the breakpoint. + Status error; + + // Clear a software breakpoint instruction + llvm::SmallVector<uint8_t, 4> curr_break_op( + it->second.breakpoint_opcodes.size(), 0); + + // Read the breakpoint opcode + size_t bytes_read = 0; + error = + ReadMemory(addr, curr_break_op.data(), curr_break_op.size(), bytes_read); + if (error.Fail() || bytes_read < curr_break_op.size()) { + return Status("addr=0x%" PRIx64 + ": tried to read %zu bytes but only read %zu", + addr, curr_break_op.size(), bytes_read); + } + const auto &saved = it->second.saved_opcodes; + // Make sure the breakpoint opcode exists at this address + if (makeArrayRef(curr_break_op) != it->second.breakpoint_opcodes) { + if (curr_break_op != it->second.saved_opcodes) + return Status("Original breakpoint trap is no longer in memory."); + LLDB_LOG(log, + "Saved opcodes ({0:@[x]}) have already been restored at {1:x}.", + llvm::make_range(saved.begin(), saved.end()), addr); + } else { + // We found a valid breakpoint opcode at this address, now restore the + // saved opcode. + size_t bytes_written = 0; + error = WriteMemory(addr, saved.data(), saved.size(), bytes_written); + if (error.Fail() || bytes_written < saved.size()) { + return Status("addr=0x%" PRIx64 + ": tried to write %zu bytes but only wrote %zu", + addr, saved.size(), bytes_written); + } + + // Verify that our original opcode made it back to the inferior + llvm::SmallVector<uint8_t, 4> verify_opcode(saved.size(), 0); + size_t verify_bytes_read = 0; + error = ReadMemory(addr, verify_opcode.data(), verify_opcode.size(), + verify_bytes_read); + if (error.Fail() || verify_bytes_read < verify_opcode.size()) { + return Status("addr=0x%" PRIx64 + ": tried to read %zu verification bytes but only read %zu", + addr, verify_opcode.size(), verify_bytes_read); + } + if (verify_opcode != saved) + LLDB_LOG(log, "Restoring bytes at {0:x}: {1:@[x]}", addr, + llvm::make_range(saved.begin(), saved.end())); + } + + m_software_breakpoints.erase(it); + return Status(); +} + +llvm::Expected<NativeProcessProtocol::SoftwareBreakpoint> +NativeProcessProtocol::EnableSoftwareBreakpoint(lldb::addr_t addr, + uint32_t size_hint) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + + auto expected_trap = GetSoftwareBreakpointTrapOpcode(size_hint); + if (!expected_trap) + return expected_trap.takeError(); + + llvm::SmallVector<uint8_t, 4> saved_opcode_bytes(expected_trap->size(), 0); + // Save the original opcodes by reading them so we can restore later. + size_t bytes_read = 0; + Status error = ReadMemory(addr, saved_opcode_bytes.data(), + saved_opcode_bytes.size(), bytes_read); + if (error.Fail()) + return error.ToError(); + + // Ensure we read as many bytes as we expected. + if (bytes_read != saved_opcode_bytes.size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to read memory while attempting to set breakpoint: attempted " + "to read {0} bytes but only read {1}.", + saved_opcode_bytes.size(), bytes_read); + } + + LLDB_LOG( + log, "Overwriting bytes at {0:x}: {1:@[x]}", addr, + llvm::make_range(saved_opcode_bytes.begin(), saved_opcode_bytes.end())); + + // Write a software breakpoint in place of the original opcode. + size_t bytes_written = 0; + error = WriteMemory(addr, expected_trap->data(), expected_trap->size(), + bytes_written); + if (error.Fail()) + return error.ToError(); + + // Ensure we wrote as many bytes as we expected. + if (bytes_written != expected_trap->size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed write memory while attempting to set " + "breakpoint: attempted to write {0} bytes but only wrote {1}", + expected_trap->size(), bytes_written); + } + + llvm::SmallVector<uint8_t, 4> verify_bp_opcode_bytes(expected_trap->size(), + 0); + size_t verify_bytes_read = 0; + error = ReadMemory(addr, verify_bp_opcode_bytes.data(), + verify_bp_opcode_bytes.size(), verify_bytes_read); + if (error.Fail()) + return error.ToError(); + + // Ensure we read as many verification bytes as we expected. + if (verify_bytes_read != verify_bp_opcode_bytes.size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to read memory while " + "attempting to verify breakpoint: attempted to read {0} bytes " + "but only read {1}", + verify_bp_opcode_bytes.size(), verify_bytes_read); + } + + if (llvm::makeArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) != + *expected_trap) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Verification of software breakpoint " + "writing failed - trap opcodes not successfully read back " + "after writing when setting breakpoint at {0:x}", + addr); + } + + LLDB_LOG(log, "addr = {0:x}: SUCCESS", addr); + return SoftwareBreakpoint{1, saved_opcode_bytes, *expected_trap}; +} + +llvm::Expected<llvm::ArrayRef<uint8_t>> +NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { + static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; + static const uint8_t g_i386_opcode[] = {0xCC}; + static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; + static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; + static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap + + switch (GetArchitecture().GetMachine()) { + case llvm::Triple::aarch64: + return llvm::makeArrayRef(g_aarch64_opcode); + + case llvm::Triple::x86: + case llvm::Triple::x86_64: + return llvm::makeArrayRef(g_i386_opcode); + + case llvm::Triple::mips: + case llvm::Triple::mips64: + return llvm::makeArrayRef(g_mips64_opcode); + + case llvm::Triple::mipsel: + case llvm::Triple::mips64el: + return llvm::makeArrayRef(g_mips64el_opcode); + + case llvm::Triple::systemz: + return llvm::makeArrayRef(g_s390x_opcode); + + case llvm::Triple::ppc64le: + return llvm::makeArrayRef(g_ppc64le_opcode); - return m_breakpoint_list.AddRef( - addr, size_hint, false, - [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, - NativeBreakpointSP &breakpoint_sp) -> Status { - return SoftwareBreakpoint::CreateSoftwareBreakpoint( - *this, addr, size_hint, breakpoint_sp); - }); + default: + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "CPU type not supported!"); + } +} + +size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() { + switch (GetArchitecture().GetMachine()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + case llvm::Triple::systemz: + // These architectures report increment the PC after breakpoint is hit. + return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size(); + + case llvm::Triple::arm: + case llvm::Triple::aarch64: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::ppc64le: + // On these architectures the PC doesn't get updated for breakpoint hits. + return 0; + + default: + llvm_unreachable("CPU type not supported!"); + } +} + +void NativeProcessProtocol::FixupBreakpointPCAsNeeded( + NativeThreadProtocol &thread) { + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); + + Status error; + + // Find out the size of a breakpoint (might depend on where we are in the + // code). + NativeRegisterContext &context = thread.GetRegisterContext(); + + uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset(); + LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); + if (breakpoint_size == 0) + return; + + // First try probing for a breakpoint at a software breakpoint location: PC - + // breakpoint size. + const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation(); + lldb::addr_t breakpoint_addr = initial_pc_addr; + // Do not allow breakpoint probe to wrap around. + if (breakpoint_addr >= breakpoint_size) + breakpoint_addr -= breakpoint_size; + + if (m_software_breakpoints.count(breakpoint_addr) == 0) { + // We didn't find one at a software probe location. Nothing to do. + LLDB_LOG(log, + "pid {0} no lldb software breakpoint found at current pc with " + "adjustment: {1}", + GetID(), breakpoint_addr); + return; + } + + // + // We have a software breakpoint and need to adjust the PC. + // + + // Change the program counter. + LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), + thread.GetID(), initial_pc_addr, breakpoint_addr); + + error = context.SetPC(breakpoint_addr); + if (error.Fail()) { + // This can happen in case the process was killed between the time we read + // the PC and when we are updating it. There's nothing better to do than to + // swallow the error. + LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), + thread.GetID(), error); + } } Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, @@ -377,15 +631,35 @@ Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, if (hardware) return RemoveHardwareBreakpoint(addr); else - return m_breakpoint_list.DecRef(addr); -} - -Status NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { - return m_breakpoint_list.EnableBreakpoint(addr); + return RemoveSoftwareBreakpoint(addr); } -Status NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { - return m_breakpoint_list.DisableBreakpoint(addr); +Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr, + void *buf, size_t size, + size_t &bytes_read) { + Status error = ReadMemory(addr, buf, size, bytes_read); + if (error.Fail()) + return error; + + auto data = + llvm::makeMutableArrayRef(static_cast<uint8_t *>(buf), bytes_read); + for (const auto &pair : m_software_breakpoints) { + lldb::addr_t bp_addr = pair.first; + auto saved_opcodes = makeArrayRef(pair.second.saved_opcodes); + + if (bp_addr + saved_opcodes.size() < addr || addr + bytes_read <= bp_addr) + continue; // Breapoint not in range, ignore + + if (bp_addr < addr) { + saved_opcodes = saved_opcodes.drop_front(addr - bp_addr); + bp_addr = addr; + } + auto bp_data = data.drop_front(bp_addr - addr); + std::copy_n(saved_opcodes.begin(), + std::min(saved_opcodes.size(), bp_data.size()), + bp_data.begin()); + } + return Status(); } lldb::StateType NativeProcessProtocol::GetState() const { diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 49b8284da970..6e6632aa710f 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -9,8 +9,8 @@ #include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Core/RegisterValue.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" #include "lldb/Host/PosixApi.h" #include "lldb/Host/common/NativeProcessProtocol.h" diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 0c648e40eb5c..af43683295b0 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -11,7 +11,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Host/common/ProcessRunLock.cpp b/source/Host/common/ProcessRunLock.cpp index 48dcd62bb939..e0ba2ecfd3e9 100644 --- a/source/Host/common/ProcessRunLock.cpp +++ b/source/Host/common/ProcessRunLock.cpp @@ -30,7 +30,7 @@ ProcessRunLock::~ProcessRunLock() { bool ProcessRunLock::ReadTryLock() { ::pthread_rwlock_rdlock(&m_rwlock); - if (m_running == false) { + if (!m_running) { return true; } ::pthread_rwlock_unlock(&m_rwlock); diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp index c9b290078e18..08d4fa218968 100644 --- a/source/Host/common/PseudoTerminal.cpp +++ b/source/Host/common/PseudoTerminal.cpp @@ -10,7 +10,8 @@ #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/Config.h" -#include <errno.h> +#include "llvm/Support/Errno.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -27,6 +28,14 @@ int posix_openpt(int flags); using namespace lldb_private; //---------------------------------------------------------------------- +// Write string describing error number +//---------------------------------------------------------------------- +static void ErrnoToStr(char *error_str, size_t error_len) { + std::string strerror = llvm::sys::StrError(); + ::snprintf(error_str, error_len, "%s", strerror.c_str()); +} + +//---------------------------------------------------------------------- // PseudoTerminal constructor //---------------------------------------------------------------------- PseudoTerminal::PseudoTerminal() @@ -88,14 +97,14 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, m_master_fd = ::posix_openpt(oflag); if (m_master_fd < 0) { if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); return false; } // Grant access to the slave pseudo terminal if (::grantpt(m_master_fd) < 0) { if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); CloseMasterFileDescriptor(); return false; } @@ -103,7 +112,7 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, // Clear the lock flag on the slave pseudo terminal if (::unlockpt(m_master_fd) < 0) { if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); CloseMasterFileDescriptor(); return false; } @@ -143,7 +152,7 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { if (m_slave_fd < 0) { if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); return false; } @@ -175,7 +184,7 @@ const char *PseudoTerminal::GetSlaveName(char *error_str, const char *slave_name = ::ptsname(m_master_fd); if (error_str && slave_name == nullptr) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); return slave_name; } @@ -213,7 +222,7 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { if (pid < 0) { // Fork failed if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); } else if (pid == 0) { // Child Process ::setsid(); @@ -229,23 +238,23 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { // Acquire the controlling terminal if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) { if (error_str) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); } #endif // Duplicate all stdio file descriptors to the slave pseudo terminal if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) { if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); } if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) { if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); } if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) { if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); + ErrnoToStr(error_str, error_len); } } } else { diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index def3e0359f01..172cb06a5819 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -21,7 +21,6 @@ #include <stddef.h> #include <stdio.h> -// C Includes #if !defined(_WIN32) #include <arpa/inet.h> #endif @@ -29,9 +28,6 @@ #include <assert.h> #include <string.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/PosixApi.h" // WindowsXP needs an inet_ntop implementation diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp deleted file mode 100644 index 353dadf6ce6d..000000000000 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ /dev/null @@ -1,350 +0,0 @@ -//===-- SoftwareBreakpoint.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/common/SoftwareBreakpoint.h" - -#include "lldb/Host/Debug.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" - -#include "lldb/Host/common/NativeProcessProtocol.h" - -using namespace lldb_private; - -// ------------------------------------------------------------------- static -// members ------------------------------------------------------------------- - -Status SoftwareBreakpoint::CreateSoftwareBreakpoint( - NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, - NativeBreakpointSP &breakpoint_sp) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - // Validate the address. - if (addr == LLDB_INVALID_ADDRESS) - return Status("SoftwareBreakpoint::%s invalid load address specified.", - __FUNCTION__); - - // Ask the NativeProcessProtocol subclass to fill in the correct software - // breakpoint trap for the breakpoint site. - size_t bp_opcode_size = 0; - const uint8_t *bp_opcode_bytes = NULL; - Status error = process.GetSoftwareBreakpointTrapOpcode( - size_hint, bp_opcode_size, bp_opcode_bytes); - - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve software " - "breakpoint trap opcode: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Validate size of trap opcode. - if (bp_opcode_size == 0) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", - __FUNCTION__); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned zero, unable to get breakpoint trap for address " - "0x%" PRIx64, - addr); - } - - if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE) { - if (log) - log->Printf("SoftwareBreakpoint::%s cannot support %zu trapcode bytes, " - "max size is %zu", - __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned too many trap opcode bytes: requires %zu but we " - "only support a max of %zu", - bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - } - - // Validate that we received opcodes. - if (!bp_opcode_bytes) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", - __FUNCTION__); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned NULL trap opcode bytes, unable to get breakpoint " - "trap for address 0x%" PRIx64, - addr); - } - - // Enable the breakpoint. - uint8_t saved_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - error = EnableSoftwareBreakpoint(process, addr, bp_opcode_size, - bp_opcode_bytes, saved_opcode_bytes); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s: failed to enable new breakpoint at " - "0x%" PRIx64 ": %s", - __FUNCTION__, addr, error.AsCString()); - return error; - } - - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); - - // Set the breakpoint and verified it was written properly. Now create a - // breakpoint remover that understands how to undo this breakpoint. - breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes, - bp_opcode_bytes, bp_opcode_size)); - return Status(); -} - -Status SoftwareBreakpoint::EnableSoftwareBreakpoint( - NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, - const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes) { - assert(bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && - "bp_opcode_size out of valid range"); - assert(bp_opcode_bytes && "bp_opcode_bytes is NULL"); - assert(saved_opcode_bytes && "saved_opcode_bytes is NULL"); - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - // Save the original opcodes by reading them so we can restore later. - size_t bytes_read = 0; - - Status error = - process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we read as many bytes as we expected. - if (bytes_read != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, bytes_read); - return Status("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, bytes_read); - } - - // Log what we read. - if (log) { - int i = 0; - for (const uint8_t *read_byte = saved_opcode_bytes; - read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " ovewriting byte index %d (was 0x%hhx)", - __FUNCTION__, addr, i++, *read_byte); - } - } - - // Write a software breakpoint in place of the original opcode. - size_t bytes_written = 0; - error = - process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to write memory while " - "attempting to set breakpoint: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we wrote as many bytes as we expected. - if (bytes_written != bp_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s failed write memory while attempting to set " - "breakpoint: attempted to write %zu bytes but only wrote %zu", - __FUNCTION__, bp_opcode_size, bytes_written); - if (log) - log->PutCString(error.AsCString()); - return error; - } - - uint8_t verify_bp_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - size_t verify_bytes_read = 0; - error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size, - verify_bytes_read); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify the breakpoint set: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we read as many verification bytes as we expected. - if (verify_bytes_read != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu " - "bytes but only read %zu", - __FUNCTION__, bp_opcode_size, verify_bytes_read); - return Status( - "SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, verify_bytes_read); - } - - if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0) { - if (log) - log->Printf("SoftwareBreakpoint::%s: verification of software breakpoint " - "writing failed - trap opcodes not successfully read back " - "after writing when setting breakpoint at 0x%" PRIx64, - __FUNCTION__, addr); - return Status("SoftwareBreakpoint::%s: verification of software breakpoint " - "writing failed - trap opcodes not successfully read back " - "after writing when setting breakpoint at 0x%" PRIx64, - __FUNCTION__, addr); - } - - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); - - return Status(); -} - -// ------------------------------------------------------------------- -// instance-level members -// ------------------------------------------------------------------- - -SoftwareBreakpoint::SoftwareBreakpoint(NativeProcessProtocol &process, - lldb::addr_t addr, - const uint8_t *saved_opcodes, - const uint8_t *trap_opcodes, - size_t opcode_size) - : NativeBreakpoint(addr), m_process(process), m_saved_opcodes(), - m_trap_opcodes(), m_opcode_size(opcode_size) { - assert(opcode_size > 0 && "setting software breakpoint with no trap opcodes"); - assert(opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large"); - - ::memcpy(m_saved_opcodes, saved_opcodes, opcode_size); - ::memcpy(m_trap_opcodes, trap_opcodes, opcode_size); -} - -Status SoftwareBreakpoint::DoEnable() { - return EnableSoftwareBreakpoint(m_process, m_addr, m_opcode_size, - m_trap_opcodes, m_saved_opcodes); -} - -Status SoftwareBreakpoint::DoDisable() { - Status error; - assert(m_addr && (m_addr != LLDB_INVALID_ADDRESS) && - "can't remove a software breakpoint for an invalid address"); - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, - m_addr); - - assert((m_opcode_size > 0) && - "cannot restore opcodes when there are no opcodes"); - - if (m_opcode_size > 0) { - // Clear a software breakpoint instruction - uint8_t curr_break_op[MAX_TRAP_OPCODE_SIZE]; - bool break_op_found = false; - assert(m_opcode_size <= sizeof(curr_break_op)); - - // Read the breakpoint opcode - size_t bytes_read = 0; - error = - m_process.ReadMemory(m_addr, curr_break_op, m_opcode_size, bytes_read); - if (error.Success() && bytes_read < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpointr::%s addr=0x%" PRIx64 - ": tried to read %zu bytes but only read %zu", - __FUNCTION__, m_addr, m_opcode_size, bytes_read); - } - if (error.Success()) { - bool verify = false; - // Make sure the breakpoint opcode exists at this address - if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) { - break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore the - // saved opcode. - size_t bytes_written = 0; - error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size, - bytes_written); - if (error.Success() && bytes_written < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to write %zu bytes but only wrote %zu", - __FUNCTION__, m_addr, m_opcode_size, bytes_written); - } - if (error.Success()) { - verify = true; - } - } else { - error.SetErrorString( - "Original breakpoint trap is no longer in memory."); - // Set verify to true and so we can check if the original opcode has - // already been restored - verify = true; - } - - if (verify) { - uint8_t verify_opcode[MAX_TRAP_OPCODE_SIZE]; - assert(m_opcode_size <= sizeof(verify_opcode)); - // Verify that our original opcode made it back to the inferior - - size_t verify_bytes_read = 0; - error = m_process.ReadMemory(m_addr, verify_opcode, m_opcode_size, - verify_bytes_read); - if (error.Success() && verify_bytes_read < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to read %zu verification bytes but only read %zu", - __FUNCTION__, m_addr, m_opcode_size, verify_bytes_read); - } - if (error.Success()) { - // compare the memory we just read with the original opcode - if (::memcmp(m_saved_opcodes, verify_opcode, m_opcode_size) == 0) { - // SUCCESS - if (log) { - int i = 0; - for (const uint8_t *verify_byte = verify_opcode; - verify_byte < verify_opcode + m_opcode_size; ++verify_byte) { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " replaced byte index %d with 0x%hhx", - __FUNCTION__, m_addr, i++, *verify_byte); - } - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " -- SUCCESS", - __FUNCTION__, m_addr); - } - return error; - } else { - if (break_op_found) - error.SetErrorString("Failed to restore original opcode."); - } - } else - error.SetErrorString("Failed to read memory to verify that " - "breakpoint trap was restored."); - } - } - } - - if (log && error.Fail()) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s", - __FUNCTION__, m_addr, error.AsCString()); - return error; -} - -bool SoftwareBreakpoint::IsSoftwareBreakpoint() const { return true; } diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp index b4171437b7e2..8f4e1956fc28 100644 --- a/source/Host/common/StringConvert.cpp +++ b/source/Host/common/StringConvert.cpp @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <stdlib.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/StringConvert.h" namespace lldb_private { diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index d7e0c13112aa..ed1677cbcb58 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -16,7 +16,6 @@ #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/SafeMachO.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" @@ -29,7 +28,6 @@ typedef int cpu_subtype_t; using namespace lldb; using namespace lldb_private; -using namespace llvm::MachO; #if defined(__APPLE__) @@ -67,96 +65,133 @@ static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, return false; } +// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid, +// return true if there is a matching dSYM bundle next to the exec_fspec, +// and return that value in dsym_fspec. +// If there is a .dSYM.yaa compressed archive next to the exec_fspec, +// call through Symbols::DownloadObjectAndSymbolFile to download the +// expanded/uncompressed dSYM and return that filepath in dsym_fspec. + +static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec, + const FileSpec &exec_fspec, + FileSpec &dsym_fspec) { + ConstString filename = exec_fspec.GetFilename(); + FileSpec dsym_directory = exec_fspec; + dsym_directory.RemoveLastPathComponent(); + + std::string dsym_filename = filename.AsCString(); + dsym_filename += ".dSYM"; + dsym_directory.AppendPathComponent(dsym_filename); + dsym_directory.AppendPathComponent("Contents"); + dsym_directory.AppendPathComponent("Resources"); + dsym_directory.AppendPathComponent("DWARF"); + + if (FileSystem::Instance().Exists(dsym_directory)) { + + // See if the binary name exists in the dSYM DWARF + // subdir. + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(filename.AsCString()); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + + // See if we have "../CF.framework" - so we'll look for + // CF.framework.dSYM/Contents/Resources/DWARF/CF + // We need to drop the last suffix after '.' to match + // 'CF' in the DWARF subdir. + std::string binary_name (filename.AsCString()); + auto last_dot = binary_name.find_last_of('.'); + if (last_dot != std::string::npos) { + binary_name.erase(last_dot); + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(binary_name); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, + mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + } + } + + // See if we have a .dSYM.yaa next to this executable path. + FileSpec dsym_yaa_fspec = exec_fspec; + dsym_yaa_fspec.RemoveLastPathComponent(); + std::string dsym_yaa_filename = filename.AsCString(); + dsym_yaa_filename += ".dSYM.yaa"; + dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename); + + if (FileSystem::Instance().Exists(dsym_yaa_fspec)) { + ModuleSpec mutable_mod_spec = mod_spec; + if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, true) && + FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) { + dsym_fspec = mutable_mod_spec.GetSymbolFileSpec(); + return true; + } + } + + return false; +} + +// Given a ModuleSpec with a FileSpec and optionally uuid/architecture +// filled in, look for a .dSYM bundle next to that binary. Returns true +// if a .dSYM bundle is found, and that path is returned in the dsym_fspec +// FileSpec. +// +// This routine looks a few directory layers above the given exec_path - +// exec_path might be /System/Library/Frameworks/CF.framework/CF and the +// dSYM might be /System/Library/Frameworks/CF.framework.dSYM. +// +// If there is a .dSYM.yaa compressed archive found next to the binary, +// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM + static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, FileSpec &dsym_fspec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + const FileSpec &exec_fspec = module_spec.GetFileSpec(); if (exec_fspec) { - char path[PATH_MAX]; - if (exec_fspec->GetPath(path, sizeof(path))) { - // Make sure the module isn't already just a dSYM file... - if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) { + if (::LookForDsymNextToExecutablePath (module_spec, exec_fspec, dsym_fspec)) { if (log) { - if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) { - log->Printf( - "Searching for dSYM bundle next to executable %s, UUID %s", - path, module_spec.GetUUIDPtr()->GetAsString().c_str()); - } else { - log->Printf("Searching for dSYM bundle next to executable %s", - path); - } + log->Printf("dSYM with matching UUID & arch found at %s", dsym_fspec.GetPath().c_str()); } - ::strncat(path, ".dSYM/Contents/Resources/DWARF/", - sizeof(path) - strlen(path) - 1); - ::strncat(path, exec_fspec->GetFilename().AsCString(), - sizeof(path) - strlen(path) - 1); - - dsym_fspec.SetFile(path, false, FileSpec::Style::native); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID(dsym_fspec, - module_spec.GetArchitecturePtr(), - module_spec.GetUUIDPtr())) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", path); - } - return true; - } else { - FileSpec parent_dirs = exec_fspec; - - // Remove the binary name from the FileSpec - parent_dirs.RemoveLastPathComponent(); - - // Add a ".dSYM" name to each directory component of the path, - // stripping off components. e.g. we may have a binary like - // /S/L/F/Foundation.framework/Versions/A/Foundation and - // /S/L/F/Foundation.framework.dSYM - // - // so we'll need to start with - // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the - // "A", and if that doesn't exist, strip off the "A" and try it again - // with "Versions", etc., until we find a dSYM bundle or we've - // stripped off enough path components that there's no need to - // continue. - - for (int i = 0; i < 4; i++) { - // Does this part of the path have a "." character - could it be a - // bundle's top level directory? - const char *fn = parent_dirs.GetFilename().AsCString(); - if (fn == nullptr) - break; - if (::strchr(fn, '.') != nullptr) { - dsym_fspec = parent_dirs; - dsym_fspec.RemoveLastPathComponent(); - - // If the current directory name is "Foundation.framework", see - // if - // "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation" - // exists & has the right uuid. - std::string dsym_fn = fn; - dsym_fn += ".dSYM"; - dsym_fspec.AppendPathComponent(dsym_fn.c_str()); - dsym_fspec.AppendPathComponent("Contents"); - dsym_fspec.AppendPathComponent("Resources"); - dsym_fspec.AppendPathComponent("DWARF"); - dsym_fspec.AppendPathComponent( - exec_fspec->GetFilename().AsCString()); - if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID( - dsym_fspec, module_spec.GetArchitecturePtr(), - module_spec.GetUUIDPtr())) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; - } + return true; + } else { + FileSpec parent_dirs = exec_fspec; + + // Remove the binary name from the FileSpec + parent_dirs.RemoveLastPathComponent(); + + // Add a ".dSYM" name to each directory component of the path, + // stripping off components. e.g. we may have a binary like + // /S/L/F/Foundation.framework/Versions/A/Foundation and + // /S/L/F/Foundation.framework.dSYM + // + // so we'll need to start with + // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the + // "A", and if that doesn't exist, strip off the "A" and try it again + // with "Versions", etc., until we find a dSYM bundle or we've + // stripped off enough path components that there's no need to + // continue. + + for (int i = 0; i < 4; i++) { + // Does this part of the path have a "." character - could it be a + // bundle's top level directory? + const char *fn = parent_dirs.GetFilename().AsCString(); + if (fn == nullptr) + break; + if (::strchr(fn, '.') != nullptr) { + if (::LookForDsymNextToExecutablePath (module_spec, parent_dirs, dsym_fspec)) { + if (log) { + log->Printf("dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); } - parent_dirs.RemoveLastPathComponent(); + return true; } } + parent_dirs.RemoveLastPathComponent(); } } } @@ -164,7 +199,7 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, return false; } -FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { +static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); const ArchSpec *arch = module_spec.GetArchitecturePtr(); const UUID *uuid = module_spec.GetUUIDPtr(); @@ -180,7 +215,7 @@ FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { ModuleSpec dsym_module_spec; // First try and find the dSYM in the same directory as the executable or in // an appropriate parent directory - if (LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec) == false) { + if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) { // We failed to easily find the dSYM above, so use DebugSymbols LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec); } else { @@ -212,9 +247,12 @@ ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) { return result; } +// Keep "symbols.enable-external-lookup" description in sync with this function. + FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); - if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists()) + if (symbol_file_spec.IsAbsolute() && + FileSystem::Instance().Exists(symbol_file_spec)) return symbol_file_spec; const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); @@ -225,25 +263,42 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { // Add module directory. FileSpec module_file_spec = module_spec.GetFileSpec(); // We keep the unresolved pathname if it fails. - FileSystem::ResolveSymbolicLink(module_file_spec, module_file_spec); + FileSystem::Instance().ResolveSymbolicLink(module_file_spec, module_file_spec); const ConstString &file_dir = module_file_spec.GetDirectory(); - debug_file_search_paths.AppendIfUnique( - FileSpec(file_dir.AsCString("."), true)); + { + FileSpec file_spec(file_dir.AsCString(".")); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } + + if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { - // Add current working directory. - debug_file_search_paths.AppendIfUnique(FileSpec(".", true)); + // Add current working directory. + { + FileSpec file_spec("."); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } #ifndef _WIN32 #if defined(__NetBSD__) - // Add /usr/libdata/debug directory. - debug_file_search_paths.AppendIfUnique( - FileSpec("/usr/libdata/debug", true)); + // Add /usr/libdata/debug directory. + { + FileSpec file_spec("/usr/libdata/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } #else - // Add /usr/lib/debug directory. - debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); + // Add /usr/lib/debug directory. + { + FileSpec file_spec("/usr/lib/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } #endif #endif // _WIN32 + } std::string uuid_str; const UUID &module_uuid = module_spec.GetUUID(); @@ -260,8 +315,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { size_t num_directories = debug_file_search_paths.GetSize(); for (size_t idx = 0; idx < num_directories; ++idx) { FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); - dirspec.ResolvePath(); - if (!llvm::sys::fs::is_directory(dirspec.GetPath())) + FileSystem::Instance().Resolve(dirspec); + if (!FileSystem::Instance().IsDirectory(dirspec)) continue; std::vector<std::string> files; @@ -279,13 +334,14 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { const uint32_t num_files = files.size(); for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { const std::string &filename = files[idx_file]; - FileSpec file_spec(filename, true); + FileSpec file_spec(filename); + FileSystem::Instance().Resolve(file_spec); if (llvm::sys::fs::equivalent(file_spec.GetPath(), module_file_spec.GetPath())) continue; - if (file_spec.Exists()) { + if (FileSystem::Instance().Exists(file_spec)) { lldb_private::ModuleSpecList specs; const size_t num_specs = ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); diff --git a/source/Host/common/TaskPool.cpp b/source/Host/common/TaskPool.cpp index c54b9a8ae56b..ba1362a46f33 100644 --- a/source/Host/common/TaskPool.cpp +++ b/source/Host/common/TaskPool.cpp @@ -10,9 +10,9 @@ #include "lldb/Host/TaskPool.h" #include "lldb/Host/ThreadLauncher.h" -#include <cstdint> // for uint32_t -#include <queue> // for queue -#include <thread> // for thread +#include <cstdint> +#include <queue> +#include <thread> namespace lldb_private { diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index 7468a3d7ac65..967a294cbf72 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -201,8 +201,7 @@ void XMLNode::ForEachAttribute(AttributeCallback const &callback) const { llvm::StringRef attr_value; if (child->content) attr_value = llvm::StringRef((const char *)child->content); - if (callback(llvm::StringRef((const char *)attr->name), attr_value) == - false) + if (!callback(llvm::StringRef((const char *)attr->name), attr_value)) return; } } @@ -217,7 +216,7 @@ void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const { if (IsValid()) { // iterate through all siblings for (xmlNodePtr node = m_node; node; node = node->next) { - if (callback(XMLNode(node)) == false) + if (!callback(XMLNode(node))) return; } } @@ -234,7 +233,7 @@ void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const { if (node->type != XML_ELEMENT_NODE) continue; - if (callback(XMLNode(node)) == false) + if (!callback(XMLNode(node))) return; } } @@ -263,7 +262,7 @@ void XMLNode::ForEachSiblingElementWithName( // ignore this one } - if (callback(XMLNode(node)) == false) + if (!callback(XMLNode(node))) return; } } @@ -439,7 +438,7 @@ XMLNode ApplePropertyList::GetValueNode(const char *key) const { "key", [key, &value_node](const XMLNode &key_node) -> bool { std::string key_name; if (key_node.GetElementText(key_name)) { - if (key_name.compare(key) == 0) { + if (key_name == key) { value_node = key_node.GetSibling(); while (value_node && !value_node.IsElement()) value_node = value_node.GetSibling(); diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 87552bc2a27e..7bf959aee982 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -8,7 +8,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <sys/types.h> #include <sys/exec.h> @@ -23,9 +22,6 @@ #include <execinfo.h> #include <stdio.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" @@ -75,11 +71,9 @@ GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, size_t pathname_len = sizeof(pathname); mib[2] = KERN_PROC_PATHNAME; if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0) - process_info.GetExecutableFile().SetFile(pathname, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(pathname, FileSpec::Style::native); else - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index 18eae3eb7606..d123936b3668 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -69,7 +69,7 @@ FileSpec HostInfoFreeBSD::GetProgramFileSpec() { if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) { char *exe_path = new char[exe_path_size]; if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) - g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native); + g_program_filespec.SetFile(exe_path, FileSpec::Style::native); delete[] exe_path; } } diff --git a/source/Host/linux/Host.cpp b/source/Host/linux/Host.cpp index 1a0eb767eb34..bd596f8cbfe0 100644 --- a/source/Host/linux/Host.cpp +++ b/source/Host/linux/Host.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <dirent.h> #include <errno.h> #include <fcntl.h> @@ -18,20 +17,17 @@ #include <sys/utsname.h> #include <unistd.h> -// C++ Includes -// Other libraries and framework includes #include "llvm/Object/ELF.h" #include "llvm/Support/ScopedPrinter.h" -// Project includes #include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/linux/Support.h" -#include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/DataExtractor.h" using namespace lldb; @@ -125,7 +121,7 @@ static bool IsDirNumeric(const char *dname) { static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - auto buffer_sp = DataBufferLLVM::CreateSliceFromPath(exe_path, 0x20, 0); + auto buffer_sp = FileSystem::Instance().CreateDataBuffer(exe_path, 0x20, 0); if (!buffer_sp) return ArchSpec(); @@ -190,8 +186,7 @@ static bool GetProcessAndStatInfo(::pid_t pid, return false; process_info.SetProcessID(pid); - process_info.GetExecutableFile().SetFile(PathRef, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native); llvm::StringRef Rest = Environ->getBuffer(); while (!Rest.empty()) { diff --git a/source/Host/linux/HostInfoLinux.cpp b/source/Host/linux/HostInfoLinux.cpp index 1d95010e2f73..f5a6b2c97a0d 100644 --- a/source/Host/linux/HostInfoLinux.cpp +++ b/source/Host/linux/HostInfoLinux.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/Config.h" #include "lldb/Host/linux/HostInfoLinux.h" +#include "lldb/Host/Config.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Utility/Log.h" #include "llvm/Support/Threading.h" @@ -20,7 +21,7 @@ #include <unistd.h> #include <algorithm> -#include <mutex> // std::once +#include <mutex> using namespace lldb_private; @@ -170,7 +171,7 @@ FileSpec HostInfoLinux::GetProgramFileSpec() { ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); if (len > 0) { exe_path[len] = 0; - g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native); + g_program_filespec.SetFile(exe_path, FileSpec::Style::native); } } @@ -179,14 +180,15 @@ FileSpec HostInfoLinux::GetProgramFileSpec() { bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) { if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && - file_spec.IsAbsolute() && file_spec.Exists()) + file_spec.IsAbsolute() && FileSystem::Instance().Exists(file_spec)) return true; file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory(); return !file_spec.GetDirectory().IsEmpty(); } bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) { - FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins", true); + FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins"); + FileSystem::Instance().Resolve(temp_file); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; } diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp index b01c48e51d90..980bbc34449c 100644 --- a/source/Host/macosx/Symbols.cpp +++ b/source/Host/macosx/Symbols.cpp @@ -9,16 +9,11 @@ #include "lldb/Host/Symbols.h" -// C Includes -#include "lldb/Utility/SafeMachO.h" #include <dirent.h> #include <pwd.h> -// C++ Includes -// Other libraries and framework includes #include <CoreFoundation/CoreFoundation.h> -// Project includes #include "Host/macosx/cfcpp/CFCBundle.h" #include "Host/macosx/cfcpp/CFCData.h" #include "Host/macosx/cfcpp/CFCReleaser.h" @@ -42,7 +37,6 @@ using namespace lldb; using namespace lldb_private; -using namespace llvm::MachO; #if !defined(__arm__) && !defined(__arm64__) && \ !defined(__aarch64__) // No DebugSymbols on the iOS devices @@ -107,9 +101,11 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, "UUID %s -- looking for the dSYM", path, uuid->GetAsString().c_str()); } - FileSpec dsym_filespec(path, path[0] == '~'); + FileSpec dsym_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(dsym_filespec); - if (llvm::sys::fs::is_directory(dsym_filespec.GetPath())) { + if (FileSystem::Instance().IsDirectory(dsym_filespec)) { dsym_filespec = Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch); ++items_found; @@ -148,8 +144,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, path, uuid->GetAsString().c_str()); } ++items_found; - FileSpec exec_filespec(path, path[0] == '~'); - if (exec_filespec.Exists()) { + FileSpec exec_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(exec_filespec); + if (FileSystem::Instance().Exists(exec_filespec)) { success = true; return_module_spec.GetFileSpec() = exec_filespec; } @@ -169,7 +167,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, "bundle with name with name %s", path); } - FileSpec file_spec(path, true); + FileSpec file_spec(path); + FileSystem::Instance().Resolve(file_spec); ModuleSpecList module_specs; ModuleSpec matched_module_spec; using namespace llvm::sys::fs; @@ -184,7 +183,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (::CFURLGetFileSystemRepresentation(bundle_exe_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { - FileSpec bundle_exe_file_spec(path, true); + FileSpec bundle_exe_file_spec(path); + FileSystem::Instance().Resolve(bundle_exe_file_spec); if (ObjectFile::GetModuleSpecifications( bundle_exe_file_spec, 0, 0, module_specs) && module_specs.FindMatchingModuleSpec( @@ -309,8 +309,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { - module_spec.GetFileSpec().SetFile(str.c_str(), true, - FileSpec::Style::native); + module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native); + FileSystem::Instance().Resolve(module_spec.GetFileSpec()); if (log) { log->Printf( "From dsymForUUID plist: Symbol rich executable is at '%s'", @@ -323,8 +323,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, CFSTR("DBGDSYMPath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { - module_spec.GetSymbolFileSpec().SetFile(str.c_str(), true, + module_spec.GetSymbolFileSpec().SetFile(str.c_str(), FileSpec::Style::native); + FileSystem::Instance().Resolve(module_spec.GetFileSpec()); success = true; if (log) { log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); @@ -398,12 +399,13 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, // DBGSourcePath values (the "values" half of key-value path pairs) // were wrong. Ignore them and use the universal DBGSourcePath // string from earlier. - if (new_style_source_remapping_dictionary == true && + if (new_style_source_remapping_dictionary && !original_DBGSourcePath_value.empty()) { DBGSourcePath = original_DBGSourcePath_value; } if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path(DBGSourcePath.c_str(), true); + FileSpec resolved_source_path(DBGSourcePath.c_str()); + FileSystem::Instance().Resolve(resolved_source_path); DBGSourcePath = resolved_source_path.GetPath(); } // With version 2 of DBGSourcePathRemapping, we can chop off the @@ -414,8 +416,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); if (do_truncate_remapping_names) { - FileSpec build_path(DBGBuildSourcePath.c_str(), false); - FileSpec source_path(DBGSourcePath.c_str(), false); + FileSpec build_path(DBGBuildSourcePath.c_str()); + FileSpec source_path(DBGSourcePath.c_str()); build_path.RemoveLastPathComponent(); build_path.RemoveLastPathComponent(); source_path.RemoveLastPathComponent(); @@ -451,7 +453,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path(DBGSourcePath.c_str(), true); + FileSpec resolved_source_path(DBGSourcePath.c_str()); + FileSystem::Instance().Resolve(resolved_source_path); DBGSourcePath = resolved_source_path.GetPath(); } module_spec.GetSourceMappingList().Append( @@ -472,7 +475,7 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, // it once per lldb run and cache the result. static bool g_have_checked_for_dbgshell_command = false; static const char *g_dbgshell_command = NULL; - if (g_have_checked_for_dbgshell_command == false) { + if (!g_have_checked_for_dbgshell_command) { g_have_checked_for_dbgshell_command = true; CFTypeRef defaults_setting = CFPreferencesCopyAppValue( CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols")); @@ -492,11 +495,12 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, // When g_dbgshell_command is NULL, the user has not enabled the use of an // external program to find the symbols, don't run it for them. - if (force_lookup == false && g_dbgshell_command == NULL) { + if (!force_lookup && g_dbgshell_command == NULL) { return false; } - if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) { + if (uuid_ptr || + (file_spec_ptr && FileSystem::Instance().Exists(*file_spec_ptr))) { static bool g_located_dsym_for_uuid_exe = false; static bool g_dsym_for_uuid_exe_exists = false; static char g_dsym_for_uuid_exe_path[PATH_MAX]; @@ -506,15 +510,18 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE"); FileSpec dsym_for_uuid_exe_spec; if (dsym_for_uuid_exe_path_cstr) { - dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true, + dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec); + g_dsym_for_uuid_exe_exists = + FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); } if (!g_dsym_for_uuid_exe_exists) { - dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false, + dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + g_dsym_for_uuid_exe_exists = + FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); if (!g_dsym_for_uuid_exe_exists) { long bufsize; if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) { @@ -527,17 +534,20 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, tilde_rc && tilde_rc->pw_dir) { std::string dsymforuuid_path(tilde_rc->pw_dir); dsymforuuid_path += "/bin/dsymForUUID"; - dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false, + dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + g_dsym_for_uuid_exe_exists = + FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); } } } } if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) { - dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true, + dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec); + g_dsym_for_uuid_exe_exists = + FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); } if (g_dsym_for_uuid_exe_exists) diff --git a/source/Host/macosx/cfcpp/CFCMutableArray.cpp b/source/Host/macosx/cfcpp/CFCMutableArray.cpp index 0b6258315eb0..f426e9c13a59 100644 --- a/source/Host/macosx/cfcpp/CFCMutableArray.cpp +++ b/source/Host/macosx/cfcpp/CFCMutableArray.cpp @@ -88,7 +88,7 @@ bool CFCMutableArray::SetValueAtIndex(CFIndex idx, const void *value) { bool CFCMutableArray::AppendValue(const void *value, bool can_create) { CFMutableArrayRef array = get(); if (array == NULL) { - if (can_create == false) + if (!can_create) return false; array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -106,7 +106,7 @@ bool CFCMutableArray::AppendCStringAsCFString(const char *s, bool can_create) { CFMutableArrayRef array = get(); if (array == NULL) { - if (can_create == false) + if (!can_create) return false; array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -124,7 +124,7 @@ bool CFCMutableArray::AppendFileSystemRepresentationAsCFString( const char *s, bool can_create) { CFMutableArrayRef array = get(); if (array == NULL) { - if (can_create == false) + if (!can_create) return false; array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); diff --git a/source/Host/macosx/cfcpp/CFCMutableSet.cpp b/source/Host/macosx/cfcpp/CFCMutableSet.cpp index c339e950674b..b8bf81e1b52e 100644 --- a/source/Host/macosx/cfcpp/CFCMutableSet.cpp +++ b/source/Host/macosx/cfcpp/CFCMutableSet.cpp @@ -9,10 +9,6 @@ #include "CFCMutableSet.h" -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes //---------------------------------------------------------------------- // CFCString constructor @@ -64,7 +60,7 @@ const void *CFCMutableSet::GetValue(const void *value) const { const void *CFCMutableSet::AddValue(const void *value, bool can_create) { CFMutableSetRef set = get(); if (set == NULL) { - if (can_create == false) + if (!can_create) return NULL; set = ::CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); reset(set); diff --git a/source/Host/macosx/objcxx/Host.mm b/source/Host/macosx/objcxx/Host.mm index a70bf0421ec4..3cf44c4cb65f 100644 --- a/source/Host/macosx/objcxx/Host.mm +++ b/source/Host/macosx/objcxx/Host.mm @@ -55,10 +55,11 @@ #include <unistd.h> #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Process.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" @@ -100,12 +101,12 @@ using namespace lldb_private; bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle_directory) { #if defined(__APPLE__) - if (llvm::sys::fs::is_directory(file.GetPath())) { + if (FileSystem::Instance().IsDirectory(file)) { char path[PATH_MAX]; if (file.GetPath(path, sizeof(path))) { CFCBundle bundle(path); if (bundle.GetPath(path, sizeof(path))) { - bundle_directory.SetFile(path, false, FileSpec::Style::native); + bundle_directory.SetFile(path, FileSpec::Style::native); return true; } } @@ -117,7 +118,7 @@ bool Host::GetBundleDirectory(const FileSpec &file, bool Host::ResolveExecutableInBundle(FileSpec &file) { #if defined(__APPLE__) - if (llvm::sys::fs::is_directory(file.GetPath())) { + if (FileSystem::Instance().IsDirectory(file)) { char path[PATH_MAX]; if (file.GetPath(path, sizeof(path))) { CFCBundle bundle(path); @@ -125,7 +126,7 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) { if (url.get()) { if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path, sizeof(path))) { - file.SetFile(path, false, FileSpec::Style::native); + file.SetFile(path, FileSpec::Style::native); return true; } } @@ -225,7 +226,7 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path, darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); - if (!darwin_debug_file_spec.Exists()) { + if (!FileSystem::Instance().Exists(darwin_debug_file_spec)) { error.SetErrorStringWithFormat( "the 'darwin-debug' executable doesn't exists at '%s'", darwin_debug_file_spec.GetPath().c_str()); @@ -485,11 +486,9 @@ static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) { bool host_cpu_is_64bit; uint32_t is64bit_capable; size_t is64bit_capable_len = sizeof(is64bit_capable); - if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, - &is64bit_capable_len, NULL, 0) == 0) - host_cpu_is_64bit = true; - else - host_cpu_is_64bit = false; + host_cpu_is_64bit = + sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, + &is64bit_capable_len, NULL, 0) == 0; // if the host is an armv8 device, its cpusubtype will be in // CPU_SUBTYPE_ARM64 numbering @@ -541,8 +540,7 @@ static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, triple_arch == llvm::Triple::x86_64); const char *cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (match_info_ptr == NULL || NameMatches( @@ -629,7 +627,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; size_t pid_data_size = 0; - if (::sysctl(mib, 4, NULL, &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 3, nullptr, &pid_data_size, nullptr, 0) != 0) return 0; // Add a few extra in case a few more show up @@ -639,7 +637,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, kinfos.resize(estimated_pid_count); pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); - if (::sysctl(mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, nullptr, 0) != 0) return 0; const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); @@ -660,7 +658,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, if (our_uid == 0) kinfo_user_matches = true; - if (kinfo_user_matches == false || // Make sure the user is acceptable + if (!kinfo_user_matches || // Make sure the user is acceptable static_cast<lldb::pid_t>(kinfo.kp_proc.p_pid) == our_pid || // Skip this process kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero) @@ -1273,21 +1271,19 @@ static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) { Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; + + FileSystem &fs = FileSystem::Instance(); FileSpec exe_spec(launch_info.GetExecutableFile()); - llvm::sys::fs::file_status stats; - status(exe_spec.GetPath(), stats); - if (!exists(stats)) { - exe_spec.ResolvePath(); - status(exe_spec.GetPath(), stats); - } - if (!exists(stats)) { - exe_spec.ResolveExecutableLocation(); - status(exe_spec.GetPath(), stats); - } - if (!exists(stats)) { + if (!fs.Exists(exe_spec)) + FileSystem::Instance().Resolve(exe_spec); + + if (!fs.Exists(exe_spec)) + FileSystem::Instance().ResolveExecutableLocation(exe_spec); + + if (!fs.Exists(exe_spec)) { error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'", - launch_info.GetExecutableFile()); + exe_spec); return error; } @@ -1337,7 +1333,7 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { return error; } expand_tool_spec.AppendPathComponent("lldb-argdumper"); - if (!expand_tool_spec.Exists()) { + if (!FileSystem::Instance().Exists(expand_tool_spec)) { error.SetErrorStringWithFormat( "could not find the lldb-argdumper tool: %s", expand_tool_spec.GetPath().c_str()); @@ -1354,14 +1350,14 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { int status; std::string output; FileSpec cwd(launch_info.GetWorkingDirectory()); - if (!cwd.Exists()) { + if (!FileSystem::Instance().Exists(cwd)) { char *wd = getcwd(nullptr, 0); if (wd == nullptr) { error.SetErrorStringWithFormat( "cwd does not exist; cannot launch with shell argument expansion"); return error; } else { - FileSpec working_dir(wd, false); + FileSpec working_dir(wd); free(wd); launch_info.SetWorkingDirectory(working_dir); } diff --git a/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/source/Host/macosx/objcxx/HostInfoMacOSX.mm index a39d26aa31ae..165e87e8bed4 100644 --- a/source/Host/macosx/objcxx/HostInfoMacOSX.mm +++ b/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostInfo.h" #include "lldb/Host/macosx/HostInfoMacOSX.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/SafeMachO.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" @@ -97,14 +97,13 @@ FileSpec HostInfoMacOSX::GetProgramFileSpec() { uint32_t len = sizeof(program_fullpath); int err = _NSGetExecutablePath(program_fullpath, &len); if (err == 0) - g_program_filespec.SetFile(program_fullpath, false, - FileSpec::Style::native); + g_program_filespec.SetFile(program_fullpath, FileSpec::Style::native); else if (err == -1) { char *large_program_fullpath = (char *)::malloc(len + 1); err = _NSGetExecutablePath(large_program_fullpath, &len); if (err == 0) - g_program_filespec.SetFile(large_program_fullpath, false, + g_program_filespec.SetFile(large_program_fullpath, FileSpec::Style::native); ::free(large_program_fullpath); @@ -140,8 +139,9 @@ bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) { // as in the case of a python script, the executable is python, not // the lldb driver. raw_path.append("/../bin"); - FileSpec support_dir_spec(raw_path, true); - if (!llvm::sys::fs::is_directory(support_dir_spec.GetPath())) { + FileSpec support_dir_spec(raw_path); + FileSystem::Instance().Resolve(support_dir_spec); + if (!FileSystem::Instance().IsDirectory(support_dir_spec)) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoMacOSX::%s(): failed to find support directory", @@ -204,7 +204,8 @@ bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) { } bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) { - FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true); + FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns"); + FileSystem::Instance().Resolve(temp_file); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; } @@ -254,6 +255,9 @@ void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32, #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 arch_32.GetTriple().setOS(llvm::Triple::TvOS); arch_64.GetTriple().setOS(llvm::Triple::TvOS); +#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 + arch_32.GetTriple().setOS(llvm::Triple::BridgeOS); + arch_64.GetTriple().setOS(llvm::Triple::BridgeOS); #else arch_32.GetTriple().setOS(llvm::Triple::IOS); arch_64.GetTriple().setOS(llvm::Triple::IOS); diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp index bfd5a74ffcc2..4d50363c72e0 100644 --- a/source/Host/netbsd/Host.cpp +++ b/source/Host/netbsd/Host.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <dlfcn.h> #include <execinfo.h> #include <stdio.h> @@ -22,9 +21,6 @@ #include <sys/exec.h> #include <sys/ptrace.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" @@ -70,7 +66,7 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, if (!cstr) return false; - process_info.GetExecutableFile().SetFile(cstr, false, + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp index dfbce310509d..a54483fcc55b 100644 --- a/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/source/Host/netbsd/HostInfoNetBSD.cpp @@ -85,7 +85,7 @@ FileSpec HostInfoNetBSD::GetProgramFileSpec() { len = sizeof(path); if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1) { - g_program_filespec.SetFile(path, false, FileSpec::Style::native); + g_program_filespec.SetFile(path, FileSpec::Style::native); } } return g_program_filespec; diff --git a/source/Host/openbsd/Host.cpp b/source/Host/openbsd/Host.cpp index 49e9c290a027..cba1f4ee6b7c 100644 --- a/source/Host/openbsd/Host.cpp +++ b/source/Host/openbsd/Host.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <sys/types.h> #include <sys/signal.h> @@ -19,9 +18,6 @@ #include <stdio.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index c21bb786a896..deac3844d4a2 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -21,7 +21,6 @@ #include "lldb/Utility/SelectHelper.h" #include "lldb/Utility/Timeout.h" -// C Includes #include <errno.h> #include <fcntl.h> #include <stdlib.h> @@ -33,16 +32,13 @@ #include <unistd.h> #endif -// C++ Includes #include <sstream> -// Other libraries and framework includes #include "llvm/Support/Errno.h" #include "llvm/Support/ErrorHandling.h" #if defined(__APPLE__) #include "llvm/ADT/SmallVector.h" #endif -// Project includes #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" #include "lldb/Host/common/TCPSocket.h" diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp index 60be642df608..d7045ff99919 100644 --- a/source/Host/posix/FileSystem.cpp +++ b/source/Host/posix/FileSystem.cpp @@ -11,6 +11,7 @@ // C includes #include <dirent.h> +#include <fcntl.h> #include <sys/mount.h> #include <sys/param.h> #include <sys/stat.h> @@ -47,7 +48,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { error.SetErrorToErrno(); else { buf[count] = '\0'; // Success - dst.SetFile(buf, false, FileSpec::Style::native); + dst.SetFile(buf, FileSpec::Style::native); } return error; } @@ -65,7 +66,7 @@ Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { return err; } - dst = FileSpec(real_path, false); + dst = FileSpec(real_path); return Status(); } @@ -73,3 +74,7 @@ Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { FILE *FileSystem::Fopen(const char *path, const char *mode) { return ::fopen(path, mode); } + +int FileSystem::Open(const char *path, int flags, int mode) { + return ::open(path, flags, mode); +} diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index 62c70fa3edc1..4763ebc9b9d4 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -119,7 +119,7 @@ uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); } uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } -FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh", false); } +FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh"); } bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec, llvm::StringRef dir) { @@ -163,7 +163,7 @@ bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { } bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) { - FileSpec temp_file("/opt/local/include/lldb", false); + FileSpec temp_file("/opt/local/include/lldb"); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; } diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp index 3c5273f4bd3f..f431e0c72de1 100644 --- a/source/Host/posix/HostProcessPosix.cpp +++ b/source/Host/posix/HostProcessPosix.cpp @@ -62,7 +62,7 @@ Status HostProcessPosix::GetMainModule(FileSpec &file_spec) const { return error; } - error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec); + error = FileSystem::Instance().Readlink(FileSpec(link_path), file_spec); if (!error.Success()) return error; diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index b321cad64275..866a9897ee43 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -61,12 +61,13 @@ bool SetCloexecFlag(int fd) { std::chrono::time_point<std::chrono::steady_clock> Now() { return std::chrono::steady_clock::now(); } -} +} // namespace PipePosix::PipePosix() : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {} -PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {} +PipePosix::PipePosix(lldb::pipe_t read, lldb::pipe_t write) + : m_fds{read, write} {} PipePosix::PipePosix(PipePosix &&pipe_posix) : PipeBase{std::move(pipe_posix)}, @@ -125,8 +126,8 @@ Status PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char> &name) { - llvm::SmallString<PATH_MAX> named_pipe_path; - llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); + llvm::SmallString<128> named_pipe_path; + llvm::SmallString<128> pipe_spec((prefix + ".%%%%%%").str()); FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir(); if (!tmpdir_file_spec) tmpdir_file_spec.AppendPathComponent("/tmp"); diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index 46ce3e3d224f..6bf78463d060 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -157,7 +157,7 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, #if defined(__linux__) if (errno == ETXTBSY) { - // On android M and earlier we can get this error because the adb deamon + // On android M and earlier we can get this error because the adb daemon // can hold a write handle on the executable even after it has finished // uploading it. This state lasts only a short time and happens only when // there are many concurrent adb commands being issued, such as when diff --git a/source/Host/windows/FileSystem.cpp b/source/Host/windows/FileSystem.cpp index 9309b89f2baf..3217cdc8480a 100644 --- a/source/Host/windows/FileSystem.cpp +++ b/source/Host/windows/FileSystem.cpp @@ -75,7 +75,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { else if (!llvm::convertWideToUTF8(buf.data(), path)) error.SetErrorString(PATH_CONVERSION_ERROR); else - dst.SetFile(path, false, FileSpec::Style::native); + dst.SetFile(path, FileSpec::Style::native); ::CloseHandle(h); return error; @@ -96,3 +96,12 @@ FILE *FileSystem::Fopen(const char *path, const char *mode) { return nullptr; return file; } + +int FileSystem::Open(const char *path, int flags, int mode) { + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return -1; + int result; + ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode); + return result; +} diff --git a/source/Host/windows/Host.cpp b/source/Host/windows/Host.cpp index cc6c454d36b1..3ac16a42286a 100644 --- a/source/Host/windows/Host.cpp +++ b/source/Host/windows/Host.cpp @@ -7,14 +7,11 @@ // //===----------------------------------------------------------------------===// -// C Includes #include "lldb/Host/windows/AutoHandle.h" #include "lldb/Host/windows/windows.h" #include <stdio.h> -// C++ Includes -// Other libraries and framework includes -// Project includes +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" @@ -36,8 +33,9 @@ namespace { bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) { // Open the PE File as a binary file, and parse just enough information to // determine the machine type. - File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead, - lldb::eFilePermissionsUserRead); + File imageBinary; + FileSystem::Instance().Open(imageBinary, executable, File::eOpenOptionRead, + lldb::eFilePermissionsUserRead); imageBinary.SeekFromStart(0x3c); int32_t peOffset = 0; uint32_t peHead = 0; @@ -83,7 +81,7 @@ void GetProcessExecutableAndTriple(const AutoHandle &handle, triple.setOS(llvm::Triple::Win32); triple.setArch(llvm::Triple::UnknownArch); if (GetExecutableForProcess(handle, executable)) { - FileSpec executableFile(executable.c_str(), false); + FileSpec executableFile(executable.c_str()); process.SetExecutableFile(executableFile, true); GetTripleForProcess(executableFile, triple); } @@ -122,7 +120,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { std::string path; if (!llvm::convertWideToUTF8(buffer.data(), path)) return module_filespec; - module_filespec.SetFile(path, false, FileSpec::Style::native); + module_filespec.SetFile(path, FileSpec::Style::native); return module_filespec; } @@ -145,7 +143,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfo process; std::string exeFile; llvm::convertWideToUTF8(pe.szExeFile, exeFile); - process.SetExecutableFile(FileSpec(exeFile, false), true); + process.SetExecutableFile(FileSpec(exeFile), true); process.SetProcessID(pe.th32ProcessID); process.SetParentProcessID(pe.th32ParentProcessID); GetProcessExecutableAndTriple(handle, process); @@ -189,7 +187,7 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { return error; } expand_tool_spec.AppendPathComponent("lldb-argdumper.exe"); - if (!expand_tool_spec.Exists()) { + if (!FileSystem::Instance().Exists(expand_tool_spec)) { error.SetErrorString("could not find the lldb-argdumper tool"); return error; } diff --git a/source/Host/windows/HostInfoWindows.cpp b/source/Host/windows/HostInfoWindows.cpp index bd3f74f2e2f3..81392d9a85b3 100644 --- a/source/Host/windows/HostInfoWindows.cpp +++ b/source/Host/windows/HostInfoWindows.cpp @@ -11,7 +11,7 @@ #include <objbase.h> -#include <mutex> // std::once +#include <mutex> #include "lldb/Host/windows/HostInfoWindows.h" #include "lldb/Host/windows/PosixApi.h" @@ -92,7 +92,7 @@ FileSpec HostInfoWindows::GetProgramFileSpec() { ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); std::string path; llvm::convertWideToUTF8(buffer.data(), path); - m_program_filespec.SetFile(path, false, FileSpec::Style::native); + m_program_filespec.SetFile(path, FileSpec::Style::native); }); return m_program_filespec; } @@ -103,9 +103,9 @@ FileSpec HostInfoWindows::GetDefaultShell() { std::string shell; if (GetEnvironmentVar("ComSpec", shell)) - return FileSpec(shell, false); + return FileSpec(shell); - return FileSpec("C:\\Windows\\system32\\cmd.exe", false); + return FileSpec("C:\\Windows\\system32\\cmd.exe"); } bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name, diff --git a/source/Host/windows/HostProcessWindows.cpp b/source/Host/windows/HostProcessWindows.cpp index ce75c14cdcf4..701167ff6fea 100644 --- a/source/Host/windows/HostProcessWindows.cpp +++ b/source/Host/windows/HostProcessWindows.cpp @@ -57,7 +57,7 @@ Status HostProcessWindows::GetMainModule(FileSpec &file_spec) const { if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) { std::string path; if (llvm::convertWideToUTF8(wpath.data(), path)) - file_spec.SetFile(path, false, FileSpec::Style::native); + file_spec.SetFile(path, FileSpec::Style::native); else error.SetErrorString("Error converting path to UTF-8"); } else diff --git a/source/Host/windows/HostThreadWindows.cpp b/source/Host/windows/HostThreadWindows.cpp index 3d603ff61663..b516230e7fa4 100644 --- a/source/Host/windows/HostThreadWindows.cpp +++ b/source/Host/windows/HostThreadWindows.cpp @@ -69,3 +69,7 @@ void HostThreadWindows::Reset() { HostNativeThreadBase::Reset(); } + +bool HostThreadWindows::EqualsThread(lldb::thread_t thread) const { + return GetThreadId() == ::GetThreadId(thread); +} diff --git a/source/Host/windows/PipeWindows.cpp b/source/Host/windows/PipeWindows.cpp index 1951c9ca193a..57221a72899c 100644 --- a/source/Host/windows/PipeWindows.cpp +++ b/source/Host/windows/PipeWindows.cpp @@ -25,14 +25,41 @@ using namespace lldb_private; namespace { std::atomic<uint32_t> g_pipe_serial(0); +constexpr llvm::StringLiteral g_pipe_name_prefix = "\\\\.\\Pipe\\"; +} // namespace + +PipeWindows::PipeWindows() + : m_read(INVALID_HANDLE_VALUE), m_write(INVALID_HANDLE_VALUE), + m_read_fd(PipeWindows::kInvalidDescriptor), + m_write_fd(PipeWindows::kInvalidDescriptor) { + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } -PipeWindows::PipeWindows() { - m_read = INVALID_HANDLE_VALUE; - m_write = INVALID_HANDLE_VALUE; +PipeWindows::PipeWindows(pipe_t read, pipe_t write) + : m_read((HANDLE)read), m_write((HANDLE)write), + m_read_fd(PipeWindows::kInvalidDescriptor), + m_write_fd(PipeWindows::kInvalidDescriptor) { + assert(read != LLDB_INVALID_PIPE || write != LLDB_INVALID_PIPE); + + // Don't risk in passing file descriptors and getting handles from them by + // _get_osfhandle since the retrieved handles are highly likely unrecognized + // in the current process and usually crashes the program. Pass handles + // instead since the handle can be inherited. + + if (read != LLDB_INVALID_PIPE) { + m_read_fd = _open_osfhandle((intptr_t)read, _O_RDONLY); + // Make sure the fd and native handle are consistent. + if (m_read_fd < 0) + m_read = INVALID_HANDLE_VALUE; + } + + if (write != LLDB_INVALID_PIPE) { + m_write_fd = _open_osfhandle((intptr_t)write, _O_WRONLY); + if (m_write_fd < 0) + m_write = INVALID_HANDLE_VALUE; + } - m_read_fd = -1; - m_write_fd = -1; ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } @@ -40,6 +67,24 @@ PipeWindows::PipeWindows() { PipeWindows::~PipeWindows() { Close(); } Status PipeWindows::CreateNew(bool child_process_inherit) { + // Create an anonymous pipe with the specified inheritance. + SECURITY_ATTRIBUTES sa{sizeof(SECURITY_ATTRIBUTES), 0, + child_process_inherit ? TRUE : FALSE}; + BOOL result = ::CreatePipe(&m_read, &m_write, &sa, 1024); + if (result == FALSE) + return Status(::GetLastError(), eErrorTypeWin32); + + m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + m_read_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr); + + m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + + return Status(); +} + +Status PipeWindows::CreateNewNamed(bool child_process_inherit) { // Even for anonymous pipes, we open a named pipe. This is because you // cannot get overlapped i/o on Windows without using a named pipe. So we // synthesize a unique name. @@ -60,7 +105,7 @@ Status PipeWindows::CreateNew(llvm::StringRef name, if (CanRead() || CanWrite()) return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - std::string pipe_path = "\\\\.\\Pipe\\"; + std::string pipe_path = g_pipe_name_prefix; pipe_path.append(name); // Always open for overlapped i/o. We implement blocking manually in Read @@ -75,7 +120,8 @@ Status PipeWindows::CreateNew(llvm::StringRef name, ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - // Open the write end of the pipe. + // Open the write end of the pipe. Note that closing either the read or + // write end of the pipe could directly close the pipe itself. Status result = OpenNamedPipe(name, child_process_inherit, false); if (!result.Success()) { CloseReadFileDescriptor(); @@ -111,7 +157,7 @@ Status PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, Status PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit) { - if (CanRead() || CanWrite()) + if (CanRead()) return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32); return OpenNamedPipe(name, child_process_inherit, true); @@ -121,7 +167,7 @@ Status PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) { - if (CanRead() || CanWrite()) + if (CanWrite()) return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32); return OpenNamedPipe(name, child_process_inherit, false); @@ -137,7 +183,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name, SECURITY_ATTRIBUTES attributes = {}; attributes.bInheritHandle = child_process_inherit; - std::string pipe_path = "\\\\.\\Pipe\\"; + std::string pipe_path = g_pipe_name_prefix; pipe_path.append(name); if (is_read) { @@ -170,9 +216,9 @@ int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; } int PipeWindows::ReleaseReadFileDescriptor() { if (!CanRead()) - return -1; + return PipeWindows::kInvalidDescriptor; int result = m_read_fd; - m_read_fd = -1; + m_read_fd = PipeWindows::kInvalidDescriptor; if (m_read_overlapped.hEvent) ::CloseHandle(m_read_overlapped.hEvent); m_read = INVALID_HANDLE_VALUE; @@ -182,9 +228,9 @@ int PipeWindows::ReleaseReadFileDescriptor() { int PipeWindows::ReleaseWriteFileDescriptor() { if (!CanWrite()) - return -1; + return PipeWindows::kInvalidDescriptor; int result = m_write_fd; - m_write_fd = -1; + m_write_fd = PipeWindows::kInvalidDescriptor; m_write = INVALID_HANDLE_VALUE; ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); return result; @@ -196,9 +242,10 @@ void PipeWindows::CloseReadFileDescriptor() { if (m_read_overlapped.hEvent) ::CloseHandle(m_read_overlapped.hEvent); + _close(m_read_fd); m_read = INVALID_HANDLE_VALUE; - m_read_fd = -1; + m_read_fd = PipeWindows::kInvalidDescriptor; ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); } @@ -208,7 +255,7 @@ void PipeWindows::CloseWriteFileDescriptor() { _close(m_write_fd); m_write = INVALID_HANDLE_VALUE; - m_write_fd = -1; + m_write_fd = PipeWindows::kInvalidDescriptor; ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } diff --git a/source/Host/windows/ProcessLauncherWindows.cpp b/source/Host/windows/ProcessLauncherWindows.cpp index 553dd9d286da..a186c7177fdf 100644 --- a/source/Host/windows/ProcessLauncherWindows.cpp +++ b/source/Host/windows/ProcessLauncherWindows.cpp @@ -76,6 +76,9 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, if (launch_info.GetFlags().Test(eLaunchFlagDebug)) flags |= DEBUG_ONLY_THIS_PROCESS; + if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO)) + flags &= ~CREATE_NEW_CONSOLE; + LPVOID env_block = nullptr; ::CreateEnvironmentBuffer(launch_info.GetEnvironment(), environment); if (!environment.empty()) |