diff options
Diffstat (limited to 'source/Host')
60 files changed, 1561 insertions, 3219 deletions
diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index 0e4a8a533e5f..f00d67420fa3 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -6,7 +6,6 @@ endmacro()  add_host_subdirectory(common    common/File.cpp    common/FileCache.cpp -  common/FileSpec.cpp    common/FileSystem.cpp    common/GetOptInc.cpp    common/Host.cpp @@ -22,11 +21,11 @@ add_host_subdirectory(common    common/NativeWatchpointList.cpp    common/NativeProcessProtocol.cpp    common/NativeRegisterContext.cpp -  common/NativeRegisterContextRegisterInfo.cpp    common/NativeThreadProtocol.cpp    common/OptionParser.cpp    common/PipeBase.cpp    common/ProcessRunLock.cpp +  common/PseudoTerminal.cpp    common/Socket.cpp    common/SocketAddress.cpp    common/SoftwareBreakpoint.cpp @@ -34,7 +33,6 @@ add_host_subdirectory(common    common/Symbols.cpp    common/TCPSocket.cpp    common/Terminal.cpp -  common/ThisThread.cpp    common/ThreadLauncher.cpp    common/XML.cpp    common/UDPSocket.cpp @@ -55,6 +53,10 @@ add_host_subdirectory(posix    posix/ConnectionFileDescriptorPosix.cpp    ) +if(NOT LLDB_DISABLE_PYTHON) +  list(APPEND LLDB_PLUGINS lldbPluginScriptInterpreterPython) +endif() +  if (CMAKE_SYSTEM_NAME MATCHES "Windows")    add_host_subdirectory(windows      windows/ConnectionGenericFileWindows.cpp @@ -68,7 +70,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")      windows/PipeWindows.cpp      windows/ProcessLauncherWindows.cpp      windows/ProcessRunLock.cpp -    windows/ThisThread.cpp      windows/Windows.cpp      )  else() @@ -86,9 +87,10 @@ else()      posix/LockFilePosix.cpp      posix/MainLoopPosix.cpp      posix/PipePosix.cpp +    posix/ProcessLauncherPosixFork.cpp      ) -  if (NOT __ANDROID_NDK__) +  if (NOT (CMAKE_SYSTEM_NAME MATCHES "Android"))      add_host_subdirectory(posix        posix/ProcessLauncherPosix.cpp        ) @@ -101,7 +103,6 @@ else()        macosx/HostInfoMacOSX.mm        macosx/HostThreadMacOSX.mm        macosx/Symbols.cpp -      macosx/ThisThread.cpp        macosx/cfcpp/CFCBundle.cpp        macosx/cfcpp/CFCData.cpp        macosx/cfcpp/CFCMutableArray.cpp @@ -110,37 +111,37 @@ else()        macosx/cfcpp/CFCString.cpp        ) -  elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") -    if (__ANDROID_NDK__) -      add_host_subdirectory(android -        android/HostInfoAndroid.cpp -        android/LibcGlue.cpp -        ) -    endif() + +  elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Android")      add_host_subdirectory(linux        linux/AbstractSocket.cpp        linux/Host.cpp        linux/HostInfoLinux.cpp -      linux/HostThreadLinux.cpp        linux/LibcGlue.cpp -      linux/ProcessLauncherLinux.cpp -      linux/ThisThread.cpp +      linux/Support.cpp        ) - +    if (CMAKE_SYSTEM_NAME MATCHES "Android") +      add_host_subdirectory(android +        android/HostInfoAndroid.cpp +        android/LibcGlue.cpp +        ) +    endif()    elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")      add_host_subdirectory(freebsd        freebsd/Host.cpp        freebsd/HostInfoFreeBSD.cpp -      freebsd/HostThreadFreeBSD.cpp -      freebsd/ThisThread.cpp        )    elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")      add_host_subdirectory(netbsd        netbsd/Host.cpp        netbsd/HostInfoNetBSD.cpp -      netbsd/HostThreadNetBSD.cpp -      netbsd/ThisThread.cpp +      ) + +  elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") +    add_host_subdirectory(openbsd +      openbsd/Host.cpp +      openbsd/HostInfoOpenBSD.cpp        )    endif()  endif() @@ -158,8 +159,22 @@ if (${get_python_libdir})    endif()  endif() -add_lldb_library(lldbHost ${HOST_SOURCES}) -  if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") -target_link_libraries(lldbHost kvm) + set(EXTRA_LIBS kvm)  endif () + +add_lldb_library(lldbHost +  ${HOST_SOURCES} +   +  LINK_LIBS +    lldbCore +    lldbInterpreter +    lldbSymbol +    lldbTarget +    lldbUtility +    ${LLDB_PLUGINS} +    ${EXTRA_LIBS} +   +  LINK_COMPONENTS +    Support +  ) diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index 1c5c0ffe902b..b157cdb7c110 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -11,16 +11,19 @@  #include <iostream>  #include <limits.h> -#include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/StringList.h"  #include "lldb/Host/ConnectionFileDescriptor.h"  #include "lldb/Host/Editline.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/FileSpec.h"  #include "lldb/Utility/LLDBAssert.h"  #include "lldb/Utility/SelectHelper.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StringList.h" +#include "lldb/Utility/Timeout.h" + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h"  using namespace lldb_private;  using namespace lldb_private::line_editor; @@ -176,9 +179,7 @@ private:      if (m_path.empty() && m_history && !m_prefix.empty()) {        FileSpec parent_path{"~/.lldb", true};        char history_path[PATH_MAX]; -      if (FileSystem::MakeDirectory(parent_path, -                                    lldb::eFilePermissionsDirectoryDefault) -              .Success()) { +      if (!llvm::sys::fs::create_directory(parent_path.GetPath())) {          snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history",                   m_prefix.c_str());        } else { @@ -1151,8 +1152,8 @@ Editline::Editline(const char *editline_name, FILE *input_file,      if (term_fd != -1) {        static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr;        static std::set<int> *g_init_terminal_fds_ptr = nullptr; -      static std::once_flag g_once_flag; -      std::call_once(g_once_flag, [&]() { +      static llvm::once_flag g_once_flag; +      llvm::call_once(g_once_flag, [&]() {          g_init_terminal_fds_mutex_ptr =              new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues          g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 4eb9ae15f069..1869a6db49c9 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -19,17 +19,18 @@  #include "lldb/Host/windows/windows.h"  #else  #include <sys/ioctl.h> +#include <sys/stat.h> +#include <termios.h>  #endif  #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/FileSystem.h"  #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/Config.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h"  using namespace lldb;  using namespace lldb_private; @@ -247,14 +248,12 @@ Error File::Open(const char *path, uint32_t options, uint32_t permissions) {  uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) {    if (file_spec) { -    struct stat file_stats; -    int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); -    if (stat_result == -1) -      error.SetErrorToErrno(); -    else { -      error.Clear(); -      return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); -    } +    error.Clear(); +    auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath()); +    if (Perms) +      return *Perms; +    error = Error(Perms.getError()); +    return 0;    } else      error.SetErrorString("empty file spec");    return 0; @@ -308,7 +307,7 @@ void File::Clear() {  Error File::GetFileSpec(FileSpec &file_spec) const {    Error error; -#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED +#ifdef F_GETPATH    if (IsValid()) {      char path[PATH_MAX];      if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp deleted file mode 100644 index 7f46d303a5d8..000000000000 --- a/source/Host/common/FileSpec.cpp +++ /dev/null @@ -1,1431 +0,0 @@ -//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef _WIN32 -#include <dirent.h> -#else -#include "lldb/Host/windows/windows.h" -#endif -#include <fcntl.h> -#ifndef _MSC_VER -#include <libgen.h> -#endif -#include <fstream> -#include <set> -#include <string.h> - -#include "lldb/Host/Config.h" // Have to include this before we test the define... -#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER -#include <pwd.h> -#endif - -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataBufferMemoryMap.h" -#include "lldb/Core/RegularExpression.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/File.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Host.h" -#include "lldb/Utility/CleanUp.h" - -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Program.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { - -bool PathSyntaxIsPosix(FileSpec::PathSyntax syntax) { -  return (syntax == FileSpec::ePathSyntaxPosix || -          (syntax == FileSpec::ePathSyntaxHostNative && -           FileSystem::GetNativePathSyntax() == FileSpec::ePathSyntaxPosix)); -} - -const char *GetPathSeparators(FileSpec::PathSyntax syntax) { -  return PathSyntaxIsPosix(syntax) ? "/" : "\\/"; -} - -char GetPreferredPathSeparator(FileSpec::PathSyntax syntax) { -  return GetPathSeparators(syntax)[0]; -} - -bool IsPathSeparator(char value, FileSpec::PathSyntax syntax) { -  return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\'); -} - -void Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) { -  if (PathSyntaxIsPosix(syntax)) -    return; - -  std::replace(path.begin(), path.end(), '\\', '/'); -  // Windows path can have \\ slashes which can be changed by replace -  // call above to //. Here we remove the duplicate. -  auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) { -    return (c1 == '/' && c2 == '/'); -  }); -  path.erase(iter, path.end()); -} - -void Denormalize(llvm::SmallVectorImpl<char> &path, -                 FileSpec::PathSyntax syntax) { -  if (PathSyntaxIsPosix(syntax)) -    return; - -  std::replace(path.begin(), path.end(), '/', '\\'); -} - -bool GetFileStats(const FileSpec *file_spec, struct stat *stats_ptr) { -  char resolved_path[PATH_MAX]; -  if (file_spec->GetPath(resolved_path, sizeof(resolved_path))) -    return FileSystem::Stat(resolved_path, stats_ptr) == 0; -  return false; -} - -size_t FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) { -  if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) -    return 0; - -  if (str.size() > 0 && IsPathSeparator(str.back(), syntax)) -    return str.size() - 1; - -  size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1); - -  if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos) -    pos = str.find_last_of(':', str.size() - 2); - -  if (pos == llvm::StringRef::npos || -      (pos == 1 && IsPathSeparator(str[0], syntax))) -    return 0; - -  return pos + 1; -} - -size_t RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) { -  // case "c:/" -  if (!PathSyntaxIsPosix(syntax) && -      (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax))) -    return 2; - -  // case "//" -  if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) -    return llvm::StringRef::npos; - -  // case "//net" -  if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] && -      !IsPathSeparator(str[2], syntax)) -    return str.find_first_of(GetPathSeparators(syntax), 2); - -  // case "/" -  if (str.size() > 0 && IsPathSeparator(str[0], syntax)) -    return 0; - -  return llvm::StringRef::npos; -} - -size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) { -  size_t end_pos = FilenamePos(path, syntax); - -  bool filename_was_sep = -      path.size() > 0 && IsPathSeparator(path[end_pos], syntax); - -  // Skip separators except for root dir. -  size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax); - -  while (end_pos > 0 && (end_pos - 1) != root_dir_pos && -         IsPathSeparator(path[end_pos - 1], syntax)) -    --end_pos; - -  if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) -    return llvm::StringRef::npos; - -  return end_pos; -} - -} // end anonymous namespace - -// Resolves the username part of a path of the form ~user/other/directories, and -// writes the result into dst_path.  This will also resolve "~" to the current -// user. -// If you want to complete "~" to the list of users, pass it to -// ResolvePartialUsername. -void FileSpec::ResolveUsername(llvm::SmallVectorImpl<char> &path) { -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER -  if (path.empty() || path[0] != '~') -    return; - -  llvm::StringRef path_str(path.data(), path.size()); -  size_t slash_pos = path_str.find('/', 1); -  if (slash_pos == 1 || path.size() == 1) { -    // A path of ~/ resolves to the current user's home dir -    llvm::SmallString<64> home_dir; -    // llvm::sys::path::home_directory() only checks if "HOME" is set in the -    // environment and does nothing else to locate the user home directory -    if (!llvm::sys::path::home_directory(home_dir)) { -      struct passwd *pw = getpwuid(getuid()); -      if (pw && pw->pw_dir && pw->pw_dir[0]) { -        // Update our environemnt so llvm::sys::path::home_directory() works -        // next time -        setenv("HOME", pw->pw_dir, 0); -        home_dir.assign(llvm::StringRef(pw->pw_dir)); -      } else { -        return; -      } -    } - -    // Overwrite the ~ with the first character of the homedir, and insert -    // the rest.  This way we only trigger one move, whereas an insert -    // followed by a delete (or vice versa) would trigger two. -    path[0] = home_dir[0]; -    path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end()); -    return; -  } - -  auto username_begin = path.begin() + 1; -  auto username_end = (slash_pos == llvm::StringRef::npos) -                          ? path.end() -                          : (path.begin() + slash_pos); -  size_t replacement_length = std::distance(path.begin(), username_end); - -  llvm::SmallString<20> username(username_begin, username_end); -  struct passwd *user_entry = ::getpwnam(username.c_str()); -  if (user_entry != nullptr) { -    // Copy over the first n characters of the path, where n is the smaller of -    // the length -    // of the home directory and the slash pos. -    llvm::StringRef homedir(user_entry->pw_dir); -    size_t initial_copy_length = std::min(homedir.size(), replacement_length); -    auto src_begin = homedir.begin(); -    auto src_end = src_begin + initial_copy_length; -    std::copy(src_begin, src_end, path.begin()); -    if (replacement_length > homedir.size()) { -      // We copied the entire home directory, but the ~username portion of the -      // path was -      // longer, so there's characters that need to be removed. -      path.erase(path.begin() + initial_copy_length, username_end); -    } else if (replacement_length < homedir.size()) { -      // We copied all the way up to the slash in the destination, but there's -      // still more -      // characters that need to be inserted. -      path.insert(username_end, src_end, homedir.end()); -    } -  } else { -    // Unable to resolve username (user doesn't exist?) -    path.clear(); -  } -#endif -} - -size_t FileSpec::ResolvePartialUsername(llvm::StringRef partial_name, -                                        StringList &matches) { -#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER -  size_t extant_entries = matches.GetSize(); - -  setpwent(); -  struct passwd *user_entry; -  partial_name = partial_name.drop_front(); -  std::set<std::string> name_list; - -  while ((user_entry = getpwent()) != NULL) { -    if (llvm::StringRef(user_entry->pw_name).startswith(partial_name)) { -      std::string tmp_buf("~"); -      tmp_buf.append(user_entry->pw_name); -      tmp_buf.push_back('/'); -      name_list.insert(tmp_buf); -    } -  } - -  for (auto &name : name_list) { -    matches.AppendString(name); -  } -  return matches.GetSize() - extant_entries; -#else -  // Resolving home directories is not supported, just copy the path... -  return 0; -#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER -} - -void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) { -  if (path.empty()) -    return; - -#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER -  if (path[0] == '~') -    ResolveUsername(path); -#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - -  // Save a copy of the original path that's passed in -  llvm::SmallString<128> original_path(path.begin(), path.end()); - -  llvm::sys::fs::make_absolute(path); -  if (!llvm::sys::fs::exists(path)) { -    path.clear(); -    path.append(original_path.begin(), original_path.end()); -  } -} - -FileSpec::FileSpec() : m_syntax(FileSystem::GetNativePathSyntax()) {} - -//------------------------------------------------------------------ -// Default constructor that can take an optional full path to a -// file on disk. -//------------------------------------------------------------------ -FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, PathSyntax syntax) -    : m_syntax(syntax) { -  SetFile(path, resolve_path, syntax); -} - -FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, ArchSpec arch) -    : FileSpec{path, resolve_path, arch.GetTriple().isOSWindows() -                                       ? ePathSyntaxWindows -                                       : ePathSyntaxPosix} {} - -//------------------------------------------------------------------ -// Copy constructor -//------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec &rhs) -    : m_directory(rhs.m_directory), m_filename(rhs.m_filename), -      m_is_resolved(rhs.m_is_resolved), m_syntax(rhs.m_syntax) {} - -//------------------------------------------------------------------ -// Copy constructor -//------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() { -  if (rhs) -    *this = *rhs; -} - -//------------------------------------------------------------------ -// Virtual destructor in case anyone inherits from this class. -//------------------------------------------------------------------ -FileSpec::~FileSpec() {} - -//------------------------------------------------------------------ -// Assignment operator. -//------------------------------------------------------------------ -const FileSpec &FileSpec::operator=(const FileSpec &rhs) { -  if (this != &rhs) { -    m_directory = rhs.m_directory; -    m_filename = rhs.m_filename; -    m_is_resolved = rhs.m_is_resolved; -    m_syntax = rhs.m_syntax; -  } -  return *this; -} - -//------------------------------------------------------------------ -// Update the contents of this object with a new path. The path will -// be split up into a directory and filename and stored as uniqued -// string values for quick comparison and efficient memory usage. -//------------------------------------------------------------------ -void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, -                       PathSyntax syntax) { -  // CLEANUP: Use StringRef for string handling.  This function is kind of a -  // mess and the unclear semantics of RootDirStart and ParentPathEnd make -  // it very difficult to understand this function.  There's no reason this -  // function should be particularly complicated or difficult to understand. -  m_filename.Clear(); -  m_directory.Clear(); -  m_is_resolved = false; -  m_syntax = (syntax == ePathSyntaxHostNative) -                 ? FileSystem::GetNativePathSyntax() -                 : syntax; - -  if (pathname.empty()) -    return; - -  llvm::SmallString<64> resolved(pathname); - -  if (resolve) { -    FileSpec::Resolve(resolved); -    m_is_resolved = true; -  } - -  Normalize(resolved, m_syntax); - -  llvm::StringRef resolve_path_ref(resolved.c_str()); -  size_t dir_end = ParentPathEnd(resolve_path_ref, m_syntax); -  if (dir_end == 0) { -    m_filename.SetString(resolve_path_ref); -    return; -  } - -  m_directory.SetString(resolve_path_ref.substr(0, dir_end)); - -  size_t filename_begin = dir_end; -  size_t root_dir_start = RootDirStart(resolve_path_ref, m_syntax); -  while (filename_begin != llvm::StringRef::npos && -         filename_begin < resolve_path_ref.size() && -         filename_begin != root_dir_start && -         IsPathSeparator(resolve_path_ref[filename_begin], m_syntax)) -    ++filename_begin; -  m_filename.SetString((filename_begin == llvm::StringRef::npos || -                        filename_begin >= resolve_path_ref.size()) -                           ? "." -                           : resolve_path_ref.substr(filename_begin)); -} - -void FileSpec::SetFile(llvm::StringRef path, bool resolve, ArchSpec arch) { -  return SetFile(path, resolve, arch.GetTriple().isOSWindows() -                                    ? ePathSyntaxWindows -                                    : ePathSyntaxPosix); -} - -//---------------------------------------------------------------------- -// Convert to pointer operator. This allows code to check any FileSpec -// objects to see if they contain anything valid using code such as: -// -//  if (file_spec) -//  {} -//---------------------------------------------------------------------- -FileSpec::operator bool() const { return m_filename || m_directory; } - -//---------------------------------------------------------------------- -// Logical NOT operator. This allows code to check any FileSpec -// objects to see if they are invalid using code such as: -// -//  if (!file_spec) -//  {} -//---------------------------------------------------------------------- -bool FileSpec::operator!() const { return !m_directory && !m_filename; } - -bool FileSpec::DirectoryEquals(const FileSpec &rhs) const { -  const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); -  return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive); -} - -bool FileSpec::FileEquals(const FileSpec &rhs) const { -  const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); -  return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive); -} - -//------------------------------------------------------------------ -// Equal to operator -//------------------------------------------------------------------ -bool FileSpec::operator==(const FileSpec &rhs) const { -  if (!FileEquals(rhs)) -    return false; -  if (DirectoryEquals(rhs)) -    return true; - -  // TODO: determine if we want to keep this code in here. -  // The code below was added to handle a case where we were -  // trying to set a file and line breakpoint and one path -  // was resolved, and the other not and the directory was -  // in a mount point that resolved to a more complete path: -  // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling -  // this out... -  if (IsResolved() && rhs.IsResolved()) { -    // Both paths are resolved, no need to look further... -    return false; -  } - -  FileSpec resolved_lhs(*this); - -  // If "this" isn't resolved, resolve it -  if (!IsResolved()) { -    if (resolved_lhs.ResolvePath()) { -      // This path wasn't resolved but now it is. Check if the resolved -      // directory is the same as our unresolved directory, and if so, -      // we can mark this object as resolved to avoid more future resolves -      m_is_resolved = (m_directory == resolved_lhs.m_directory); -    } else -      return false; -  } - -  FileSpec resolved_rhs(rhs); -  if (!rhs.IsResolved()) { -    if (resolved_rhs.ResolvePath()) { -      // rhs's path wasn't resolved but now it is. Check if the resolved -      // directory is the same as rhs's unresolved directory, and if so, -      // we can mark this object as resolved to avoid more future resolves -      rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory); -    } else -      return false; -  } - -  // If we reach this point in the code we were able to resolve both paths -  // and since we only resolve the paths if the basenames are equal, then -  // we can just check if both directories are equal... -  return DirectoryEquals(rhs); -} - -//------------------------------------------------------------------ -// Not equal to operator -//------------------------------------------------------------------ -bool FileSpec::operator!=(const FileSpec &rhs) const { return !(*this == rhs); } - -//------------------------------------------------------------------ -// Less than operator -//------------------------------------------------------------------ -bool FileSpec::operator<(const FileSpec &rhs) const { -  return FileSpec::Compare(*this, rhs, true) < 0; -} - -//------------------------------------------------------------------ -// Dump a FileSpec object to a stream -//------------------------------------------------------------------ -Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) { -  f.Dump(&s); -  return s; -} - -//------------------------------------------------------------------ -// Clear this object by releasing both the directory and filename -// string values and making them both the empty string. -//------------------------------------------------------------------ -void FileSpec::Clear() { -  m_directory.Clear(); -  m_filename.Clear(); -} - -//------------------------------------------------------------------ -// Compare two FileSpec objects. If "full" is true, then both -// the directory and the filename must match. If "full" is false, -// then the directory names for "a" and "b" are only compared if -// they are both non-empty. This allows a FileSpec object to only -// contain a filename and it can match FileSpec objects that have -// matching filenames with different paths. -// -// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b" -// and "1" if "a" is greater than "b". -//------------------------------------------------------------------ -int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) { -  int result = 0; - -  // case sensitivity of compare -  const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - -  // If full is true, then we must compare both the directory and filename. - -  // If full is false, then if either directory is empty, then we match on -  // the basename only, and if both directories have valid values, we still -  // do a full compare. This allows for matching when we just have a filename -  // in one of the FileSpec objects. - -  if (full || (a.m_directory && b.m_directory)) { -    result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive); -    if (result) -      return result; -  } -  return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive); -} - -bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full, -                     bool remove_backups) { -  // case sensitivity of equality test -  const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - -  if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) -    return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive); - -  if (remove_backups == false) -    return a == b; - -  if (a == b) -    return true; - -  return Equal(a.GetNormalizedPath(), b.GetNormalizedPath(), full, false); -} - -FileSpec FileSpec::GetNormalizedPath() const { -  // Fast path. Do nothing if the path is not interesting. -  if (!m_directory.GetStringRef().contains(".") && -      !m_directory.GetStringRef().contains("//") && -      m_filename.GetStringRef() != ".." && m_filename.GetStringRef() != ".") -    return *this; - -  llvm::SmallString<64> path, result; -  const bool normalize = false; -  GetPath(path, normalize); -  llvm::StringRef rest(path); - -  // We will not go below root dir. -  size_t root_dir_start = RootDirStart(path, m_syntax); -  const bool absolute = root_dir_start != llvm::StringRef::npos; -  if (absolute) { -    result += rest.take_front(root_dir_start + 1); -    rest = rest.drop_front(root_dir_start + 1); -  } else { -    if (m_syntax == ePathSyntaxWindows && path.size() > 2 && path[1] == ':') { -      result += rest.take_front(2); -      rest = rest.drop_front(2); -    } -  } - -  bool anything_added = false; -  llvm::SmallVector<llvm::StringRef, 0> components, processed; -  rest.split(components, '/', -1, false); -  processed.reserve(components.size()); -  for (auto component : components) { -    if (component == ".") -      continue; // Skip these. -    if (component != "..") { -      processed.push_back(component); -      continue; // Regular file name. -    } -    if (!processed.empty()) { -      processed.pop_back(); -      continue; // Dots. Go one level up if we can. -    } -    if (absolute) -      continue; // We're at the top level. Cannot go higher than that. Skip. - -    result += component; // We're a relative path. We need to keep these. -    result += '/'; -    anything_added = true; -  } -  for (auto component : processed) { -    result += component; -    result += '/'; -    anything_added = true; -  } -  if (anything_added) -    result.pop_back(); // Pop last '/'. -  else if (result.empty()) -    result = "."; - -  return FileSpec(result, false, m_syntax); -} - -//------------------------------------------------------------------ -// Dump the object to the supplied stream. If the object contains -// a valid directory name, it will be displayed followed by a -// directory delimiter, and the filename. -//------------------------------------------------------------------ -void FileSpec::Dump(Stream *s) const { -  if (s) { -    std::string path{GetPath(true)}; -    s->PutCString(path); -    char path_separator = GetPreferredPathSeparator(m_syntax); -    if (!m_filename && !path.empty() && path.back() != path_separator) -      s->PutChar(path_separator); -  } -} - -//------------------------------------------------------------------ -// Returns true if the file exists. -//------------------------------------------------------------------ -bool FileSpec::Exists() const { -  struct stat file_stats; -  return GetFileStats(this, &file_stats); -} - -bool FileSpec::Readable() const { -  const uint32_t permissions = GetPermissions(); -  if (permissions & eFilePermissionsEveryoneR) -    return true; -  return false; -} - -bool FileSpec::ResolveExecutableLocation() { -  // CLEANUP: Use StringRef for string handling. -  if (!m_directory) { -    const char *file_cstr = m_filename.GetCString(); -    if (file_cstr) { -      const std::string file_str(file_cstr); -      llvm::ErrorOr<std::string> error_or_path = -          llvm::sys::findProgramByName(file_str); -      if (!error_or_path) -        return false; -      std::string path = error_or_path.get(); -      llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); -      if (!dir_ref.empty()) { -        // FindProgramByName returns "." if it can't find the file. -        if (strcmp(".", dir_ref.data()) == 0) -          return false; - -        m_directory.SetCString(dir_ref.data()); -        if (Exists()) -          return true; -        else { -          // If FindProgramByName found the file, it returns the directory + -          // filename in its return results. -          // We need to separate them. -          FileSpec tmp_file(dir_ref.data(), false); -          if (tmp_file.Exists()) { -            m_directory = tmp_file.m_directory; -            return true; -          } -        } -      } -    } -  } - -  return false; -} - -bool FileSpec::ResolvePath() { -  if (m_is_resolved) -    return true; // We have already resolved this path - -  char path_buf[PATH_MAX]; -  if (!GetPath(path_buf, PATH_MAX, false)) -    return false; -  // SetFile(...) will set m_is_resolved correctly if it can resolve the path -  SetFile(path_buf, true); -  return m_is_resolved; -} - -uint64_t FileSpec::GetByteSize() const { -  struct stat file_stats; -  if (GetFileStats(this, &file_stats)) -    return file_stats.st_size; -  return 0; -} - -FileSpec::PathSyntax FileSpec::GetPathSyntax() const { return m_syntax; } - -FileSpec::FileType FileSpec::GetFileType() const { -  struct stat file_stats; -  if (GetFileStats(this, &file_stats)) { -    mode_t file_type = file_stats.st_mode & S_IFMT; -    switch (file_type) { -    case S_IFDIR: -      return eFileTypeDirectory; -    case S_IFREG: -      return eFileTypeRegular; -#ifndef _WIN32 -    case S_IFIFO: -      return eFileTypePipe; -    case S_IFSOCK: -      return eFileTypeSocket; -    case S_IFLNK: -      return eFileTypeSymbolicLink; -#endif -    default: -      break; -    } -    return eFileTypeUnknown; -  } -  return eFileTypeInvalid; -} - -bool FileSpec::IsSymbolicLink() const { -  char resolved_path[PATH_MAX]; -  if (!GetPath(resolved_path, sizeof(resolved_path))) -    return false; - -#ifdef _WIN32 -  std::wstring wpath; -  if (!llvm::ConvertUTF8toWide(resolved_path, wpath)) -    return false; -  auto attrs = ::GetFileAttributesW(wpath.c_str()); -  if (attrs == INVALID_FILE_ATTRIBUTES) -    return false; - -  return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); -#else -  struct stat file_stats; -  if (::lstat(resolved_path, &file_stats) != 0) -    return false; - -  return (file_stats.st_mode & S_IFMT) == S_IFLNK; -#endif -} - -uint32_t FileSpec::GetPermissions() const { -  uint32_t file_permissions = 0; -  if (*this) -    FileSystem::GetFilePermissions(*this, file_permissions); -  return file_permissions; -} - -//------------------------------------------------------------------ -// Directory string get accessor. -//------------------------------------------------------------------ -ConstString &FileSpec::GetDirectory() { return m_directory; } - -//------------------------------------------------------------------ -// Directory string const get accessor. -//------------------------------------------------------------------ -const ConstString &FileSpec::GetDirectory() const { return m_directory; } - -//------------------------------------------------------------------ -// Filename string get accessor. -//------------------------------------------------------------------ -ConstString &FileSpec::GetFilename() { return m_filename; } - -//------------------------------------------------------------------ -// Filename string const get accessor. -//------------------------------------------------------------------ -const ConstString &FileSpec::GetFilename() const { return m_filename; } - -//------------------------------------------------------------------ -// Extract the directory and path into a fixed buffer. This is -// needed as the directory and path are stored in separate string -// values. -//------------------------------------------------------------------ -size_t FileSpec::GetPath(char *path, size_t path_max_len, -                         bool denormalize) const { -  if (!path) -    return 0; - -  std::string result = GetPath(denormalize); -  ::snprintf(path, path_max_len, "%s", result.c_str()); -  return std::min(path_max_len - 1, result.length()); -} - -std::string FileSpec::GetPath(bool denormalize) const { -  llvm::SmallString<64> result; -  GetPath(result, denormalize); -  return std::string(result.begin(), result.end()); -} - -const char *FileSpec::GetCString(bool denormalize) const { -  return ConstString{GetPath(denormalize)}.AsCString(NULL); -} - -void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path, -                       bool denormalize) const { -  path.append(m_directory.GetStringRef().begin(), -              m_directory.GetStringRef().end()); -  if (m_directory && m_filename && -      !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) -    path.insert(path.end(), GetPreferredPathSeparator(m_syntax)); -  path.append(m_filename.GetStringRef().begin(), -              m_filename.GetStringRef().end()); -  Normalize(path, m_syntax); -  if (denormalize && !path.empty()) -    Denormalize(path, m_syntax); -} - -ConstString FileSpec::GetFileNameExtension() const { -  if (m_filename) { -    const char *filename = m_filename.GetCString(); -    const char *dot_pos = strrchr(filename, '.'); -    if (dot_pos && dot_pos[1] != '\0') -      return ConstString(dot_pos + 1); -  } -  return ConstString(); -} - -ConstString FileSpec::GetFileNameStrippingExtension() const { -  const char *filename = m_filename.GetCString(); -  if (filename == NULL) -    return ConstString(); - -  const char *dot_pos = strrchr(filename, '.'); -  if (dot_pos == NULL) -    return m_filename; - -  return ConstString(filename, dot_pos - filename); -} - -//------------------------------------------------------------------ -// Returns a shared pointer to a data buffer that contains all or -// part of the contents of a file. The data is memory mapped and -// will lazily page in data from the file as memory is accessed. -// The data that is mapped will start "file_offset" bytes into the -// file, and "file_size" bytes will be mapped. If "file_size" is -// greater than the number of bytes available in the file starting -// at "file_offset", the number of bytes will be appropriately -// truncated. The final number of bytes that get mapped can be -// verified using the DataBuffer::GetByteSize() function. -//------------------------------------------------------------------ -DataBufferSP FileSpec::MemoryMapFileContents(off_t file_offset, -                                             size_t file_size) const { -  DataBufferSP data_sp; -  std::unique_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap()); -  if (mmap_data.get()) { -    const size_t mapped_length = -        mmap_data->MemoryMapFromFileSpec(this, file_offset, file_size); -    if (((file_size == SIZE_MAX) && (mapped_length > 0)) || -        (mapped_length >= file_size)) -      data_sp.reset(mmap_data.release()); -  } -  return data_sp; -} - -DataBufferSP FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, -                                                    size_t file_size) const { -  if (FileSystem::IsLocal(*this)) -    return MemoryMapFileContents(file_offset, file_size); -  else -    return ReadFileContents(file_offset, file_size, NULL); -} - -//------------------------------------------------------------------ -// Return the size in bytes that this object takes in memory. This -// returns the size in bytes of this object, not any shared string -// values it may refer to. -//------------------------------------------------------------------ -size_t FileSpec::MemorySize() const { -  return m_filename.MemorySize() + m_directory.MemorySize(); -} - -size_t FileSpec::ReadFileContents(off_t file_offset, void *dst, size_t dst_len, -                                  Error *error_ptr) const { -  Error error; -  size_t bytes_read = 0; -  char resolved_path[PATH_MAX]; -  if (GetPath(resolved_path, sizeof(resolved_path))) { -    File file; -    error = file.Open(resolved_path, File::eOpenOptionRead); -    if (error.Success()) { -      off_t file_offset_after_seek = file_offset; -      bytes_read = dst_len; -      error = file.Read(dst, bytes_read, file_offset_after_seek); -    } -  } else { -    error.SetErrorString("invalid file specification"); -  } -  if (error_ptr) -    *error_ptr = error; -  return bytes_read; -} - -//------------------------------------------------------------------ -// Returns a shared pointer to a data buffer that contains all or -// part of the contents of a file. The data copies into a heap based -// buffer that lives in the DataBuffer shared pointer object returned. -// The data that is cached will start "file_offset" bytes into the -// file, and "file_size" bytes will be mapped. If "file_size" is -// greater than the number of bytes available in the file starting -// at "file_offset", the number of bytes will be appropriately -// truncated. The final number of bytes that get mapped can be -// verified using the DataBuffer::GetByteSize() function. -//------------------------------------------------------------------ -DataBufferSP FileSpec::ReadFileContents(off_t file_offset, size_t file_size, -                                        Error *error_ptr) const { -  Error error; -  DataBufferSP data_sp; -  char resolved_path[PATH_MAX]; -  if (GetPath(resolved_path, sizeof(resolved_path))) { -    File file; -    error = file.Open(resolved_path, File::eOpenOptionRead); -    if (error.Success()) { -      const bool null_terminate = false; -      error = file.Read(file_size, file_offset, null_terminate, data_sp); -    } -  } else { -    error.SetErrorString("invalid file specification"); -  } -  if (error_ptr) -    *error_ptr = error; -  return data_sp; -} - -DataBufferSP FileSpec::ReadFileContentsAsCString(Error *error_ptr) { -  Error error; -  DataBufferSP data_sp; -  char resolved_path[PATH_MAX]; -  if (GetPath(resolved_path, sizeof(resolved_path))) { -    File file; -    error = file.Open(resolved_path, File::eOpenOptionRead); -    if (error.Success()) { -      off_t offset = 0; -      size_t length = SIZE_MAX; -      const bool null_terminate = true; -      error = file.Read(length, offset, null_terminate, data_sp); -    } -  } else { -    error.SetErrorString("invalid file specification"); -  } -  if (error_ptr) -    *error_ptr = error; -  return data_sp; -} - -size_t FileSpec::ReadFileLines(STLStringArray &lines) { -  lines.clear(); -  char path[PATH_MAX]; -  if (GetPath(path, sizeof(path))) { -    std::ifstream file_stream(path); - -    if (file_stream) { -      std::string line; -      while (getline(file_stream, line)) -        lines.push_back(line); -    } -  } -  return lines.size(); -} - -FileSpec::EnumerateDirectoryResult -FileSpec::ForEachItemInDirectory(llvm::StringRef dir_path, -                                 DirectoryCallback const &callback) { -  if (dir_path.empty()) -    return eEnumerateDirectoryResultNext; - -#ifdef _WIN32 -    std::string szDir(dir_path); -    szDir += "\\*"; - -    std::wstring wszDir; -    if (!llvm::ConvertUTF8toWide(szDir, wszDir)) { -      return eEnumerateDirectoryResultNext; -    } - -    WIN32_FIND_DATAW ffd; -    HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd); - -    if (hFind == INVALID_HANDLE_VALUE) { -      return eEnumerateDirectoryResultNext; -    } - -    do { -      FileSpec::FileType file_type = eFileTypeUnknown; -      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { -        size_t len = wcslen(ffd.cFileName); - -        if (len == 1 && ffd.cFileName[0] == L'.') -          continue; - -        if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.') -          continue; - -        file_type = eFileTypeDirectory; -      } else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { -        file_type = eFileTypeOther; -      } else { -        file_type = eFileTypeRegular; -      } - -      std::string fileName; -      if (!llvm::convertWideToUTF8(ffd.cFileName, fileName)) { -        continue; -      } - -      std::string child_path = llvm::join_items("\\", dir_path, fileName); -      // Don't resolve the file type or path -      FileSpec child_path_spec(child_path.data(), false); - -      EnumerateDirectoryResult result = callback(file_type, child_path_spec); - -      switch (result) { -      case eEnumerateDirectoryResultNext: -        // Enumerate next entry in the current directory. We just -        // exit this switch and will continue enumerating the -        // current directory as we currently are... -        break; - -      case eEnumerateDirectoryResultEnter: // Recurse into the current entry -                                           // if it is a directory or symlink, -                                           // or next if not -        if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == -            eEnumerateDirectoryResultQuit) { -          // The subdirectory returned Quit, which means to -          // stop all directory enumerations at all levels. -          return eEnumerateDirectoryResultQuit; -        } -        break; - -      case eEnumerateDirectoryResultExit: // Exit from the current directory -                                          // at the current level. -        // Exit from this directory level and tell parent to -        // keep enumerating. -        return eEnumerateDirectoryResultNext; - -      case eEnumerateDirectoryResultQuit: // Stop directory enumerations at -                                          // any level -        return eEnumerateDirectoryResultQuit; -      } -    } while (FindNextFileW(hFind, &ffd) != 0); - -    FindClose(hFind); -#else -  std::string dir_string(dir_path); -  lldb_utility::CleanUp<DIR *, int> dir_path_dir(opendir(dir_string.c_str()), -                                                 NULL, closedir); -  if (dir_path_dir.is_valid()) { -    char dir_path_last_char = dir_path.back(); - -    long path_max = fpathconf(dirfd(dir_path_dir.get()), _PC_NAME_MAX); -#if defined(__APPLE_) && defined(__DARWIN_MAXPATHLEN) -      if (path_max < __DARWIN_MAXPATHLEN) -        path_max = __DARWIN_MAXPATHLEN; -#endif -      struct dirent *buf, *dp; -      buf = (struct dirent *)malloc(offsetof(struct dirent, d_name) + path_max + -                                    1); - -      while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp) { -        // Only search directories -        if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) { -          size_t len = strlen(dp->d_name); - -          if (len == 1 && dp->d_name[0] == '.') -            continue; - -          if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') -            continue; -        } - -        FileSpec::FileType file_type = eFileTypeUnknown; - -        switch (dp->d_type) { -        default: -        case DT_UNKNOWN: -          file_type = eFileTypeUnknown; -          break; -        case DT_FIFO: -          file_type = eFileTypePipe; -          break; -        case DT_CHR: -          file_type = eFileTypeOther; -          break; -        case DT_DIR: -          file_type = eFileTypeDirectory; -          break; -        case DT_BLK: -          file_type = eFileTypeOther; -          break; -        case DT_REG: -          file_type = eFileTypeRegular; -          break; -        case DT_LNK: -          file_type = eFileTypeSymbolicLink; -          break; -        case DT_SOCK: -          file_type = eFileTypeSocket; -          break; -#if !defined(__OpenBSD__) -        case DT_WHT: -          file_type = eFileTypeOther; -          break; -#endif -        } - -        std::string child_path; -        // Don't make paths with "/foo//bar", that just confuses everybody. -        if (dir_path_last_char == '/') -          child_path = llvm::join_items("", dir_path, dp->d_name); -        else -          child_path = llvm::join_items('/', dir_path, dp->d_name); - -          // Don't resolve the file type or path -          FileSpec child_path_spec(child_path, false); - -          EnumerateDirectoryResult result = -              callback(file_type, child_path_spec); - -          switch (result) { -          case eEnumerateDirectoryResultNext: -            // Enumerate next entry in the current directory. We just -            // exit this switch and will continue enumerating the -            // current directory as we currently are... -            break; - -          case eEnumerateDirectoryResultEnter: // Recurse into the current entry -                                               // if it is a directory or -                                               // symlink, or next if not -            if (FileSpec::ForEachItemInDirectory(child_path, callback) == -                eEnumerateDirectoryResultQuit) { -              // The subdirectory returned Quit, which means to -              // stop all directory enumerations at all levels. -              if (buf) -                free(buf); -              return eEnumerateDirectoryResultQuit; -            } -            break; - -          case eEnumerateDirectoryResultExit: // Exit from the current directory -                                              // at the current level. -            // Exit from this directory level and tell parent to -            // keep enumerating. -            if (buf) -              free(buf); -            return eEnumerateDirectoryResultNext; - -          case eEnumerateDirectoryResultQuit: // Stop directory enumerations at -                                              // any level -            if (buf) -              free(buf); -            return eEnumerateDirectoryResultQuit; -          } -      } -      if (buf) { -        free(buf); -      } -    } -#endif -  // By default when exiting a directory, we tell the parent enumeration -  // to continue enumerating. -  return eEnumerateDirectoryResultNext; -} - -FileSpec::EnumerateDirectoryResult -FileSpec::EnumerateDirectory(llvm::StringRef dir_path, bool find_directories, -                             bool find_files, bool find_other, -                             EnumerateDirectoryCallbackType callback, -                             void *callback_baton) { -  return ForEachItemInDirectory( -      dir_path, -      [&find_directories, &find_files, &find_other, &callback, -       &callback_baton](FileType file_type, const FileSpec &file_spec) { -        switch (file_type) { -        case FileType::eFileTypeDirectory: -          if (find_directories) -            return callback(callback_baton, file_type, file_spec); -          break; -        case FileType::eFileTypeRegular: -          if (find_files) -            return callback(callback_baton, file_type, file_spec); -          break; -        default: -          if (find_other) -            return callback(callback_baton, file_type, file_spec); -          break; -        } -        return eEnumerateDirectoryResultNext; -      }); -} - -FileSpec -FileSpec::CopyByAppendingPathComponent(llvm::StringRef component) const { -  FileSpec ret = *this; -  ret.AppendPathComponent(component); -  return ret; -} - -FileSpec FileSpec::CopyByRemovingLastPathComponent() const { -  // CLEANUP: Use StringRef for string handling. -  const bool resolve = false; -  if (m_filename.IsEmpty() && m_directory.IsEmpty()) -    return FileSpec("", resolve); -  if (m_directory.IsEmpty()) -    return FileSpec("", resolve); -  if (m_filename.IsEmpty()) { -    const char *dir_cstr = m_directory.GetCString(); -    const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); - -    // check for obvious cases before doing the full thing -    if (!last_slash_ptr) -      return FileSpec("", resolve); -    if (last_slash_ptr == dir_cstr) -      return FileSpec("/", resolve); - -    size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; -    ConstString new_path(dir_cstr, last_slash_pos); -    return FileSpec(new_path.GetCString(), resolve); -  } else -    return FileSpec(m_directory.GetCString(), resolve); -} - -ConstString FileSpec::GetLastPathComponent() const { -  // CLEANUP: Use StringRef for string handling. -  if (m_filename) -    return m_filename; -  if (m_directory) { -    const char *dir_cstr = m_directory.GetCString(); -    const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); -    if (last_slash_ptr == NULL) -      return m_directory; -    if (last_slash_ptr == dir_cstr) { -      if (last_slash_ptr[1] == 0) -        return ConstString(last_slash_ptr); -      else -        return ConstString(last_slash_ptr + 1); -    } -    if (last_slash_ptr[1] != 0) -      return ConstString(last_slash_ptr + 1); -    const char *penultimate_slash_ptr = last_slash_ptr; -    while (*penultimate_slash_ptr) { -      --penultimate_slash_ptr; -      if (penultimate_slash_ptr == dir_cstr) -        break; -      if (*penultimate_slash_ptr == '/') -        break; -    } -    ConstString result(penultimate_slash_ptr + 1, -                       last_slash_ptr - penultimate_slash_ptr); -    return result; -  } -  return ConstString(); -} - -void FileSpec::PrependPathComponent(llvm::StringRef component) { -  if (component.empty()) -    return; - -  const bool resolve = false; -  if (m_filename.IsEmpty() && m_directory.IsEmpty()) { -    SetFile(component, resolve); -    return; -  } - -  char sep = GetPreferredPathSeparator(m_syntax); -  std::string result; -  if (m_filename.IsEmpty()) -    result = llvm::join_items(sep, component, m_directory.GetStringRef()); -  else if (m_directory.IsEmpty()) -    result = llvm::join_items(sep, component, m_filename.GetStringRef()); -  else -    result = llvm::join_items(sep, component, m_directory.GetStringRef(), -                              m_filename.GetStringRef()); - -  SetFile(result, resolve); -} - -void FileSpec::PrependPathComponent(const FileSpec &new_path) { -  return PrependPathComponent(new_path.GetPath(false)); -} - -void FileSpec::AppendPathComponent(llvm::StringRef component) { -  if (component.empty()) -    return; - -  std::string result; -  if (!m_directory.IsEmpty()) { -    result += m_directory.GetStringRef(); -    if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) -      result += GetPreferredPathSeparator(m_syntax); -  } - -  if (!m_filename.IsEmpty()) { -    result += m_filename.GetStringRef(); -    if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) -      result += GetPreferredPathSeparator(m_syntax); -  } - -  component = component.drop_while( -      [this](char c) { return IsPathSeparator(c, m_syntax); }); - -  result += component; - -  SetFile(result, false, m_syntax); -} - -void FileSpec::AppendPathComponent(const FileSpec &new_path) { -  return AppendPathComponent(new_path.GetPath(false)); -} - -void FileSpec::RemoveLastPathComponent() { -  // CLEANUP: Use StringRef for string handling. - -  const bool resolve = false; -  if (m_filename.IsEmpty() && m_directory.IsEmpty()) { -    SetFile("", resolve); -    return; -  } -  if (m_directory.IsEmpty()) { -    SetFile("", resolve); -    return; -  } -  if (m_filename.IsEmpty()) { -    const char *dir_cstr = m_directory.GetCString(); -    const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); - -    // check for obvious cases before doing the full thing -    if (!last_slash_ptr) { -      SetFile("", resolve); -      return; -    } -    if (last_slash_ptr == dir_cstr) { -      SetFile("/", resolve); -      return; -    } -    size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; -    ConstString new_path(dir_cstr, last_slash_pos); -    SetFile(new_path.GetCString(), resolve); -  } else -    SetFile(m_directory.GetCString(), resolve); -} -//------------------------------------------------------------------ -/// Returns true if the filespec represents an implementation source -/// file (files with a ".c", ".cpp", ".m", ".mm" (many more) -/// extension). -/// -/// @return -///     \b true if the filespec represents an implementation source -///     file, \b false otherwise. -//------------------------------------------------------------------ -bool FileSpec::IsSourceImplementationFile() const { -  ConstString extension(GetFileNameExtension()); -  if (!extension) -    return false; - -  static RegularExpression g_source_file_regex(llvm::StringRef( -      "^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[" -      "cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][" -      "rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])" -      "$")); -  return g_source_file_regex.Execute(extension.GetStringRef()); -} - -bool FileSpec::IsRelative() const { -  const char *dir = m_directory.GetCString(); -  llvm::StringRef directory(dir ? dir : ""); - -  if (directory.size() > 0) { -    if (PathSyntaxIsPosix(m_syntax)) { -      // If the path doesn't start with '/' or '~', return true -      switch (directory[0]) { -      case '/': -      case '~': -        return false; -      default: -        return true; -      } -    } else { -      if (directory.size() >= 2 && directory[1] == ':') -        return false; -      if (directory[0] == '/') -        return false; -      return true; -    } -  } else if (m_filename) { -    // No directory, just a basename, return true -    return true; -  } -  return false; -} - -bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); } - -void llvm::format_provider<FileSpec>::format(const FileSpec &F, -                                             raw_ostream &Stream, -                                             StringRef Style) { -  assert( -      (Style.empty() || Style.equals_lower("F") || Style.equals_lower("D")) && -      "Invalid FileSpec style!"); - -  StringRef dir = F.GetDirectory().GetStringRef(); -  StringRef file = F.GetFilename().GetStringRef(); - -  if (dir.empty() && file.empty()) { -    Stream << "(empty)"; -    return; -  } - -  if (Style.equals_lower("F")) { -    Stream << (file.empty() ? "(empty)" : file); -    return; -  } - -  // Style is either D or empty, either way we need to print the directory. -  if (!dir.empty()) { -    // Directory is stored in normalized form, which might be different -    // than preferred form.  In order to handle this, we need to cut off -    // the filename, then denormalize, then write the entire denorm'ed -    // directory. -    llvm::SmallString<64> denormalized_dir = dir; -    Denormalize(denormalized_dir, F.GetPathSyntax()); -    Stream << denormalized_dir; -    Stream << GetPreferredPathSeparator(F.GetPathSyntax()); -  } - -  if (Style.equals_lower("D")) { -    // We only want to print the directory, so now just exit. -    if (dir.empty()) -      Stream << "(empty)"; -    return; -  } - -  if (!file.empty()) -    Stream << file; -} diff --git a/source/Host/common/FileSystem.cpp b/source/Host/common/FileSystem.cpp index 88f29b46f360..4472aece1daa 100644 --- a/source/Host/common/FileSystem.cpp +++ b/source/Host/common/FileSystem.cpp @@ -10,7 +10,6 @@  #include "lldb/Host/FileSystem.h"  #include "llvm/Support/FileSystem.h" -#include "llvm/Support/MD5.h"  #include <algorithm>  #include <fstream> @@ -19,79 +18,6 @@  using namespace lldb;  using namespace lldb_private; -namespace { - -bool CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, -             llvm::MD5::MD5Result &md5_result) { -  llvm::MD5 md5_hash; -  std::ifstream file(file_spec.GetPath(), std::ios::binary); -  if (!file.is_open()) -    return false; - -  if (offset > 0) -    file.seekg(offset, file.beg); - -  std::vector<char> read_buf(4096); -  uint64_t total_read_bytes = 0; -  while (!file.eof()) { -    const uint64_t to_read = -        (length > 0) ? std::min(static_cast<uint64_t>(read_buf.size()), -                                length - total_read_bytes) -                     : read_buf.size(); -    if (to_read == 0) -      break; - -    file.read(&read_buf[0], to_read); -    const auto read_bytes = file.gcount(); -    if (read_bytes == 0) -      break; - -    md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes)); -    total_read_bytes += read_bytes; -  } - -  md5_hash.final(md5_result); -  return true; -} - -} // namespace - -bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, -                              uint64_t &high) { -  return CalculateMD5(file_spec, 0, 0, low, high); -} - -bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset, -                              uint64_t length, uint64_t &low, uint64_t &high) { -  llvm::MD5::MD5Result md5_result; -  if (!CalcMD5(file_spec, offset, length, md5_result)) -    return false; - -  const auto uint64_res = reinterpret_cast<const uint64_t *>(md5_result); -  high = uint64_res[0]; -  low = uint64_res[1]; - -  return true; -} - -bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, -                                      std::string &digest_str) { -  return CalculateMD5AsString(file_spec, 0, 0, digest_str); -} - -bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, -                                      uint64_t offset, uint64_t length, -                                      std::string &digest_str) { -  llvm::MD5::MD5Result md5_result; -  if (!CalcMD5(file_spec, offset, length, md5_result)) -    return false; - -  llvm::SmallString<32> result_str; -  llvm::MD5::stringifyResult(md5_result, result_str); -  digest_str = result_str.c_str(); -  return true; -} -  llvm::sys::TimePoint<>  FileSystem::GetModificationTime(const FileSpec &file_spec) {    llvm::sys::fs::file_status status; diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 6d0ad0175fd8..7754d96ad331 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -28,7 +28,8 @@  #endif  #if defined(__linux__) || defined(__FreeBSD__) ||                              \ -    defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +    defined(__FreeBSD_kernel__) || defined(__APPLE__) ||                       \ +    defined(__NetBSD__) || defined(__OpenBSD__)  #if !defined(__ANDROID__)  #include <spawn.h>  #endif @@ -40,16 +41,16 @@  #include <pthread_np.h>  #endif +#if defined(__NetBSD__) +#include <lwp.h> +#endif +  // C++ Includes  // Other libraries and framework includes  // Project includes  #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/HostProcess.h" @@ -61,14 +62,18 @@  #include "lldb/Target/ProcessLaunchInfo.h"  #include "lldb/Target/UnixSignals.h"  #include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h"  #include "lldb/lldb-private-forward.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Support/FileSystem.h"  #if defined(_WIN32)  #include "lldb/Host/windows/ProcessLauncherWindows.h" -#elif defined(__linux__) -#include "lldb/Host/linux/ProcessLauncherLinux.h" +#elif defined(__linux__) || defined(__NetBSD__) +#include "lldb/Host/posix/ProcessLauncherPosixFork.h"  #else  #include "lldb/Host/posix/ProcessLauncherPosix.h"  #endif @@ -180,7 +185,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) {    delete info;    int status = -1; -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)  #define __WALL 0  #endif    const int options = __WALL; @@ -310,25 +315,6 @@ lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }  #ifndef _WIN32 -lldb::tid_t Host::GetCurrentThreadID() { -#if defined(__APPLE__) -  // Calling "mach_thread_self()" bumps the reference count on the thread -  // port, so we need to deallocate it. mach_task_self() doesn't bump the ref -  // count. -  thread_port_t thread_self = mach_thread_self(); -  mach_port_deallocate(mach_task_self(), thread_self); -  return thread_self; -#elif defined(__FreeBSD__) -  return lldb::tid_t(pthread_getthreadid_np()); -#elif defined(__ANDROID__) -  return lldb::tid_t(gettid()); -#elif defined(__linux__) -  return lldb::tid_t(syscall(SYS_gettid)); -#else -  return lldb::tid_t(pthread_self()); -#endif -} -  lldb::thread_t Host::GetCurrentThread() {    return lldb::thread_t(pthread_self());  } @@ -601,23 +587,22 @@ Error Host::RunShellCommand(const Args &args, const FileSpec &working_dir,              error.SetErrorStringWithFormat(                  "shell command output is too large to fit into a std::string");            } else { -            std::vector<char> command_output(file_size); -            output_file_spec.ReadFileContents(0, command_output.data(), -                                              file_size, &error); +            auto Buffer = +                DataBufferLLVM::CreateFromPath(output_file_spec.GetPath());              if (error.Success()) -              command_output_ptr->assign(command_output.data(), file_size); +              command_output_ptr->assign(Buffer->GetChars(), +                                         Buffer->GetByteSize());            }          }        }      }    } -  if (FileSystem::GetFileExists(output_file_spec)) -    FileSystem::Unlink(output_file_spec); +  llvm::sys::fs::remove(output_file_spec.GetPath());    return error;  } -// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC +// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD, NetBSD and other GLIBC  // systems  #if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) ||        \ @@ -679,10 +664,10 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,    posix_spawnattr_t attr;    error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); -  if (error.Fail() || log) -    error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); -  if (error.Fail()) +  if (error.Fail()) { +    LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error);      return error; +  }    // Make a quick class that will cleanup the posix spawn attributes in case    // we return in the middle of this function. @@ -694,7 +679,7 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,    sigemptyset(&no_signals);    sigfillset(&all_signals);    ::posix_spawnattr_setsigmask(&attr, &no_signals); -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)    ::posix_spawnattr_setsigdefault(&attr, &no_signals);  #else    ::posix_spawnattr_setsigdefault(&attr, &all_signals); @@ -703,11 +688,12 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,    short flags = GetPosixspawnFlags(launch_info);    error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); -  if (error.Fail() || log) -    error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", -                   flags); -  if (error.Fail()) +  if (error.Fail()) { +    LLDB_LOG(log, +             "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )", +             error, flags);      return error; +  }  // posix_spawnattr_setbinpref_np appears to be an Apple extension per:  // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ @@ -734,10 +720,10 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,        size_t ocount = 0;        error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount),                       eErrorTypePOSIX); -      if (error.Fail() || log) -        error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, " -                            "cpu_type = 0x%8.8x, count => %llu )", -                       cpu, (uint64_t)ocount); +      if (error.Fail()) +        LLDB_LOG(log, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, " +                      "cpu_type = {1:x}, count => {2} )", +                 error, cpu, ocount);        if (error.Fail() || ocount != 1)          return error; @@ -788,14 +774,14 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,  #else      if (::getcwd(current_dir, sizeof(current_dir)) == NULL) {        error.SetError(errno, eErrorTypePOSIX); -      error.LogIfError(log, "unable to save the current directory"); +      LLDB_LOG(log, "error: {0}, unable to save the current directory", error);        return error;      }      if (::chdir(working_dir.GetCString()) == -1) {        error.SetError(errno, eErrorTypePOSIX); -      error.LogIfError(log, "unable to change working directory to %s", -                       working_dir.GetCString()); +      LLDB_LOG(log, "error: {0}, unable to change working directory to {1}", +               error, working_dir);        return error;      }  #endif @@ -807,10 +793,12 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,      posix_spawn_file_actions_t file_actions;      error.SetError(::posix_spawn_file_actions_init(&file_actions),                     eErrorTypePOSIX); -    if (error.Fail() || log) -      error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); -    if (error.Fail()) +    if (error.Fail()) { +      LLDB_LOG(log, +               "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )", +               error);        return error; +    }      // Make a quick class that will cleanup the posix spawn attributes in case      // we return in the middle of this function. @@ -832,16 +820,14 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,          ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp),          eErrorTypePOSIX); -    if (error.Fail() || log) { -      error.PutToLog( -          log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, " -               "attr = %p, argv = %p, envp = %p )", -          result_pid, exe_path, static_cast<void *>(&file_actions), -          static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), -          reinterpret_cast<const void *>(envp)); +    if (error.Fail()) { +      LLDB_LOG(log, "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', " +                    "file_actions = {3}, " +                    "attr = {4}, argv = {5}, envp = {6} )", +               error, result_pid, exe_path, &file_actions, &attr, argv, envp);        if (log) {          for (int ii = 0; argv[ii]; ++ii) -          log->Printf("argv[%i] = '%s'", ii, argv[ii]); +          LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]);        }      } @@ -850,16 +836,13 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,          ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp),          eErrorTypePOSIX); -    if (error.Fail() || log) { -      error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', " -                          "file_actions = NULL, attr = %p, argv = %p, envp = " -                          "%p )", -                     result_pid, exe_path, static_cast<void *>(&attr), -                     reinterpret_cast<const void *>(argv), -                     reinterpret_cast<const void *>(envp)); +    if (error.Fail()) { +      LLDB_LOG(log, "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', " +                    "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )", +               error, result_pid, exe_path, &attr, argv, envp);        if (log) {          for (int ii = 0; argv[ii]; ++ii) -          log->Printf("argv[%i] = '%s'", ii, argv[ii]); +          LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]);        }      }    } @@ -872,8 +855,9 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,  #else      if (::chdir(current_dir) == -1 && error.Success()) {        error.SetError(errno, eErrorTypePOSIX); -      error.LogIfError(log, "unable to change current directory back to %s", -                       current_dir); +      LLDB_LOG(log, +               "error: {0}, unable to change current directory back to {1}", +               error, current_dir);      }  #endif    } @@ -902,10 +886,10 @@ bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,        error.SetError(            ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()),            eErrorTypePOSIX); -      if (log && (error.Fail() || log)) -        error.PutToLog(log, -                       "posix_spawn_file_actions_addclose (action=%p, fd=%i)", -                       static_cast<void *>(file_actions), info->GetFD()); +      if (error.Fail()) +        LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_addclose " +                      "(action={1}, fd={2})", +                 error, file_actions, info->GetFD());      }      break; @@ -921,12 +905,10 @@ bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,            ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(),                                               info->GetActionArgument()),            eErrorTypePOSIX); -      if (log && (error.Fail() || log)) -        error.PutToLog( -            log, -            "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", -            static_cast<void *>(file_actions), info->GetFD(), -            info->GetActionArgument()); +      if (error.Fail()) +        LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_adddup2 " +                      "(action={1}, fd={2}, dup_fd={3})", +                 error, file_actions, info->GetFD(), info->GetActionArgument());      }      break; @@ -946,11 +928,11 @@ bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,                           file_actions, info->GetFD(),                           info->GetPath().str().c_str(), oflag, mode),                       eErrorTypePOSIX); -      if (error.Fail() || log) -        error.PutToLog(log, "posix_spawn_file_actions_addopen (action=%p, " -                            "fd=%i, path='%s', oflag=%i, mode=%i)", -                       static_cast<void *>(file_actions), info->GetFD(), -                       info->GetPath().str().c_str(), oflag, mode); +      if (error.Fail()) +        LLDB_LOG( +            log, "error: {0}, posix_spawn_file_actions_addopen (action={1}, " +                 "fd={2}, path='{3}', oflag={4}, mode={5})", +            error, file_actions, info->GetFD(), info->GetPath(), oflag, mode);      }      break;    } @@ -969,8 +951,8 @@ Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) {    std::unique_ptr<ProcessLauncher> delegate_launcher;  #if defined(_WIN32)    delegate_launcher.reset(new ProcessLauncherWindows()); -#elif defined(__linux__) -  delegate_launcher.reset(new ProcessLauncherLinux()); +#elif defined(__linux__) || defined(__NetBSD__) +  delegate_launcher.reset(new ProcessLauncherPosixFork());  #else    delegate_launcher.reset(new ProcessLauncherPosix());  #endif diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index 01ac87047c5d..a6c9e91a98e8 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -10,21 +10,22 @@  #include "lldb/Host/Config.h"  #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/HostInfoBase.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/ADT/Triple.h"  #include "llvm/Support/Host.h"  #include "llvm/Support/Path.h"  #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/Threading.h"  #include "llvm/Support/raw_ostream.h" -#include <mutex> // std::once +#include <mutex>  #include <thread>  using namespace lldb; @@ -45,13 +46,10 @@ struct HostInfoBaseFields {        // Remove the LLDB temporary directory if we have one. Set "recurse" to        // true to all files that were created for the LLDB process can be cleaned        // up. -      FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true); +      llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());      }    } -  uint32_t m_number_cpus; -  std::string m_vendor_string; -  std::string m_os_string;    std::string m_host_triple;    ArchSpec m_host_arch_32; @@ -78,37 +76,9 @@ void HostInfoBase::Terminate() {    g_fields = nullptr;  } -uint32_t HostInfoBase::GetNumberCPUS() { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { -    g_fields->m_number_cpus = std::thread::hardware_concurrency(); -  }); -  return g_fields->m_number_cpus; -} - -uint32_t HostInfoBase::GetMaxThreadNameLength() { return 0; } - -llvm::StringRef HostInfoBase::GetVendorString() { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { -    g_fields->m_vendor_string = -        HostInfo::GetArchitecture().GetTriple().getVendorName().str(); -  }); -  return g_fields->m_vendor_string; -} - -llvm::StringRef HostInfoBase::GetOSString() { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { -    g_fields->m_os_string = -        std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); -  }); -  return g_fields->m_os_string; -} -  llvm::StringRef HostInfoBase::GetTargetTriple() { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { +  static llvm::once_flag g_once_flag; +  llvm::call_once(g_once_flag, []() {      g_fields->m_host_triple =          HostInfo::GetArchitecture().GetTriple().getTriple();    }); @@ -116,8 +86,8 @@ llvm::StringRef HostInfoBase::GetTargetTriple() {  }  const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { +  static llvm::once_flag g_once_flag; +  llvm::call_once(g_once_flag, []() {      HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,                                               g_fields->m_host_arch_64);    }); @@ -144,9 +114,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {    FileSpec *result = nullptr;    switch (type) {    case lldb::ePathTypeLLDBShlibDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success =            HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -158,9 +128,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_so_dir;    } break;    case lldb::ePathTypeSupportExecutableDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeSupportExeDirectory(            g_fields->m_lldb_support_exe_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -173,9 +143,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_support_exe_dir;    } break;    case lldb::ePathTypeHeaderDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);        if (log) @@ -186,9 +156,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_headers_dir;    } break;    case lldb::ePathTypePythonDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);        if (log) @@ -199,9 +169,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_python_dir;    } break;    case lldb::ePathTypeClangDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success =            HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -214,9 +184,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_clang_resource_dir;    } break;    case lldb::ePathTypeLLDBSystemPlugins: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeSystemPluginsDirectory(            g_fields->m_lldb_system_plugin_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -229,9 +199,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_system_plugin_dir;    } break;    case lldb::ePathTypeLLDBUserPlugins: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeUserPluginsDirectory(            g_fields->m_lldb_user_plugin_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -244,9 +214,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_user_plugin_dir;    } break;    case lldb::ePathTypeLLDBTempSystemDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeProcessTempFileDirectory(            g_fields->m_lldb_process_tmp_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -259,9 +229,9 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {        result = &g_fields->m_lldb_process_tmp_dir;    } break;    case lldb::ePathTypeGlobalLLDBTempSystemDir: { -    static std::once_flag g_once_flag; +    static llvm::once_flag g_once_flag;      static bool success = false; -    std::call_once(g_once_flag, []() { +    llvm::call_once(g_once_flag, []() {        success = HostInfo::ComputeGlobalTempFileDirectory(            g_fields->m_lldb_global_tmp_dir);        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -313,9 +283,7 @@ bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {    std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};    temp_file_spec.AppendPathComponent(pid_str); -  if (!FileSystem::MakeDirectory(temp_file_spec, -                                 eFilePermissionsDirectoryDefault) -           .Success()) +  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))      return false;    file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); @@ -337,9 +305,7 @@ bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {      return false;    temp_file_spec.AppendPathComponent("lldb"); -  if (!FileSystem::MakeDirectory(temp_file_spec, -                                 eFilePermissionsDirectoryDefault) -           .Success()) +  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))      return false;    file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp index fd39e0d1e2fe..402d3caacfcb 100644 --- a/source/Host/common/HostNativeThreadBase.cpp +++ b/source/Host/common/HostNativeThreadBase.cpp @@ -8,11 +8,12 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/HostNativeThreadBase.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/HostInfo.h" -#include "lldb/Host/ThisThread.h"  #include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/Log.h" +  #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Threading.h"  using namespace lldb;  using namespace lldb_private; @@ -52,7 +53,7 @@ lldb::thread_result_t  HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) {    ThreadLauncher::HostThreadCreateInfo *info =        (ThreadLauncher::HostThreadCreateInfo *)arg; -  ThisThread::SetName(info->thread_name, HostInfo::GetMaxThreadNameLength()); +  llvm::set_thread_name(info->thread_name);    thread_func_t thread_fptr = info->thread_fptr;    thread_arg_t thread_arg = info->thread_arg; diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp index ae98cc83379d..2aa6c7f50b66 100644 --- a/source/Host/common/MonitoringProcessLauncher.cpp +++ b/source/Host/common/MonitoringProcessLauncher.cpp @@ -8,14 +8,16 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/MonitoringProcessLauncher.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Host/HostProcess.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" + +#include "llvm/Support/FileSystem.h"  using namespace lldb;  using namespace lldb_private; @@ -38,8 +40,9 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,    FileSpec exe_spec(resolved_info.GetExecutableFile()); -  FileSpec::FileType file_type = exe_spec.GetFileType(); -  if (file_type != FileSpec::eFileTypeRegular) { +  llvm::sys::fs::file_status stats; +  status(exe_spec.GetPath(), stats); +  if (!is_regular_file(stats)) {      ModuleSpec module_spec(exe_spec, arch_spec);      lldb::ModuleSP exe_module_sp;      error = @@ -48,11 +51,13 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,      if (error.Fail())        return HostProcess(); -    if (exe_module_sp) +    if (exe_module_sp) {        exe_spec = exe_module_sp->GetFileSpec(); +      status(exe_spec.GetPath(), stats); +    }    } -  if (exe_spec.Exists()) { +  if (exists(stats)) {      exe_spec.GetPath(exe_path, sizeof(exe_path));    } else {      resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp index d61a2f531ac3..8a3ee72179c3 100644 --- a/source/Host/common/NativeBreakpoint.cpp +++ b/source/Host/common/NativeBreakpoint.cpp @@ -9,8 +9,8 @@  #include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h"  #include "lldb/lldb-defines.h"  using namespace lldb_private; diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp index df5bce8079e0..60608a0bbc55 100644 --- a/source/Host/common/NativeBreakpointList.cpp +++ b/source/Host/common/NativeBreakpointList.cpp @@ -9,7 +9,7 @@  #include "lldb/Host/common/NativeBreakpointList.h" -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h"  #include "lldb/Host/common/NativeBreakpoint.h"  #include "lldb/Host/common/SoftwareBreakpoint.h" diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index d77b8b2e9746..9d4149d700ba 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -10,7 +10,6 @@  #include "lldb/Host/common/NativeProcessProtocol.h"  #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/State.h"  #include "lldb/Host/Host.h" @@ -20,6 +19,7 @@  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Target/Process.h"  #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h"  #include "lldb/lldb-enumerations.h"  using namespace lldb; @@ -46,6 +46,12 @@ lldb_private::Error NativeProcessProtocol::Interrupt() {  #endif  } +Error NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef<int> signals) { +  m_signals_to_ignore.clear(); +  m_signals_to_ignore.insert(signals.begin(), signals.end()); +  return Error(); +} +  lldb_private::Error  NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr,                                             MemoryRegionInfo &range_info) { @@ -139,11 +145,8 @@ NativeProcessProtocol::GetWatchpointMap() const {    return m_watchpoint_list.GetWatchpointMap();  } -uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { -  // This default implementation will return the number of -  // *hardware* breakpoints available.  MacOSX and other OS -  // implementations that support software breakpoints will want to -  // override this correctly for their implementation. +llvm::Optional<std::pair<uint32_t, uint32_t>> +NativeProcessProtocol::GetHardwareDebugSupportInfo() const {    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));    // get any thread @@ -154,7 +157,7 @@ uint32_t NativeProcessProtocol::GetMaxWatchpoints() const {        log->Warning("NativeProcessProtocol::%s (): failed to find a thread to "                     "grab a NativeRegisterContext!",                     __FUNCTION__); -    return 0; +    return llvm::None;    }    NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); @@ -163,10 +166,11 @@ uint32_t NativeProcessProtocol::GetMaxWatchpoints() const {        log->Warning("NativeProcessProtocol::%s (): failed to get a "                     "RegisterContextNativeProcess from the first thread!",                     __FUNCTION__); -    return 0; +    return llvm::None;    } -  return reg_ctx_sp->NumSupportedHardwareWatchpoints(); +  return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), +                        reg_ctx_sp->NumSupportedHardwareWatchpoints());  }  Error NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -263,6 +267,92 @@ Error NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) {    return overall_error.Fail() ? overall_error : error;  } +const HardwareBreakpointMap & +NativeProcessProtocol::GetHardwareBreakpointMap() const { +  return m_hw_breakpoints_map; +} + +Error NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, +                                                   size_t size) { +  // This default implementation assumes setting a hardware breakpoint for +  // this process will require setting same hardware breakpoint for each +  // of its existing threads. New thread will do the same once created. +  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +  // Update the thread list +  UpdateThreads(); + +  // Exit here if target does not have required hardware breakpoint capability. +  auto hw_debug_cap = GetHardwareDebugSupportInfo(); + +  if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || +      hw_debug_cap->first <= m_hw_breakpoints_map.size()) +    return Error("Target does not have required no of hardware breakpoints"); + +  // Vector below stores all thread pointer for which we have we successfully +  // set this hardware breakpoint. If any of the current process threads fails +  // to set this hardware breakpoint then roll back and remove this breakpoint +  // for all the threads that had already set it successfully. +  std::vector<NativeThreadProtocolSP> breakpoint_established_threads; + +  // Request to set a hardware breakpoint for each of current process threads. +  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); +  for (auto thread_sp : m_threads) { +    assert(thread_sp && "thread list should not have a NULL thread!"); +    if (!thread_sp) +      continue; + +    Error thread_error = thread_sp->SetHardwareBreakpoint(addr, size); +    if (thread_error.Success()) { +      // Remember that we set this breakpoint successfully in +      // case we need to clear it later. +      breakpoint_established_threads.push_back(thread_sp); +    } else { +      // Unset the breakpoint for each thread we successfully +      // set so that we get back to a consistent state of "not +      // set" for this hardware breakpoint. +      for (auto rollback_thread_sp : breakpoint_established_threads) { +        Error remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); +        if (remove_error.Fail() && log) { +          log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" +                       " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", +                       __FUNCTION__, GetID(), rollback_thread_sp->GetID(), +                       remove_error.AsCString()); +        } +      } + +      return thread_error; +    } +  } + +  // Register new hardware breakpoint into hardware breakpoints map of current +  // process. +  m_hw_breakpoints_map[addr] = {addr, size}; + +  return Error(); +} + +Error NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { +  // Update the thread list +  UpdateThreads(); + +  Error error; + +  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); +  for (auto thread_sp : m_threads) { +    assert(thread_sp && "thread list should not have a NULL thread!"); +    if (!thread_sp) +      continue; + +    error = thread_sp->RemoveHardwareBreakpoint(addr); +  } + +  // Also remove from hardware breakpoint map of current process. +  m_hw_breakpoints_map.erase(addr); + +  return error; +} +  bool NativeProcessProtocol::RegisterNativeDelegate(      NativeDelegate &native_delegate) {    std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); @@ -339,8 +429,12 @@ Error NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr,        });  } -Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr) { -  return m_breakpoint_list.DecRef(addr); +Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, +                                              bool hardware) { +  if (hardware) +    return RemoveHardwareBreakpoint(addr); +  else +    return m_breakpoint_list.DecRef(addr);  }  Error NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { @@ -410,7 +504,7 @@ Error NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid,      return Error("failed to retrieve a valid architecture from the exe module");  } -#ifndef __linux__ +#if !defined(__linux__) && !defined(__NetBSD__)  // These need to be implemented to support lldb-gdb-server on a given platform.  // Stubs are  // provided to make the rest of the code link on non-supported platforms. diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 73b2629c57c1..3bc0a0d9705c 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/Log.h"  #include "lldb/Core/RegisterValue.h" +#include "lldb/Utility/Log.h"  #include "lldb/Host/PosixApi.h"  #include "lldb/Host/common/NativeProcessProtocol.h" @@ -246,10 +246,20 @@ uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,    return LLDB_INVALID_INDEX32;  } +Error NativeRegisterContext::ClearAllHardwareBreakpoints() { +  return Error("not implemented"); +} +  bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) {    return false;  } +Error NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index, +                                                      lldb::addr_t trap_addr) { +  bp_index = LLDB_INVALID_INDEX32; +  return Error("not implemented"); +} +  uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; }  uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, diff --git a/source/Host/common/NativeRegisterContextRegisterInfo.cpp b/source/Host/common/NativeRegisterContextRegisterInfo.cpp deleted file mode 100644 index 5ff596b57693..000000000000 --- a/source/Host/common/NativeRegisterContextRegisterInfo.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-- NativeRegisterContextRegisterInfo.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/NativeRegisterContextRegisterInfo.h" -#include "lldb/lldb-private-forward.h" -#include "lldb/lldb-types.h" - -using namespace lldb_private; - -NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( -    NativeThreadProtocol &thread, uint32_t concrete_frame_idx, -    RegisterInfoInterface *register_info_interface) -    : NativeRegisterContext(thread, concrete_frame_idx), -      m_register_info_interface_up(register_info_interface) { -  assert(register_info_interface && "null register_info_interface"); -} - -uint32_t NativeRegisterContextRegisterInfo::GetRegisterCount() const { -  return m_register_info_interface_up->GetRegisterCount(); -} - -uint32_t NativeRegisterContextRegisterInfo::GetUserRegisterCount() const { -  return m_register_info_interface_up->GetUserRegisterCount(); -} - -const RegisterInfo *NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex( -    uint32_t reg_index) const { -  if (reg_index <= GetRegisterCount()) -    return m_register_info_interface_up->GetRegisterInfo() + reg_index; -  else -    return nullptr; -} - -const RegisterInfoInterface & -NativeRegisterContextRegisterInfo::GetRegisterInfoInterface() const { -  return *m_register_info_interface_up; -} diff --git a/source/Host/common/NativeWatchpointList.cpp b/source/Host/common/NativeWatchpointList.cpp index 5948adf3c8d1..168e5b42b961 100644 --- a/source/Host/common/NativeWatchpointList.cpp +++ b/source/Host/common/NativeWatchpointList.cpp @@ -9,7 +9,7 @@  #include "lldb/Host/common/NativeWatchpointList.h" -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h"  using namespace lldb;  using namespace lldb_private; diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp new file mode 100644 index 000000000000..58c32e4a1c4b --- /dev/null +++ b/source/Host/common/PseudoTerminal.cpp @@ -0,0 +1,310 @@ +//===-- PseudoTerminal.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/PseudoTerminal.h" +#include "lldb/Host/Config.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if defined(TIOCSCTTY) +#include <sys/ioctl.h> +#endif + +#include "lldb/Host/PosixApi.h" + +#if defined(__ANDROID__) +int posix_openpt(int flags); +#endif + +using namespace lldb_utility; + +//---------------------------------------------------------------------- +// PseudoTerminal constructor +//---------------------------------------------------------------------- +PseudoTerminal::PseudoTerminal() +    : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {} + +//---------------------------------------------------------------------- +// Destructor +// +// The destructor will close the master and slave file descriptors +// if they are valid and ownership has not been released using the +// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() +// member functions. +//---------------------------------------------------------------------- +PseudoTerminal::~PseudoTerminal() { +  CloseMasterFileDescriptor(); +  CloseSlaveFileDescriptor(); +} + +//---------------------------------------------------------------------- +// Close the master file descriptor if it is valid. +//---------------------------------------------------------------------- +void PseudoTerminal::CloseMasterFileDescriptor() { +  if (m_master_fd >= 0) { +    ::close(m_master_fd); +    m_master_fd = invalid_fd; +  } +} + +//---------------------------------------------------------------------- +// Close the slave file descriptor if it is valid. +//---------------------------------------------------------------------- +void PseudoTerminal::CloseSlaveFileDescriptor() { +  if (m_slave_fd >= 0) { +    ::close(m_slave_fd); +    m_slave_fd = invalid_fd; +  } +} + +//---------------------------------------------------------------------- +// Open the first available pseudo terminal with OFLAG as the +// permissions. The file descriptor is stored in this object and can +// be accessed with the MasterFileDescriptor() accessor. The +// ownership of the master file descriptor can be released using +// the ReleaseMasterFileDescriptor() accessor. If this object has +// a valid master files descriptor when its destructor is called, it +// will close the master file descriptor, therefore clients must +// call ReleaseMasterFileDescriptor() if they wish to use the master +// file descriptor after this object is out of scope or destroyed. +// +// RETURNS: +//  True when successful, false indicating an error occurred. +//---------------------------------------------------------------------- +bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, +                                              size_t error_len) { +  if (error_str) +    error_str[0] = '\0'; + +#if !defined(LLDB_DISABLE_POSIX) +  // Open the master side of a pseudo terminal +  m_master_fd = ::posix_openpt(oflag); +  if (m_master_fd < 0) { +    if (error_str) +      ::strerror_r(errno, 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); +    CloseMasterFileDescriptor(); +    return false; +  } + +  // 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); +    CloseMasterFileDescriptor(); +    return false; +  } + +  return true; +#else +  if (error_str) +    ::snprintf(error_str, error_len, "%s", "pseudo terminal not supported"); +  return false; +#endif +} + +//---------------------------------------------------------------------- +// Open the slave pseudo terminal for the current master pseudo +// terminal. A master pseudo terminal should already be valid prior to +// calling this function (see OpenFirstAvailableMaster()). +// The file descriptor is stored this object's member variables and can +// be accessed via the GetSlaveFileDescriptor(), or released using the +// ReleaseSlaveFileDescriptor() member function. +// +// RETURNS: +//  True when successful, false indicating an error occurred. +//---------------------------------------------------------------------- +bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { +  if (error_str) +    error_str[0] = '\0'; + +  CloseSlaveFileDescriptor(); + +  // Open the master side of a pseudo terminal +  const char *slave_name = GetSlaveName(error_str, error_len); + +  if (slave_name == nullptr) +    return false; + +  m_slave_fd = ::open(slave_name, oflag); + +  if (m_slave_fd < 0) { +    if (error_str) +      ::strerror_r(errno, error_str, error_len); +    return false; +  } + +  return true; +} + +//---------------------------------------------------------------------- +// Get the name of the slave pseudo terminal. A master pseudo terminal +// should already be valid prior to calling this function (see +// OpenFirstAvailableMaster()). +// +// RETURNS: +//  NULL if no valid master pseudo terminal or if ptsname() fails. +//  The name of the slave pseudo terminal as a NULL terminated C string +//  that comes from static memory, so a copy of the string should be +//  made as subsequent calls can change this value. +//---------------------------------------------------------------------- +const char *PseudoTerminal::GetSlaveName(char *error_str, +                                         size_t error_len) const { +  if (error_str) +    error_str[0] = '\0'; + +  if (m_master_fd < 0) { +    if (error_str) +      ::snprintf(error_str, error_len, "%s", +                 "master file descriptor is invalid"); +    return nullptr; +  } +  const char *slave_name = ::ptsname(m_master_fd); + +  if (error_str && slave_name == nullptr) +    ::strerror_r(errno, error_str, error_len); + +  return slave_name; +} + +//---------------------------------------------------------------------- +// Fork a child process and have its stdio routed to a pseudo terminal. +// +// In the parent process when a valid pid is returned, the master file +// descriptor can be used as a read/write access to stdio of the +// child process. +// +// In the child process the stdin/stdout/stderr will already be routed +// to the slave pseudo terminal and the master file descriptor will be +// closed as it is no longer needed by the child process. +// +// This class will close the file descriptors for the master/slave +// when the destructor is called, so be sure to call +// ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any +// file descriptors are going to be used past the lifespan of this +// object. +// +// RETURNS: +//  in the parent process: the pid of the child, or -1 if fork fails +//  in the child process: zero +//---------------------------------------------------------------------- +lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { +  if (error_str) +    error_str[0] = '\0'; +  pid_t pid = LLDB_INVALID_PROCESS_ID; +#if !defined(LLDB_DISABLE_POSIX) +  int flags = O_RDWR; +  flags |= O_CLOEXEC; +  if (OpenFirstAvailableMaster(flags, error_str, error_len)) { +    // Successfully opened our master pseudo terminal + +    pid = ::fork(); +    if (pid < 0) { +      // Fork failed +      if (error_str) +        ::strerror_r(errno, error_str, error_len); +    } else if (pid == 0) { +      // Child Process +      ::setsid(); + +      if (OpenSlave(O_RDWR, error_str, error_len)) { +        // Successfully opened slave + +        // Master FD should have O_CLOEXEC set, but let's close it just in +        // case... +        CloseMasterFileDescriptor(); + +#if defined(TIOCSCTTY) +        // Acquire the controlling terminal +        if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) { +          if (error_str) +            ::strerror_r(errno, 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); +        } + +        if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) { +          if (error_str && !error_str[0]) +            ::strerror_r(errno, 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); +        } +      } +    } else { +      // Parent Process +      // Do nothing and let the pid get returned! +    } +  } +#endif +  return pid; +} + +//---------------------------------------------------------------------- +// The master file descriptor accessor. This object retains ownership +// of the master file descriptor when this accessor is used. Use +// ReleaseMasterFileDescriptor() if you wish this object to release +// ownership of the master file descriptor. +// +// Returns the master file descriptor, or -1 if the master file +// descriptor is not currently valid. +//---------------------------------------------------------------------- +int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; } + +//---------------------------------------------------------------------- +// The slave file descriptor accessor. +// +// Returns the slave file descriptor, or -1 if the slave file +// descriptor is not currently valid. +//---------------------------------------------------------------------- +int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; } + +//---------------------------------------------------------------------- +// Release ownership of the master pseudo terminal file descriptor +// without closing it. The destructor for this class will close the +// master file descriptor if the ownership isn't released using this +// call and the master file descriptor has been opened. +//---------------------------------------------------------------------- +int PseudoTerminal::ReleaseMasterFileDescriptor() { +  // Release ownership of the master pseudo terminal file +  // descriptor without closing it. (the destructor for this +  // class will close it otherwise!) +  int fd = m_master_fd; +  m_master_fd = invalid_fd; +  return fd; +} + +//---------------------------------------------------------------------- +// Release ownership of the slave pseudo terminal file descriptor +// without closing it. The destructor for this class will close the +// slave file descriptor if the ownership isn't released using this +// call and the slave file descriptor has been opened. +//---------------------------------------------------------------------- +int PseudoTerminal::ReleaseSlaveFileDescriptor() { +  // Release ownership of the slave pseudo terminal file +  // descriptor without closing it (the destructor for this +  // class will close it otherwise!) +  int fd = m_slave_fd; +  m_slave_fd = invalid_fd; +  return fd; +} diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 79777c88fa46..2a665ddacb64 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -9,14 +9,14 @@  #include "lldb/Host/Socket.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/RegularExpression.h"  #include "lldb/Host/Config.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/SocketAddress.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/common/TCPSocket.h"  #include "lldb/Host/common/UDPSocket.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegularExpression.h"  #ifndef LLDB_DISABLE_POSIX  #include "lldb/Host/posix/DomainSocket.h" @@ -38,11 +38,9 @@  #include <asm-generic/errno-base.h>  #include <errno.h>  #include <linux/tcp.h> -#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC)  #include <fcntl.h>  #include <sys/syscall.h>  #include <unistd.h> -#endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC  #endif // __ANDROID__  using namespace lldb; @@ -174,15 +172,13 @@ Error Socket::TcpListen(llvm::StringRef host_and_port,  }  Error Socket::UdpConnect(llvm::StringRef host_and_port, -                         bool child_processes_inherit, Socket *&send_socket, -                         Socket *&recv_socket) { +                         bool child_processes_inherit, Socket *&socket) {    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));    if (log)      log->Printf("Socket::%s (host/port = %s)", __FUNCTION__,                  host_and_port.data()); -  return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, -                            recv_socket); +  return UDPSocket::Connect(host_and_port, child_processes_inherit, socket);  }  Error Socket::UnixDomainConnect(llvm::StringRef name, @@ -424,9 +420,13 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,                                    socklen_t *addrlen,                                    bool child_processes_inherit, Error &error) {    error.Clear(); -#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) -  // Temporary workaround for statically linking Android lldb-server with the -  // latest API. +#if defined(ANDROID_USE_ACCEPT_WORKAROUND) +  // Hack: +  // This enables static linking lldb-server to an API 21 libc, but still having +  // it run on older devices. It is necessary because API 21 libc's +  // implementation of accept() uses the accept4 syscall(), which is not +  // available in older kernels. Using an older libc would fix this issue, but +  // introduce other ones, as the old libraries were quite buggy.    int fd = syscall(__NR_accept, sockfd, addr, addrlen);    if (fd >= 0 && !child_processes_inherit) {      int flags = ::fcntl(fd, F_GETFD); @@ -441,11 +441,7 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,    if (!child_processes_inherit) {      flags |= SOCK_CLOEXEC;    } -#if defined(__NetBSD__) -  NativeSocket fd = ::paccept(sockfd, addr, addrlen, nullptr, flags); -#else    NativeSocket fd = ::accept4(sockfd, addr, addrlen, flags); -#endif  #else    NativeSocket fd = ::accept(sockfd, addr, addrlen);  #endif diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 1f5de2e5df18..48c3ec1c48ed 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -89,6 +89,10 @@ SocketAddress::SocketAddress(const struct sockaddr_storage &s) {    m_socket_addr.sa_storage = s;  } +SocketAddress::SocketAddress(const struct addrinfo *addr_info) { +  *this = addr_info; +} +  //----------------------------------------------------------------------  // SocketAddress copy constructor  //---------------------------------------------------------------------- @@ -244,6 +248,24 @@ bool SocketAddress::getaddrinfo(const char *host, const char *service,    return result;  } +std::vector<SocketAddress> SocketAddress::GetAddressInfo(const char *hostname, +                                                       const char *servname) { +  std::vector<SocketAddress> addr_list; + +  struct addrinfo *service_info_list = NULL; +  int err = ::getaddrinfo(hostname, servname, NULL, &service_info_list); +  if (err == 0 && service_info_list) { +    for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL; +         service_ptr = service_ptr->ai_next) { +      addr_list.emplace_back(SocketAddress(service_ptr)); +    } +  } + +  if (service_info_list) +    ::freeaddrinfo(service_info_list); +  return addr_list; +} +  bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {    switch (family) {    case AF_INET: @@ -287,3 +309,29 @@ bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {    Clear();    return false;  } + +bool SocketAddress::IsAnyAddr() const { +  return (GetFamily() == AF_INET) +             ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY) +             : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16); +} + +bool SocketAddress::operator==(const SocketAddress &rhs) const { +  if (GetFamily() != rhs.GetFamily()) +    return false; +  if (GetLength() != rhs.GetLength()) +    return false; +  switch (GetFamily()) { +  case AF_INET: +    return m_socket_addr.sa_ipv4.sin_addr.s_addr == +           rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr; +  case AF_INET6: +    return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, +                       &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16); +  } +  return false; +} + +bool SocketAddress::operator!=(const SocketAddress &rhs) const { +  return !(*this == rhs); +} diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp index 3d57b7dd6b88..436cb2bb112e 100644 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ b/source/Host/common/SoftwareBreakpoint.cpp @@ -9,9 +9,9 @@  #include "lldb/Host/common/SoftwareBreakpoint.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/Debug.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h"  #include "lldb/Host/common/NativeProcessProtocol.h" diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index 461b15a07f84..9e0a3b5bf4df 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -9,17 +9,17 @@  #include "lldb/Host/Symbols.h"  #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Core/Timer.h" -#include "lldb/Core/UUID.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Target/Target.h" +#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/UUID.h"  #include "llvm/Support/FileSystem.h" @@ -54,7 +54,9 @@ static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec,    if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) {      ModuleSpec spec;      for (size_t i = 0; i < module_specs.GetSize(); ++i) { -      assert(module_specs.GetModuleSpecAtIndex(i, spec)); +      bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); +      UNUSED_IF_ASSERT_DISABLED(got_spec); +      assert(got_spec);        if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&            (arch == NULL || (spec.GetArchitecturePtr() &&                              spec.GetArchitecture().IsCompatibleMatch(*arch)))) { @@ -210,8 +212,13 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {      debug_file_search_paths.AppendIfUnique(FileSpec(".", true));  #ifndef LLVM_ON_WIN32 +#if defined(__NetBSD__) +    // Add /usr/libdata/debug directory. +    debug_file_search_paths.AppendIfUnique(FileSpec("/usr/libdata/debug", true)); +#else      // Add /usr/lib/debug directory.      debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); +#endif  #endif // LLVM_ON_WIN32      std::string uuid_str; @@ -228,7 +235,7 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {      for (size_t idx = 0; idx < num_directories; ++idx) {        FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);        dirspec.ResolvePath(); -      if (!dirspec.Exists() || !dirspec.IsDirectory()) +      if (!llvm::sys::fs::is_directory(dirspec.GetPath()))          continue;        std::vector<std::string> files; diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp index 9685ceeeadf1..9a009280a904 100644 --- a/source/Host/common/TCPSocket.cpp +++ b/source/Host/common/TCPSocket.cpp @@ -13,8 +13,8 @@  #include "lldb/Host/common/TCPSocket.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h"  #ifndef LLDB_DISABLE_POSIX  #include <arpa/inet.h> diff --git a/source/Host/common/ThisThread.cpp b/source/Host/common/ThisThread.cpp deleted file mode 100644 index b3f9edee2e16..000000000000 --- a/source/Host/common/ThisThread.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//===-- ThisThread.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/ThisThread.h" -#include "lldb/Core/Error.h" -#include "lldb/Host/HostInfo.h" - -#include "llvm/ADT/STLExtras.h" - -#include <algorithm> - -using namespace lldb; -using namespace lldb_private; - -void ThisThread::SetName(llvm::StringRef name, int max_length) { -  std::string truncated_name(name.data()); - -  // Thread names are coming in like '<lldb.comm.debugger.edit>' and -  // '<lldb.comm.debugger.editline>'.  So just chopping the end of the string -  // off leads to a lot of similar named threads.  Go through the thread name -  // and search for the last dot and use that. - -  if (max_length > 0 && -      truncated_name.length() > static_cast<size_t>(max_length)) { -    // First see if we can get lucky by removing any initial or final braces. -    std::string::size_type begin = truncated_name.find_first_not_of("(<"); -    std::string::size_type end = truncated_name.find_last_not_of(")>."); -    if (end - begin > static_cast<size_t>(max_length)) { -      // We're still too long.  Since this is a dotted component, use everything -      // after the last -      // dot, up to a maximum of |length| characters. -      std::string::size_type last_dot = truncated_name.rfind('.'); -      if (last_dot != std::string::npos) -        begin = last_dot + 1; - -      end = std::min(end, begin + max_length); -    } - -    std::string::size_type count = end - begin + 1; -    truncated_name = truncated_name.substr(begin, count); -  } - -  SetName(truncated_name); -} diff --git a/source/Host/common/ThreadLauncher.cpp b/source/Host/common/ThreadLauncher.cpp index b91c2fe9baab..32641efe408a 100644 --- a/source/Host/common/ThreadLauncher.cpp +++ b/source/Host/common/ThreadLauncher.cpp @@ -10,10 +10,9 @@  // lldb Includes  #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/HostNativeThread.h"  #include "lldb/Host/HostThread.h" -#include "lldb/Host/ThisThread.h" +#include "lldb/Utility/Log.h"  #if defined(_WIN32)  #include "lldb/Host/windows/windows.h" diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp index 972f87eb73d8..7ca62e7496ba 100644 --- a/source/Host/common/UDPSocket.cpp +++ b/source/Host/common/UDPSocket.cpp @@ -9,8 +9,8 @@  #include "lldb/Host/common/UDPSocket.h" -#include "lldb/Core/Log.h"  #include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h"  #ifndef LLDB_DISABLE_POSIX  #include <arpa/inet.h> @@ -38,7 +38,7 @@ UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)  size_t UDPSocket::Send(const void *buf, const size_t num_bytes) {    return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0, -                  m_send_sockaddr, m_send_sockaddr.GetLength()); +                  m_sockaddr, m_sockaddr.GetLength());  }  Error UDPSocket::Connect(llvm::StringRef name) { @@ -55,9 +55,8 @@ Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,  }  Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, -                         Socket *&send_socket, Socket *&recv_socket) { -  std::unique_ptr<UDPSocket> final_send_socket; -  std::unique_ptr<UDPSocket> final_recv_socket; +                         Socket *&socket) { +  std::unique_ptr<UDPSocket> final_socket;    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));    if (log) @@ -70,25 +69,6 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,    if (!DecodeHostAndPort(name, host_str, port_str, port, &error))      return error; -  // Setup the receiving end of the UDP connection on this localhost -  // on port zero. After we bind to port zero we can read the port. -  final_recv_socket.reset(new UDPSocket(child_processes_inherit, error)); -  if (error.Success()) { -    // Socket was created, now lets bind to the requested port -    SocketAddress addr; -    addr.SetToAnyAddress(AF_INET, 0); - -    if (::bind(final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -        -1) { -      // Bind failed... -      SetLastError(error); -    } -  } - -  assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); -  if (error.Fail()) -    return error; -    // At this point we have setup the receive port, now we need to    // setup the UDP send socket @@ -118,8 +98,8 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,          service_info_ptr->ai_family, service_info_ptr->ai_socktype,          service_info_ptr->ai_protocol, child_processes_inherit, error);      if (error.Success()) { -      final_send_socket.reset(new UDPSocket(send_fd)); -      final_send_socket->m_send_sockaddr = service_info_ptr; +      final_socket.reset(new UDPSocket(send_fd)); +      final_socket->m_sockaddr = service_info_ptr;        break;      } else        continue; @@ -127,11 +107,31 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,    ::freeaddrinfo(service_info_list); -  if (!final_send_socket) +  if (!final_socket) +    return error; + +  SocketAddress bind_addr; + +  // Only bind to the loopback address if we are expecting a connection from +  // localhost to avoid any firewall issues. +  const bool bind_addr_success = (host_str == "127.0.0.1" || host_str == "localhost") +                                     ? bind_addr.SetToLocalhost(kDomain, port) +                                     : bind_addr.SetToAnyAddress(kDomain, port); + +  if (!bind_addr_success) { +    error.SetErrorString("Failed to get hostspec to bind for");      return error; +  } + +  bind_addr.SetPort(0); // Let the source port # be determined dynamically + +  err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength()); + +  struct sockaddr_in source_info; +  socklen_t address_len = sizeof (struct sockaddr_in); +  err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len); -  send_socket = final_send_socket.release(); -  recv_socket = final_recv_socket.release(); +  socket = final_socket.release();    error.Clear();    return error;  } diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index aeab780ac453..9415b2bb3fd0 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -26,21 +26,21 @@  // C++ Includes  // Other libraries and framework includes  // Project includes -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/Endian.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h"  #include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h"  #include "lldb/Utility/NameMatches.h"  #include "llvm/Support/Host.h" @@ -52,18 +52,6 @@ extern char **environ;  using namespace lldb;  using namespace lldb_private; -size_t Host::GetEnvironment(StringList &env) { -  char *v; -  char **var = environ; -  for (; var != NULL && *var != NULL; ++var) { -    v = strchr(*var, (int)'-'); -    if (v == NULL) -      continue; -    env.AppendString(v); -  } -  return env.GetSize(); -} -  static bool  GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,                        ProcessInstanceInfo &process_info) { @@ -243,21 +231,13 @@ bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {    return false;  } -lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { -  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, 0}; -  size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); -  DataBufferSP buf_sp; - -  std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(auxv_size, 0)); - -  mib[3] = process->GetID(); -  if (::sysctl(mib, 4, buf_ap->GetBytes(), &auxv_size, NULL, 0) == 0) { -    buf_sp.reset(buf_ap.release()); -  } else { -    perror("sysctl failed on auxv"); -  } - -  return buf_sp; +size_t Host::GetEnvironment(StringList &env) { +  char **host_env = environ; +  char *env_entry; +  size_t i; +  for (i = 0; (env_entry = host_env[i]) != NULL; ++i) +    env.AppendString(env_entry); +  return i;  }  Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index fb9d86678dbb..9c82fcca7563 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -14,11 +14,10 @@  #include <sys/sysctl.h>  #include <sys/types.h>  #include <sys/utsname.h> +#include <unistd.h>  using namespace lldb_private; -uint32_t HostInfoFreeBSD::GetMaxThreadNameLength() { return 16; } -  bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor,                                     uint32_t &update) {    struct utsname un; diff --git a/source/Host/freebsd/HostThreadFreeBSD.cpp b/source/Host/freebsd/HostThreadFreeBSD.cpp deleted file mode 100644 index 97d4d9d05b66..000000000000 --- a/source/Host/freebsd/HostThreadFreeBSD.cpp +++ /dev/null @@ -1,70 +0,0 @@ -//===-- HostThreadFreeBSD.cpp -----------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// lldb Includes -#include "lldb/Host/freebsd/HostThreadFreeBSD.h" -#include "lldb/Host/Host.h" - -// C includes -#include <errno.h> -#include <pthread.h> -#if defined(__FreeBSD__) -#include <pthread_np.h> -#endif -#include <stdlib.h> -#include <sys/sysctl.h> -#include <sys/user.h> - -// C++ includes -#include <string> - -using namespace lldb_private; - -HostThreadFreeBSD::HostThreadFreeBSD() {} - -HostThreadFreeBSD::HostThreadFreeBSD(lldb::thread_t thread) -    : HostThreadPosix(thread) {} - -void HostThreadFreeBSD::GetName(lldb::tid_t tid, -                                llvm::SmallVectorImpl<char> &name) { -  name.clear(); -  int pid = Host::GetCurrentProcessID(); - -  struct kinfo_proc *kp = nullptr, *nkp; -  size_t len = 0; -  int error; -  int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, -                (int)pid}; - -  while (1) { -    error = sysctl(ctl, 4, kp, &len, nullptr, 0); -    if (kp == nullptr || (error != 0 && errno == ENOMEM)) { -      // Add extra space in case threads are added before next call. -      len += sizeof(*kp) + len / 10; -      nkp = (struct kinfo_proc *)realloc(kp, len); -      if (nkp == nullptr) { -        free(kp); -        return; -      } -      kp = nkp; -      continue; -    } -    if (error != 0) -      len = 0; -    break; -  } - -  for (size_t i = 0; i < len / sizeof(*kp); i++) { -    if (kp[i].ki_tid == (lwpid_t)tid) { -      name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname)); -      break; -    } -  } -  free(kp); -} diff --git a/source/Host/freebsd/ThisThread.cpp b/source/Host/freebsd/ThisThread.cpp deleted file mode 100644 index da0f2379a870..000000000000 --- a/source/Host/freebsd/ThisThread.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===-- ThisThread.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/ThisThread.h" -#include "lldb/Host/HostNativeThread.h" - -#include "llvm/ADT/SmallVector.h" - -#include <pthread.h> -#if defined(__FreeBSD__) -#include <pthread_np.h> -#endif - -using namespace lldb_private; - -void ThisThread::SetName(llvm::StringRef name) { -#if defined(__FreeBSD__) // Kfreebsd does not have a simple alternative -  ::pthread_set_name_np(::pthread_self(), name.data()); -#endif -} - -void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { -#if defined(__FreeBSD__) -  HostNativeThread::GetName(::pthread_getthreadid_np(), name); -#else -  // Kfreebsd -  HostNativeThread::GetName((unsigned)pthread_self(), name); -#endif -} diff --git a/source/Host/linux/Host.cpp b/source/Host/linux/Host.cpp index 8acf4a94e5bf..810222cbbf2f 100644 --- a/source/Host/linux/Host.cpp +++ b/source/Host/linux/Host.cpp @@ -21,150 +21,195 @@  // Other libraries and framework includes  #include "llvm/Support/ScopedPrinter.h"  // Project includes -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Target/Process.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h" +#include "lldb/Host/linux/Support.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" -#include "Plugins/Process/Linux/ProcFileReader.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Symbol/ObjectFile.h"  using namespace lldb;  using namespace lldb_private; -typedef enum ProcessStateFlags { -  eProcessStateRunning = (1u << 0),  // Running -  eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait -  eProcessStateWaiting = (1u << 2),  // Waiting in an uninterruptible disk sleep -  eProcessStateZombie = (1u << 3),   // Zombie -  eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal) -  eProcessStatePaging = (1u << 5)           // Paging -} ProcessStateFlags; - -typedef struct ProcessStatInfo { -  lldb::pid_t ppid;       // Parent Process ID -  uint32_t fProcessState; // ProcessStateFlags -} ProcessStatInfo; - -// Get the process info with additional information from /proc/$PID/stat (like -// process state, and tracer pid). -static bool GetProcessAndStatInfo(lldb::pid_t pid, -                                  ProcessInstanceInfo &process_info, -                                  ProcessStatInfo &stat_info, -                                  lldb::pid_t &tracerpid); - -static bool ReadProcPseudoFileStat(lldb::pid_t pid, -                                   ProcessStatInfo &stat_info) { -  // Read the /proc/$PID/stat file. -  lldb::DataBufferSP buf_sp = -      process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "stat"); - -  // The filename of the executable is stored in parenthesis right after the -  // pid. We look for the closing -  // parenthesis for the filename and work from there in case the name has -  // something funky like ')' in it. -  const char *filename_end = strrchr((const char *)buf_sp->GetBytes(), ')'); -  if (filename_end) { -    char state = '\0'; -    int ppid = LLDB_INVALID_PROCESS_ID; - -    // Read state and ppid. -    sscanf(filename_end + 1, " %c %d", &state, &ppid); - -    stat_info.ppid = ppid; - -    switch (state) { -    case 'R': -      stat_info.fProcessState |= eProcessStateRunning; -      break; -    case 'S': -      stat_info.fProcessState |= eProcessStateSleeping; -      break; -    case 'D': -      stat_info.fProcessState |= eProcessStateWaiting; -      break; -    case 'Z': -      stat_info.fProcessState |= eProcessStateZombie; -      break; -    case 'T': -      stat_info.fProcessState |= eProcessStateTracedOrStopped; -      break; -    case 'W': -      stat_info.fProcessState |= eProcessStatePaging; -      break; +namespace { +enum class ProcessState { +  Unknown, +  DiskSleep, +  Paging, +  Running, +  Sleeping, +  TracedOrStopped, +  Zombie, +}; +} + +static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, +                          ProcessState &State, ::pid_t &TracerPid) { +  auto BufferOrError = getProcFile(Pid, "status"); +  if (!BufferOrError) +    return false; + +  llvm::StringRef Rest = BufferOrError.get()->getBuffer(); +  while(!Rest.empty()) { +    llvm::StringRef Line; +    std::tie(Line, Rest) = Rest.split('\n'); + +    if (Line.consume_front("Gid:")) { +      // Real, effective, saved set, and file system GIDs. Read the first two. +      Line = Line.ltrim(); +      uint32_t RGid, EGid; +      Line.consumeInteger(10, RGid); +      Line = Line.ltrim(); +      Line.consumeInteger(10, EGid); + +      ProcessInfo.SetGroupID(RGid); +      ProcessInfo.SetEffectiveGroupID(EGid); +    } else if (Line.consume_front("Uid:")) { +      // Real, effective, saved set, and file system UIDs. Read the first two. +      Line = Line.ltrim(); +      uint32_t RUid, EUid; +      Line.consumeInteger(10, RUid); +      Line = Line.ltrim(); +      Line.consumeInteger(10, EUid); + +      ProcessInfo.SetUserID(RUid); +      ProcessInfo.SetEffectiveUserID(EUid); +    } else if (Line.consume_front("PPid:")) { +      ::pid_t PPid; +      Line.ltrim().consumeInteger(10, PPid); +      ProcessInfo.SetParentProcessID(PPid); +    } else if (Line.consume_front("State:")) { +      char S = Line.ltrim().front(); +      switch (S) { +      case 'R': +        State = ProcessState::Running; +        break; +      case 'S': +        State = ProcessState::Sleeping; +        break; +      case 'D': +        State = ProcessState::DiskSleep; +        break; +      case 'Z': +        State = ProcessState::Zombie; +        break; +      case 'T': +        State = ProcessState::TracedOrStopped; +        break; +      case 'W': +        State = ProcessState::Paging; +        break; +      } +    } else if (Line.consume_front("TracerPid:")) { +      Line = Line.ltrim(); +      Line.consumeInteger(10, TracerPid);      } +  } +  return true; +} -    return true; +static bool IsDirNumeric(const char *dname) { +  for (; *dname; dname++) { +    if (!isdigit(*dname)) +      return false;    } +  return true; +} +static bool GetELFProcessCPUType(llvm::StringRef exe_path, +                                 ProcessInstanceInfo &process_info) { +  // Clear the architecture. +  process_info.GetArchitecture().Clear(); + +  ModuleSpecList specs; +  FileSpec filespec(exe_path, false); +  const size_t num_specs = +      ObjectFile::GetModuleSpecifications(filespec, 0, 0, specs); +  // GetModuleSpecifications() could fail if the executable has been deleted or +  // is locked. +  // But it shouldn't return more than 1 architecture. +  assert(num_specs <= 1 && "Linux plugin supports only a single architecture"); +  if (num_specs == 1) { +    ModuleSpec module_spec; +    if (specs.GetModuleSpecAtIndex(0, module_spec) && +        module_spec.GetArchitecture().IsValid()) { +      process_info.GetArchitecture() = module_spec.GetArchitecture(); +      return true; +    } +  }    return false;  } -static void GetLinuxProcessUserAndGroup(lldb::pid_t pid, -                                        ProcessInstanceInfo &process_info, -                                        lldb::pid_t &tracerpid) { +static bool GetProcessAndStatInfo(::pid_t pid, +                                  ProcessInstanceInfo &process_info, +                                  ProcessState &State, ::pid_t &tracerpid) {    tracerpid = 0; -  uint32_t rUid = UINT32_MAX; // Real User ID -  uint32_t eUid = UINT32_MAX; // Effective User ID -  uint32_t rGid = UINT32_MAX; // Real Group ID -  uint32_t eGid = UINT32_MAX; // Effective Group ID - -  // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: -  // fields. -  lldb::DataBufferSP buf_sp = -      process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "status"); - -  static const char uid_token[] = "Uid:"; -  char *buf_uid = strstr((char *)buf_sp->GetBytes(), uid_token); -  if (buf_uid) { -    // Real, effective, saved set, and file system UIDs. Read the first two. -    buf_uid += sizeof(uid_token); -    rUid = strtol(buf_uid, &buf_uid, 10); -    eUid = strtol(buf_uid, &buf_uid, 10); -  } +  process_info.Clear(); -  static const char gid_token[] = "Gid:"; -  char *buf_gid = strstr((char *)buf_sp->GetBytes(), gid_token); -  if (buf_gid) { -    // Real, effective, saved set, and file system GIDs. Read the first two. -    buf_gid += sizeof(gid_token); -    rGid = strtol(buf_gid, &buf_gid, 10); -    eGid = strtol(buf_gid, &buf_gid, 10); -  } +  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +  // We can't use getProcFile here because proc/[pid]/exe is a symbolic link. +  llvm::SmallString<64> ProcExe; +  (llvm::Twine("/proc/") + llvm::Twine(pid) + "/exe").toVector(ProcExe); +  std::string ExePath(PATH_MAX, '\0'); -  static const char tracerpid_token[] = "TracerPid:"; -  char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token); -  if (buf_tracerpid) { -    // Tracer PID. 0 if we're not being debugged. -    buf_tracerpid += sizeof(tracerpid_token); -    tracerpid = strtol(buf_tracerpid, &buf_tracerpid, 10); +  ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX); +  if (len <= 0) { +    LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid, +             Error(errno, eErrorTypePOSIX)); +    return false;    } +  ExePath.resize(len); -  process_info.SetUserID(rUid); -  process_info.SetEffectiveUserID(eUid); -  process_info.SetGroupID(rGid); -  process_info.SetEffectiveGroupID(eGid); -} +  // If the binary has been deleted, the link name has " (deleted)" appended. +  // Remove if there. +  llvm::StringRef PathRef = ExePath; +  PathRef.consume_back(" (deleted)"); -lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { -  return process_linux::ProcFileReader::ReadIntoDataBuffer(process->GetID(), -                                                           "auxv"); -} +  GetELFProcessCPUType(PathRef, process_info); -lldb::DataBufferSP Host::GetAuxvData(lldb::pid_t pid) { -  return process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "auxv"); -} +  // Get the process environment. +  auto BufferOrError = getProcFile(pid, "environ"); +  if (!BufferOrError) +    return false; +  std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError); -static bool IsDirNumeric(const char *dname) { -  for (; *dname; dname++) { -    if (!isdigit(*dname)) -      return false; +  // Get the command line used to start the process. +  BufferOrError = getProcFile(pid, "cmdline"); +  if (!BufferOrError) +    return false; +  std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError); + +  // Get User and Group IDs and get tracer pid. +  if (!GetStatusInfo(pid, process_info, State, tracerpid)) +    return false; + +  process_info.SetProcessID(pid); +  process_info.GetExecutableFile().SetFile(PathRef, false); +  process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture()); + +  llvm::StringRef Rest = Environ->getBuffer(); +  while (!Rest.empty()) { +    llvm::StringRef Var; +    std::tie(Var, Rest) = Rest.split('\0'); +    process_info.GetEnvironmentEntries().AppendArgument(Var);    } + +  llvm::StringRef Arg0; +  std::tie(Arg0, Rest) = Cmdline->getBuffer().split('\0'); +  process_info.SetArg0(Arg0); +  while (!Rest.empty()) { +    llvm::StringRef Arg; +    std::tie(Arg, Rest) = Rest.split('\0'); +    process_info.GetArguments().AppendArgument(Arg); +  } +    return true;  } @@ -189,19 +234,18 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,        if (pid == our_pid)          continue; -      lldb::pid_t tracerpid; -      ProcessStatInfo stat_info; +      ::pid_t tracerpid; +      ProcessState State;        ProcessInstanceInfo process_info; -      if (!GetProcessAndStatInfo(pid, process_info, stat_info, tracerpid)) +      if (!GetProcessAndStatInfo(pid, process_info, State, tracerpid))          continue;        // Skip if process is being debugged.        if (tracerpid != 0)          continue; -      // Skip zombies. -      if (stat_info.fProcessState & eProcessStateZombie) +      if (State == ProcessState::Zombie)          continue;        // Check for user match if we're not matching all users and not running as @@ -246,121 +290,10 @@ bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {    return tids_changed;  } -static bool GetELFProcessCPUType(const char *exe_path, -                                 ProcessInstanceInfo &process_info) { -  // Clear the architecture. -  process_info.GetArchitecture().Clear(); - -  ModuleSpecList specs; -  FileSpec filespec(exe_path, false); -  const size_t num_specs = -      ObjectFile::GetModuleSpecifications(filespec, 0, 0, specs); -  // GetModuleSpecifications() could fail if the executable has been deleted or -  // is locked. -  // But it shouldn't return more than 1 architecture. -  assert(num_specs <= 1 && "Linux plugin supports only a single architecture"); -  if (num_specs == 1) { -    ModuleSpec module_spec; -    if (specs.GetModuleSpecAtIndex(0, module_spec) && -        module_spec.GetArchitecture().IsValid()) { -      process_info.GetArchitecture() = module_spec.GetArchitecture(); -      return true; -    } -  } -  return false; -} - -static bool GetProcessAndStatInfo(lldb::pid_t pid, -                                  ProcessInstanceInfo &process_info, -                                  ProcessStatInfo &stat_info, -                                  lldb::pid_t &tracerpid) { -  tracerpid = 0; -  process_info.Clear(); -  ::memset(&stat_info, 0, sizeof(stat_info)); -  stat_info.ppid = LLDB_INVALID_PROCESS_ID; - -  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - -  // Use special code here because proc/[pid]/exe is a symbolic link. -  char link_path[PATH_MAX]; -  char exe_path[PATH_MAX] = ""; -  if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) { -    if (log) -      log->Printf("%s: failed to sprintf pid %" PRIu64, __FUNCTION__, pid); -    return false; -  } - -  ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1); -  if (len <= 0) { -    if (log) -      log->Printf("%s: failed to read link %s: %s", __FUNCTION__, link_path, -                  strerror(errno)); -    return false; -  } - -  // readlink does not append a null byte. -  exe_path[len] = 0; - -  // If the binary has been deleted, the link name has " (deleted)" appended. -  //  Remove if there. -  static const ssize_t deleted_len = strlen(" (deleted)"); -  if (len > deleted_len && -      !strcmp(exe_path + len - deleted_len, " (deleted)")) { -    exe_path[len - deleted_len] = 0; -  } else { -    GetELFProcessCPUType(exe_path, process_info); -  } - -  process_info.SetProcessID(pid); -  process_info.GetExecutableFile().SetFile(exe_path, false); -  process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture()); - -  lldb::DataBufferSP buf_sp; - -  // Get the process environment. -  buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ"); -  Args &info_env = process_info.GetEnvironmentEntries(); -  char *next_var = (char *)buf_sp->GetBytes(); -  char *end_buf = next_var + buf_sp->GetByteSize(); -  while (next_var < end_buf && 0 != *next_var) { -    info_env.AppendArgument(llvm::StringRef(next_var)); -    next_var += strlen(next_var) + 1; -  } - -  // Get the command line used to start the process. -  buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline"); - -  // Grab Arg0 first, if there is one. -  char *cmd = (char *)buf_sp->GetBytes(); -  if (cmd) { -    process_info.SetArg0(cmd); - -    // Now process any remaining arguments. -    Args &info_args = process_info.GetArguments(); -    char *next_arg = cmd + strlen(cmd) + 1; -    end_buf = cmd + buf_sp->GetByteSize(); -    while (next_arg < end_buf && 0 != *next_arg) { -      info_args.AppendArgument(llvm::StringRef(next_arg)); -      next_arg += strlen(next_arg) + 1; -    } -  } - -  // Read /proc/$PID/stat to get our parent pid. -  if (ReadProcPseudoFileStat(pid, stat_info)) { -    process_info.SetParentProcessID(stat_info.ppid); -  } - -  // Get User and Group IDs and get tracer pid. -  GetLinuxProcessUserAndGroup(pid, process_info, tracerpid); - -  return true; -} -  bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { -  lldb::pid_t tracerpid; -  ProcessStatInfo stat_info; - -  return GetProcessAndStatInfo(pid, process_info, stat_info, tracerpid); +  ::pid_t tracerpid; +  ProcessState State; +  return GetProcessAndStatInfo(pid, process_info, State, tracerpid);  }  size_t Host::GetEnvironment(StringList &env) { diff --git a/source/Host/linux/HostInfoLinux.cpp b/source/Host/linux/HostInfoLinux.cpp index 2a01f0676142..3ff722d5c109 100644 --- a/source/Host/linux/HostInfoLinux.cpp +++ b/source/Host/linux/HostInfoLinux.cpp @@ -8,7 +8,9 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/linux/HostInfoLinux.h" -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h" + +#include "llvm/Support/Threading.h"  #include <limits.h>  #include <stdio.h> @@ -39,13 +41,11 @@ void HostInfoLinux::Initialize() {    g_fields = new HostInfoLinuxFields();  } -uint32_t HostInfoLinux::GetMaxThreadNameLength() { return 16; } -  bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor,                                   uint32_t &update) {    static bool success = false; -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { +  static llvm::once_flag g_once_flag; +  llvm::call_once(g_once_flag, []() {      struct utsname un;      if (uname(&un) == 0) { @@ -100,8 +100,8 @@ bool HostInfoLinux::GetOSKernelDescription(std::string &s) {  llvm::StringRef HostInfoLinux::GetDistributionId() {    // Try to run 'lbs_release -i', and use that response    // for the distribution id. -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { +  static llvm::once_flag g_once_flag; +  llvm::call_once(g_once_flag, []() {      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST));      if (log) diff --git a/source/Host/linux/HostThreadLinux.cpp b/source/Host/linux/HostThreadLinux.cpp deleted file mode 100644 index 625f05d0e9d8..000000000000 --- a/source/Host/linux/HostThreadLinux.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===-- HostThreadLinux.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/linux/HostThreadLinux.h" -#include "Plugins/Process/Linux/ProcFileReader.h" -#include "lldb/Core/DataBuffer.h" - -#include "llvm/ADT/SmallVector.h" - -#include <pthread.h> - -using namespace lldb_private; - -HostThreadLinux::HostThreadLinux() : HostThreadPosix() {} - -HostThreadLinux::HostThreadLinux(lldb::thread_t thread) -    : HostThreadPosix(thread) {} - -void HostThreadLinux::SetName(lldb::thread_t thread, llvm::StringRef name) { -#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__) -  ::pthread_setname_np(thread, name.data()); -#else -  (void)thread; -  (void)name; -#endif -} - -void HostThreadLinux::GetName(lldb::thread_t thread, -                              llvm::SmallVectorImpl<char> &name) { -  // Read /proc/$TID/comm file. -  lldb::DataBufferSP buf_sp = -      process_linux::ProcFileReader::ReadIntoDataBuffer(thread, "comm"); -  const char *comm_str = (const char *)buf_sp->GetBytes(); -  const char *cr_str = ::strchr(comm_str, '\n'); -  size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); - -  name.clear(); -  name.append(comm_str, comm_str + length); -} diff --git a/source/Host/linux/ProcessLauncherLinux.cpp b/source/Host/linux/ProcessLauncherLinux.cpp index 27a6329da067..e69de29bb2d1 100644 --- a/source/Host/linux/ProcessLauncherLinux.cpp +++ b/source/Host/linux/ProcessLauncherLinux.cpp @@ -1,216 +0,0 @@ -//===-- ProcessLauncherLinux.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/linux/ProcessLauncherLinux.h" -#include "lldb/Core/Log.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostProcess.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Target/ProcessLaunchInfo.h" - -#include <limits.h> -#include <sys/personality.h> -#include <sys/ptrace.h> -#include <sys/wait.h> - -#include <sstream> - -using namespace lldb; -using namespace lldb_private; - -static void FixupEnvironment(Args &env) { -#ifdef __ANDROID__ -  // If there is no PATH variable specified inside the environment then set the -  // path to /system/bin. It is required because the default path used by -  // execve() is wrong on android. -  static const char *path = "PATH="; -  for (auto &entry : env.entries()) { -    if (entry.ref.startswith(path)) -      return; -  } -  env.AppendArgument(llvm::StringRef("PATH=/system/bin")); -#endif -} - -static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd, -                                                  const char *operation) { -  std::ostringstream os; -  os << operation << " failed: " << strerror(errno); -  write(error_fd, os.str().data(), os.str().size()); -  close(error_fd); -  _exit(1); -} - -static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, -                          int flags) { -  int target_fd = ::open(file_spec.GetCString(), flags, 0666); - -  if (target_fd == -1) -    ExitWithError(error_fd, "DupDescriptor-open"); - -  if (target_fd == fd) -    return; - -  if (::dup2(target_fd, fd) == -1) -    ExitWithError(error_fd, "DupDescriptor-dup2"); - -  ::close(target_fd); -  return; -} - -static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, -                                              const ProcessLaunchInfo &info) { -  // First, make sure we disable all logging. If we are logging to stdout, our -  // logs can be -  // mistaken for inferior output. -  Log::DisableAllLogChannels(nullptr); - -  // Do not inherit setgid powers. -  if (setgid(getgid()) != 0) -    ExitWithError(error_fd, "setgid"); - -  if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) { -    if (setpgid(0, 0) != 0) -      ExitWithError(error_fd, "setpgid"); -  } - -  for (size_t i = 0; i < info.GetNumFileActions(); ++i) { -    const FileAction &action = *info.GetFileActionAtIndex(i); -    switch (action.GetAction()) { -    case FileAction::eFileActionClose: -      if (close(action.GetFD()) != 0) -        ExitWithError(error_fd, "close"); -      break; -    case FileAction::eFileActionDuplicate: -      if (dup2(action.GetFD(), action.GetActionArgument()) == -1) -        ExitWithError(error_fd, "dup2"); -      break; -    case FileAction::eFileActionOpen: -      DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(), -                    action.GetActionArgument()); -      break; -    case FileAction::eFileActionNone: -      break; -    } -  } - -  const char **argv = info.GetArguments().GetConstArgumentVector(); - -  // Change working directory -  if (info.GetWorkingDirectory() && -      0 != ::chdir(info.GetWorkingDirectory().GetCString())) -    ExitWithError(error_fd, "chdir"); - -  // Disable ASLR if requested. -  if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) { -    const unsigned long personality_get_current = 0xffffffff; -    int value = personality(personality_get_current); -    if (value == -1) -      ExitWithError(error_fd, "personality get"); - -    value = personality(ADDR_NO_RANDOMIZE | value); -    if (value == -1) -      ExitWithError(error_fd, "personality set"); -  } - -  Args env = info.GetEnvironmentEntries(); -  FixupEnvironment(env); -  const char **envp = env.GetConstArgumentVector(); - -  // Clear the signal mask to prevent the child from being affected by -  // any masking done by the parent. -  sigset_t set; -  if (sigemptyset(&set) != 0 || -      pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) -    ExitWithError(error_fd, "pthread_sigmask"); - -  if (info.GetFlags().Test(eLaunchFlagDebug)) { -    // HACK: -    // Close everything besides stdin, stdout, and stderr that has no file -    // action to avoid leaking. Only do this when debugging, as elsewhere we -    // actually rely on -    // passing open descriptors to child processes. -    for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) -      if (!info.GetFileActionForFD(fd) && fd != error_fd) -        close(fd); - -    // Start tracing this child that is about to exec. -    if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) -      ExitWithError(error_fd, "ptrace"); -  } - -  // Execute.  We should never return... -  execve(argv[0], const_cast<char *const *>(argv), -         const_cast<char *const *>(envp)); - -  if (errno == ETXTBSY) { -    // On android M and earlier we can get this error because the adb deamon 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 running the test suite. (The file remains open when -    // someone does -    // an "adb shell" command in the fork() child before it has had a chance to -    // exec.) Since -    // this state should clear up quickly, wait a while and then give it one -    // more go. -    usleep(50000); -    execve(argv[0], const_cast<char *const *>(argv), -           const_cast<char *const *>(envp)); -  } - -  // ...unless exec fails.  In which case we definitely need to end the child -  // here. -  ExitWithError(error_fd, "execve"); -} - -HostProcess -ProcessLauncherLinux::LaunchProcess(const ProcessLaunchInfo &launch_info, -                                    Error &error) { -  char exe_path[PATH_MAX]; -  launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - -  // A pipe used by the child process to report errors. -  PipePosix pipe; -  const bool child_processes_inherit = false; -  error = pipe.CreateNew(child_processes_inherit); -  if (error.Fail()) -    return HostProcess(); - -  ::pid_t pid = ::fork(); -  if (pid == -1) { -    // Fork failed -    error.SetErrorStringWithFormat("Fork failed with error message: %s", -                                   strerror(errno)); -    return HostProcess(LLDB_INVALID_PROCESS_ID); -  } -  if (pid == 0) { -    // child process -    pipe.CloseReadFileDescriptor(); -    ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info); -  } - -  // parent process - -  pipe.CloseWriteFileDescriptor(); -  char buf[1000]; -  int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf); - -  if (r == 0) -    return HostProcess(pid); // No error. We're done. - -  error.SetErrorString(buf); - -  waitpid(pid, nullptr, 0); - -  return HostProcess(); -} diff --git a/source/Host/linux/Support.cpp b/source/Host/linux/Support.cpp new file mode 100644 index 000000000000..8fbb60052e3f --- /dev/null +++ b/source/Host/linux/Support.cpp @@ -0,0 +1,34 @@ +//===-- Support.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/linux/Support.h" +#include "lldb/Utility/Log.h" +#include "llvm/Support/MemoryBuffer.h" + +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +lldb_private::getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file) { +  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); +  std::string File = +      ("/proc/" + llvm::Twine(pid) + "/task/" + llvm::Twine(tid) + "/" + file) +          .str(); +  auto Ret = llvm::MemoryBuffer::getFileAsStream(File); +  if (!Ret) +    LLDB_LOG(log, "Failed to open {0}: {1}", File, Ret.getError().message()); +  return Ret; +} + +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +lldb_private::getProcFile(::pid_t pid, const llvm::Twine &file) { +  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); +  std::string File = ("/proc/" + llvm::Twine(pid) + "/" + file).str(); +  auto Ret = llvm::MemoryBuffer::getFileAsStream(File); +  if (!Ret) +    LLDB_LOG(log, "Failed to open {0}: {1}", File, Ret.getError().message()); +  return Ret; +} diff --git a/source/Host/linux/ThisThread.cpp b/source/Host/linux/ThisThread.cpp deleted file mode 100644 index f65440b9d778..000000000000 --- a/source/Host/linux/ThisThread.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===-- ThisThread.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/ThisThread.h" -#include "lldb/Host/HostNativeThread.h" - -#include "llvm/ADT/SmallVector.h" - -#include <pthread.h> - -using namespace lldb_private; - -void ThisThread::SetName(llvm::StringRef name) { -  HostNativeThread::SetName(::pthread_self(), name); -} - -void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { -  HostNativeThread::GetName(::pthread_self(), name); -} diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm index 99bc7ec8ff15..4c51e8ff154b 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/Host.mm @@ -56,24 +56,25 @@  #include "lldb/Core/ArchSpec.h"  #include "lldb/Core/Communication.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Core/StructuredData.h"  #include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/Endian.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/ThreadLauncher.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h"  #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/Support/FileSystem.h"  #include "cfcpp/CFCBundle.h"  #include "cfcpp/CFCMutableArray.h" @@ -101,7 +102,7 @@ using namespace lldb_private;  bool Host::GetBundleDirectory(const FileSpec &file,                                FileSpec &bundle_directory) {  #if defined(__APPLE__) -  if (file.GetFileType() == FileSpec::eFileTypeDirectory) { +  if (llvm::sys::fs::is_directory(file.GetPath())) {      char path[PATH_MAX];      if (file.GetPath(path, sizeof(path))) {        CFCBundle bundle(path); @@ -118,7 +119,7 @@ bool Host::GetBundleDirectory(const FileSpec &file,  bool Host::ResolveExecutableInBundle(FileSpec &file) {  #if defined(__APPLE__) -  if (file.GetFileType() == FileSpec::eFileTypeDirectory) { +  if (llvm::sys::fs::is_directory(file.GetPath())) {      char path[PATH_MAX];      if (file.GetPath(path, sizeof(path))) {        CFCBundle bundle(path); @@ -528,7 +529,7 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path,      WaitForProcessToSIGSTOP(pid, 5);    } -  FileSystem::Unlink(FileSpec{unix_socket_name, false}); +  llvm::sys::fs::remove(unix_socket_name);    [applescript release];    if (pid != LLDB_INVALID_PROCESS_ID)      launch_info.SetProcessID(pid); @@ -957,9 +958,7 @@ static Error getXPCAuthorization(ProcessLaunchInfo &launch_info) {      if (createStatus != errAuthorizationSuccess) {        error.SetError(1, eErrorTypeGeneric);        error.SetErrorString("Can't create authorizationRef."); -      if (log) { -        error.PutToLog(log, "%s", error.AsCString()); -      } +      LLDB_LOG(log, "error: {0}", error);        return error;      } @@ -1012,9 +1011,7 @@ static Error getXPCAuthorization(ProcessLaunchInfo &launch_info) {        error.SetError(2, eErrorTypeGeneric);        error.SetErrorStringWithFormat(            "Launching as root needs root authorization."); -      if (log) { -        error.PutToLog(log, "%s", error.AsCString()); -      } +      LLDB_LOG(log, "error: {0}", error);        if (authorizationRef) {          AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); @@ -1050,9 +1047,7 @@ static Error LaunchProcessXPC(const char *exe_path,        error.SetError(3, eErrorTypeGeneric);        error.SetErrorStringWithFormat("Launching root via XPC needs to "                                       "externalize authorization reference."); -      if (log) { -        error.PutToLog(log, "%s", error.AsCString()); -      } +      LLDB_LOG(log, "error: {0}", error);        return error;      }      xpc_service = LaunchUsingXPCRightName; @@ -1060,9 +1055,7 @@ static Error LaunchProcessXPC(const char *exe_path,      error.SetError(4, eErrorTypeGeneric);      error.SetErrorStringWithFormat(          "Launching via XPC is only currently available for root."); -    if (log) { -      error.PutToLog(log, "%s", error.AsCString()); -    } +    LLDB_LOG(log, "error: {0}", error);      return error;    } @@ -1146,9 +1139,7 @@ static Error LaunchProcessXPC(const char *exe_path,        error.SetErrorStringWithFormat(            "Problems with launching via XPC. Error type : %i, code : %i",            errorType, errorCode); -      if (log) { -        error.PutToLog(log, "%s", error.AsCString()); -      } +      LLDB_LOG(log, "error: {0}", error);        if (authorizationRef) {          AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); @@ -1160,9 +1151,7 @@ static Error LaunchProcessXPC(const char *exe_path,      error.SetErrorStringWithFormat(          "Problems with launching via XPC. XPC error : %s",          xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); -    if (log) { -      error.PutToLog(log, "%s", error.AsCString()); -    } +    LLDB_LOG(log, "error: {0}", error);    }    return error; @@ -1196,8 +1185,8 @@ Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) {    ModuleSpec exe_module_spec(launch_info.GetExecutableFile(),                               launch_info.GetArchitecture()); -  FileSpec::FileType file_type = exe_module_spec.GetFileSpec().GetFileType(); -  if (file_type != FileSpec::eFileTypeRegular) { +  if (!llvm::sys::fs::is_regular_file( +          exe_module_spec.GetFileSpec().GetPath())) {      lldb::ModuleSP exe_module_sp;      error = host_platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp,                                                  NULL); @@ -1458,7 +1447,3 @@ void Host::SystemLog(SystemLogType type, const char *format, va_list args) {      ::asl_vlog(NULL, g_aslmsg, asl_level, format, args);    }  } - -lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { -  return lldb::DataBufferSP(); -} diff --git a/source/Host/macosx/HostInfoMacOSX.mm b/source/Host/macosx/HostInfoMacOSX.mm index 1c526c6ecccb..8774c76ef2da 100644 --- a/source/Host/macosx/HostInfoMacOSX.mm +++ b/source/Host/macosx/HostInfoMacOSX.mm @@ -11,13 +11,14 @@  #include "Plugins/ScriptInterpreter/Python/lldb-python.h"  #endif -#include "lldb/Core/Log.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/macosx/HostInfoMacOSX.h"  #include "lldb/Interpreter/Args.h" +#include "lldb/Utility/Log.h"  #include "lldb/Utility/SafeMachO.h"  #include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h"  #include "llvm/Support/raw_ostream.h"  // C++ Includes @@ -152,7 +153,7 @@ bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) {      // the lldb driver.      raw_path.append("/../bin");      FileSpec support_dir_spec(raw_path, true); -    if (!support_dir_spec.Exists() || !support_dir_spec.IsDirectory()) { +    if (!llvm::sys::fs::is_directory(support_dir_spec.GetPath())) {        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);        if (log)          log->Printf("HostInfoMacOSX::%s(): failed to find support directory", @@ -334,5 +335,3 @@ void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,      }    }  } - -uint32_t HostInfoMacOSX::GetMaxThreadNameLength() { return 64; } diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp index c428377eb7d2..a5085681495d 100644 --- a/source/Host/macosx/Symbols.cpp +++ b/source/Host/macosx/Symbols.cpp @@ -24,20 +24,22 @@  #include "Host/macosx/cfcpp/CFCReleaser.h"  #include "Host/macosx/cfcpp/CFCString.h"  #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Core/Timer.h" -#include "lldb/Core/UUID.h" -#include "lldb/Host/Endian.h"  #include "lldb/Host/Host.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/UUID.h"  #include "mach/machine.h" +#include "llvm/Support/FileSystem.h" +  using namespace lldb;  using namespace lldb_private;  using namespace llvm::MachO; @@ -101,7 +103,7 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,              }              FileSpec dsym_filespec(path, path[0] == '~'); -            if (dsym_filespec.GetFileType() == FileSpec::eFileTypeDirectory) { +            if (llvm::sys::fs::is_directory(dsym_filespec.GetPath())) {                dsym_filespec =                    Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch);                ++items_found; @@ -164,8 +166,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,                  FileSpec file_spec(path, true);                  ModuleSpecList module_specs;                  ModuleSpec matched_module_spec; -                switch (file_spec.GetFileType()) { -                case FileSpec::eFileTypeDirectory: // Bundle directory? +                using namespace llvm::sys::fs; +                switch (get_file_type(file_spec.GetPath())) { + +                case file_type::directory_file: // Bundle directory?                  {                    CFCBundle bundle(path);                    CFCReleaser<CFURLRef> bundle_exe_url( @@ -193,15 +197,17 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,                    }                  } break; -                case FileSpec::eFileTypePipe:   // Forget pipes -                case FileSpec::eFileTypeSocket: // We can't process socket files -                case FileSpec::eFileTypeInvalid: // File doesn't exist... +                case file_type::fifo_file:      // Forget pipes +                case file_type::socket_file:    // We can't process socket files +                case file_type::file_not_found: // File doesn't exist... +                case file_type::status_error:                    break; -                case FileSpec::eFileTypeUnknown: -                case FileSpec::eFileTypeRegular: -                case FileSpec::eFileTypeSymbolicLink: -                case FileSpec::eFileTypeOther: +                case file_type::type_unknown: +                case file_type::regular_file: +                case file_type::symlink_file: +                case file_type::block_file: +                case file_type::character_file:                    if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0,                                                            module_specs) &&                        module_specs.FindMatchingModuleSpec(module_spec, @@ -263,7 +269,9 @@ FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,                                                    module_specs)) {              ModuleSpec spec;              for (size_t i = 0; i < module_specs.GetSize(); ++i) { -              assert(module_specs.GetModuleSpecAtIndex(i, spec)); +              bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); +              UNUSED_IF_ASSERT_DISABLED(got_spec); +              assert(got_spec);                if ((uuid == NULL ||                     (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&                    (arch == NULL || diff --git a/source/Host/macosx/ThisThread.cpp b/source/Host/macosx/ThisThread.cpp deleted file mode 100644 index 5244ba014121..000000000000 --- a/source/Host/macosx/ThisThread.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===-- ThisThread.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/ThisThread.h" - -#include "llvm/ADT/SmallVector.h" -#include <pthread.h> - -using namespace lldb_private; - -void ThisThread::SetName(llvm::StringRef name) { -#if defined(__APPLE__) -  ::pthread_setname_np(name.str().c_str()); -#endif -} - -void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { -  // FIXME - implement this. -} diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp index 717af9b20aeb..6a6b8ab51a17 100644 --- a/source/Host/netbsd/Host.cpp +++ b/source/Host/netbsd/Host.cpp @@ -1,5 +1,4 @@ -//===-- source/Host/netbsd/Host.cpp ------------------------------*- C++ -//-*-===// +//===-- source/Host/netbsd/Host.cpp -----------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -15,7 +14,6 @@  #include <sys/proc.h>  #include <sys/sysctl.h>  #include <sys/types.h> -#include <sys/user.h>  #include <limits.h> @@ -27,21 +25,21 @@  // C++ Includes  // Other libraries and framework includes  // Project includes -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/Endian.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h"  #include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h"  #include "lldb/Utility/NameMatches.h"  #include "llvm/Support/Host.h" @@ -54,15 +52,12 @@ using namespace lldb;  using namespace lldb_private;  size_t Host::GetEnvironment(StringList &env) { -  char *v; -  char **var = environ; -  for (; var != NULL && *var != NULL; ++var) { -    v = ::strchr(*var, (int)'-'); -    if (v == NULL) -      continue; -    env.AppendString(v); -  } -  return env.GetSize(); +  char **host_env = environ; +  char *env_entry; +  size_t i; +  for (i = 0; (env_entry = host_env[i]) != NULL; ++i) +    env.AppendString(env_entry); +  return i;  }  static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, @@ -259,10 +254,6 @@ bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {    return false;  } -lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { -  return lldb::DataBufferSP(); -} -  Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {    return Error("unimplemented");  } diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp index 3c1385ab562f..428183bbe2c3 100644 --- a/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/source/Host/netbsd/HostInfoNetBSD.cpp @@ -21,10 +21,6 @@  using namespace lldb_private; -uint32_t HostInfoNetBSD::GetMaxThreadNameLength() { -  return PTHREAD_MAX_NAMELEN_NP; -} -  bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor,                                    uint32_t &update) {    struct utsname un; @@ -85,15 +81,15 @@ FileSpec HostInfoNetBSD::GetProgramFileSpec() {    static FileSpec g_program_filespec;    if (!g_program_filespec) { -    ssize_t len; -    static char buf[PATH_MAX]; -    char name[PATH_MAX]; - -    ::snprintf(name, PATH_MAX, "/proc/%d/exe", ::getpid()); -    len = ::readlink(name, buf, PATH_MAX - 1); -    if (len != -1) { -      buf[len] = '\0'; -      g_program_filespec.SetFile(buf, false); +    static const int name[] = { +        CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME, +    }; +    char path[MAXPATHLEN]; +    size_t len; + +    len = sizeof(path); +    if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1) { +        g_program_filespec.SetFile(path, false);      }    }    return g_program_filespec; diff --git a/source/Host/netbsd/HostThreadNetBSD.cpp b/source/Host/netbsd/HostThreadNetBSD.cpp deleted file mode 100644 index e8c106b7f229..000000000000 --- a/source/Host/netbsd/HostThreadNetBSD.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-- HostThreadNetBSD.cpp -----------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// lldb Includes -#include "lldb/Host/netbsd/HostThreadNetBSD.h" -#include "lldb/Host/Host.h" - -// C includes -#include <errno.h> -#include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include <sys/sysctl.h> -#include <sys/user.h> - -// C++ includes -#include <string> - -using namespace lldb_private; - -HostThreadNetBSD::HostThreadNetBSD() {} - -HostThreadNetBSD::HostThreadNetBSD(lldb::thread_t thread) -    : HostThreadPosix(thread) {} - -void HostThreadNetBSD::SetName(lldb::thread_t thread, llvm::StringRef &name) { -  ::pthread_setname_np(thread, "%s", const_cast<char *>(name.data())); -} - -void HostThreadNetBSD::GetName(lldb::thread_t thread, -                               llvm::SmallVectorImpl<char> &name) { -  char buf[PTHREAD_MAX_NAMELEN_NP]; -  ::pthread_getname_np(thread, buf, PTHREAD_MAX_NAMELEN_NP); - -  name.clear(); -  name.append(buf, buf + strlen(buf)); -} diff --git a/source/Host/netbsd/ThisThread.cpp b/source/Host/netbsd/ThisThread.cpp deleted file mode 100644 index ea16981ef257..000000000000 --- a/source/Host/netbsd/ThisThread.cpp +++ /dev/null @@ -1,26 +0,0 @@ -//===-- ThisThread.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/ThisThread.h" -#include "lldb/Host/HostNativeThread.h" - -#include "llvm/ADT/SmallVector.h" - -#include <pthread.h> -#include <string.h> - -using namespace lldb_private; - -void ThisThread::SetName(llvm::StringRef name) { -  HostNativeThread::SetName(::pthread_self(), name); -} - -void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { -  HostNativeThread::GetName(::pthread_self(), name); -} diff --git a/source/Host/openbsd/Host.cpp b/source/Host/openbsd/Host.cpp new file mode 100644 index 000000000000..c9ff69366c2f --- /dev/null +++ b/source/Host/openbsd/Host.cpp @@ -0,0 +1,225 @@ +//===-- source/Host/openbsd/Host.cpp ----------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include <sys/types.h> + +#include <sys/signal.h> +#include <sys/exec.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/sysctl.h> +#include <sys/user.h> + +#include <stdio.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" + +#include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/NameMatches.h" + +#include "llvm/Support/Host.h" + +extern "C" { +extern char **environ; +} + +using namespace lldb; +using namespace lldb_private; + +size_t Host::GetEnvironment(StringList &env) { +  char *v; +  char **var = environ; +  for (; var != NULL && *var != NULL; ++var) { +    v = strchr(*var, (int)'-'); +    if (v == NULL) +      continue; +    env.AppendString(v); +  } +  return env.GetSize(); +} + +static bool +GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, +                      ProcessInstanceInfo &process_info) { +  if (process_info.ProcessIDIsValid()) { +    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, +                  (int)process_info.GetProcessID()}; + +    char arg_data[8192]; +    size_t arg_data_size = sizeof(arg_data); +    if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) { +      DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(), +                         sizeof(void *)); +      lldb::offset_t offset = 0; +      const char *cstr; + +      cstr = data.GetCStr(&offset); +      if (cstr) { +        process_info.GetExecutableFile().SetFile(cstr, false); + +        if (!(match_info_ptr == NULL || +              NameMatches( +                  process_info.GetExecutableFile().GetFilename().GetCString(), +                  match_info_ptr->GetNameMatchType(), +                  match_info_ptr->GetProcessInfo().GetName()))) +          return false; + +        Args &proc_args = process_info.GetArguments(); +        while (1) { +          const uint8_t *p = data.PeekData(offset, 1); +          while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { +            ++offset; +            p = data.PeekData(offset, 1); +          } +          if (p == NULL || offset >= arg_data_size) +            return true; + +          cstr = data.GetCStr(&offset); +          if (cstr) +            proc_args.AppendArgument(llvm::StringRef(cstr)); +          else +            return true; +        } +      } +    } +  } +  return false; +} + +static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) { +  if (process_info.ProcessIDIsValid()) { +    process_info.GetArchitecture() = +        HostInfo::GetArchitecture(HostInfo::eArchKindDefault); +    return true; +  } +  process_info.GetArchitecture().Clear(); +  return false; +} + +static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { +  struct kinfo_proc proc_kinfo; +  size_t proc_kinfo_size; + +  if (process_info.ProcessIDIsValid()) { +    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, +                  (int)process_info.GetProcessID()}; +    proc_kinfo_size = sizeof(struct kinfo_proc); + +    if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { +      if (proc_kinfo_size > 0) { +        process_info.SetParentProcessID(proc_kinfo.p_ppid); +        process_info.SetUserID(proc_kinfo.p_ruid); +        process_info.SetGroupID(proc_kinfo.p_rgid); +        process_info.SetEffectiveUserID(proc_kinfo.p_uid); +	process_info.SetEffectiveGroupID(proc_kinfo.p_gid); +        return true; +      } +    } +  } +  process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID); +  process_info.SetUserID(UINT32_MAX); +  process_info.SetGroupID(UINT32_MAX); +  process_info.SetEffectiveUserID(UINT32_MAX); +  process_info.SetEffectiveGroupID(UINT32_MAX); +  return false; +} + +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, +                             ProcessInstanceInfoList &process_infos) { +  std::vector<struct kinfo_proc> kinfos; + +  int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + +  size_t pid_data_size = 0; +  if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0) +    return 0; + +  // Add a few extra in case a few more show up +  const size_t estimated_pid_count = +      (pid_data_size / sizeof(struct kinfo_proc)) + 10; + +  kinfos.resize(estimated_pid_count); +  pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); + +  if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) +    return 0; + +  const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); + +  bool all_users = match_info.GetMatchAllUsers(); +  const ::pid_t our_pid = getpid(); +  const uid_t our_uid = getuid(); +  for (size_t i = 0; i < actual_pid_count; i++) { +    const struct kinfo_proc &kinfo = kinfos[i]; +    const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) || +                                     // Special case, if lldb is being run as +                                     // root we can attach to anything. +                                     (our_uid == 0)); + +    if (kinfo_user_matches == false || // Make sure the user is acceptable +        kinfo.p_pid == our_pid ||     // Skip this process +        kinfo.p_pid == 0 ||           // Skip kernel (kernel pid is zero) +        kinfo.p_stat == SZOMB ||      // Zombies are bad, they like brains... +        kinfo.p_psflags & PS_TRACED || // Being debugged? +        kinfo.p_flag & P_WEXIT)       // Working on exiting +      continue; + +    ProcessInstanceInfo process_info; +    process_info.SetProcessID(kinfo.p_pid); +    process_info.SetParentProcessID(kinfo.p_ppid); +    process_info.SetUserID(kinfo.p_ruid); +    process_info.SetGroupID(kinfo.p_rgid); +    process_info.SetEffectiveUserID(kinfo.p_svuid); +    process_info.SetEffectiveGroupID(kinfo.p_svgid); + +    // Make sure our info matches before we go fetch the name and cpu type +    if (match_info.Matches(process_info) && +        GetOpenBSDProcessArgs(&match_info, process_info)) { +      GetOpenBSDProcessCPUType(process_info); +      if (match_info.Matches(process_info)) +        process_infos.Append(process_info); +    } +  } + +  return process_infos.GetSize(); +} + +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { +  process_info.SetProcessID(pid); + +  if (GetOpenBSDProcessArgs(NULL, process_info)) { +    // should use libprocstat instead of going right into sysctl? +    GetOpenBSDProcessCPUType(process_info); +    GetOpenBSDProcessUserAndGroup(process_info); +    return true; +  } + +  process_info.Clear(); +  return false; +} + +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { +  return Error("unimplemented"); +} diff --git a/source/Host/openbsd/HostInfoOpenBSD.cpp b/source/Host/openbsd/HostInfoOpenBSD.cpp new file mode 100644 index 000000000000..548958899322 --- /dev/null +++ b/source/Host/openbsd/HostInfoOpenBSD.cpp @@ -0,0 +1,65 @@ +//===-- HostInfoOpenBSD.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/openbsd/HostInfoOpenBSD.h" + +#include <stdio.h> +#include <string.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <sys/utsname.h> + +using namespace lldb_private; + +bool HostInfoOpenBSD::GetOSVersion(uint32_t &major, uint32_t &minor, +                                   uint32_t &update) { +  struct utsname un; + +  ::memset(&un, 0, sizeof(utsname)); +  if (uname(&un) < 0) +    return false; + +  int status = sscanf(un.release, "%u.%u", &major, &minor); +  return status == 2; +} + +bool HostInfoOpenBSD::GetOSBuildString(std::string &s) { +  int mib[2] = {CTL_KERN, KERN_OSREV}; +  char osrev_str[12]; +  uint32_t osrev = 0; +  size_t osrev_len = sizeof(osrev); + +  if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) { +    ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev); +    s.assign(osrev_str); +    return true; +  } + +  s.clear(); +  return false; +} + +bool HostInfoOpenBSD::GetOSKernelDescription(std::string &s) { +  struct utsname un; + +  ::memset(&un, 0, sizeof(utsname)); +  s.clear(); + +  if (uname(&un) < 0) +    return false; + +  s.assign(un.version); + +  return true; +} + +FileSpec HostInfoOpenBSD::GetProgramFileSpec() { +  static FileSpec g_program_filespec; +  return g_program_filespec; +} diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 64101fdc4267..a3ac36558e32 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -19,7 +19,6 @@  #include "lldb/Host/IOObject.h"  #include "lldb/Host/Socket.h"  #include "lldb/Host/SocketAddress.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Utility/SelectHelper.h"  // C Includes @@ -43,13 +42,12 @@  #endif  // Project includes  #include "lldb/Core/Communication.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Core/Timer.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/Socket.h"  #include "lldb/Host/common/TCPSocket.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h"  using namespace lldb;  using namespace lldb_private; @@ -561,10 +559,7 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,    // ever get used more generally we will need to lock here as well.    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); -  if (log) -    log->Printf( -        "%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %lu)", -        static_cast<void *>(this), long(timeout ? timeout->count() : -1)); +  LLDB_LOG(log, "this = {0}, timeout = {1}", this, timeout);    // Make a copy of the file descriptors to make sure we don't    // have another thread change these values out from under us @@ -753,14 +748,12 @@ ConnectionStatus ConnectionFileDescriptor::ConnectTCP(llvm::StringRef s,  ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s,                                                        Error *error_ptr) { -  Socket *send_socket = nullptr; -  Socket *recv_socket = nullptr; -  Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, -                                   recv_socket); +  Socket *socket = nullptr; +  Error error = Socket::UdpConnect(s, m_child_processes_inherit, socket);    if (error_ptr)      *error_ptr = error; -  m_write_sp.reset(send_socket); -  m_read_sp.reset(recv_socket); +  m_write_sp.reset(socket); +  m_read_sp = m_write_sp;    if (error.Fail()) {      return eConnectionStatusError;    } diff --git a/source/Host/posix/DomainSocket.cpp b/source/Host/posix/DomainSocket.cpp index cb0a1d057506..538979df2b6b 100644 --- a/source/Host/posix/DomainSocket.cpp +++ b/source/Host/posix/DomainSocket.cpp @@ -9,7 +9,7 @@  #include "lldb/Host/posix/DomainSocket.h" -#include "lldb/Host/FileSystem.h" +#include "llvm/Support/FileSystem.h"  #include <stddef.h>  #include <sys/socket.h> @@ -116,5 +116,5 @@ Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit,  size_t DomainSocket::GetNameOffset() const { return 0; }  void DomainSocket::DeleteSocketFile(llvm::StringRef name) { -  FileSystem::Unlink(FileSpec{name, true}); +  llvm::sys::fs::remove(name);  } diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp index aaa53ce07723..22f337fcfec5 100644 --- a/source/Host/posix/FileSystem.cpp +++ b/source/Host/posix/FileSystem.cpp @@ -25,149 +25,17 @@  #endif  // lldb Includes -#include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h"  #include "lldb/Host/Host.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/Support/FileSystem.h"  using namespace lldb;  using namespace lldb_private;  const char *FileSystem::DEV_NULL = "/dev/null"; -FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { -  return FileSpec::ePathSyntaxPosix; -} - -Error FileSystem::MakeDirectory(const FileSpec &file_spec, -                                uint32_t file_permissions) { -  if (file_spec) { -    Error error; -    if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { -      error.SetErrorToErrno(); -      errno = 0; -      switch (error.GetError()) { -      case ENOENT: { -        // Parent directory doesn't exist, so lets make it if we can -        // Make the parent directory and try again -        FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false}; -        error = MakeDirectory(parent_file_spec, file_permissions); -        if (error.Fail()) -          return error; -        // Try and make the directory again now that the parent directory was -        // made successfully -        if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { -          error.SetErrorToErrno(); -        } -        return error; -      } break; -      case EEXIST: { -        if (file_spec.IsDirectory()) -          return Error(); // It is a directory and it already exists -      } break; -      } -    } -    return error; -  } -  return Error("empty path"); -} - -Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { -  Error error; -  if (file_spec) { -    if (recurse) { -      // Save all sub directories in a list so we don't recursively call this -      // function -      // and possibly run out of file descriptors if the directory is too deep. -      std::vector<FileSpec> sub_directories; - -      FileSpec::ForEachItemInDirectory( -          file_spec.GetCString(), -          [&error, &sub_directories]( -              FileSpec::FileType file_type, -              const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult { -            if (file_type == FileSpec::eFileTypeDirectory) { -              // Save all directorires and process them after iterating through -              // this directory -              sub_directories.push_back(spec); -            } else { -              // Update sub_spec to point to the current file and delete it -              error = FileSystem::Unlink(spec); -            } -            // If anything went wrong, stop iterating, else process the next -            // file -            if (error.Fail()) -              return FileSpec::eEnumerateDirectoryResultQuit; -            else -              return FileSpec::eEnumerateDirectoryResultNext; -          }); - -      if (error.Success()) { -        // Now delete all sub directories with separate calls that aren't -        // recursively calling into this function _while_ this function is -        // iterating through the current directory. -        for (const auto &sub_directory : sub_directories) { -          error = DeleteDirectory(sub_directory, recurse); -          if (error.Fail()) -            break; -        } -      } -    } - -    if (error.Success()) { -      if (::rmdir(file_spec.GetCString()) != 0) -        error.SetErrorToErrno(); -    } -  } else { -    error.SetErrorString("empty path"); -  } -  return error; -} - -Error FileSystem::GetFilePermissions(const FileSpec &file_spec, -                                     uint32_t &file_permissions) { -  Error error; -  struct stat file_stats; -  if (::stat(file_spec.GetCString(), &file_stats) == 0) { -    // The bits in "st_mode" currently match the definitions -    // for the file mode bits in unix. -    file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); -  } else { -    error.SetErrorToErrno(); -  } -  return error; -} - -Error FileSystem::SetFilePermissions(const FileSpec &file_spec, -                                     uint32_t file_permissions) { -  Error error; -  if (::chmod(file_spec.GetCString(), file_permissions) != 0) -    error.SetErrorToErrno(); -  return error; -} - -lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { -  return file_spec.GetByteSize(); -} - -bool FileSystem::GetFileExists(const FileSpec &file_spec) { -  return file_spec.Exists(); -} - -Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { -  Error error; -  if (::link(dst.GetCString(), src.GetCString()) == -1) -    error.SetErrorToErrno(); -  return error; -} - -int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { -  struct stat file_stat; -  if (::stat(file_spec.GetCString(), &file_stat) == 0) -    return file_stat.st_nlink; - -  return -1; -} -  Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {    Error error;    if (::symlink(dst.GetCString(), src.GetCString()) == -1) @@ -175,13 +43,6 @@ Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {    return error;  } -Error FileSystem::Unlink(const FileSpec &file_spec) { -  Error error; -  if (::unlink(file_spec.GetCString()) == -1) -    error.SetErrorToErrno(); -  return error; -} -  Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {    Error error;    char buf[PATH_MAX]; @@ -213,50 +74,6 @@ Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {    return Error();  } -#if defined(__NetBSD__) -static bool IsLocal(const struct statvfs &info) { -  return (info.f_flag & MNT_LOCAL) != 0; -} -#else -static bool IsLocal(const struct statfs &info) { -#ifdef __linux__ -#define CIFS_MAGIC_NUMBER 0xFF534D42 -  switch ((uint32_t)info.f_type) { -  case NFS_SUPER_MAGIC: -  case SMB_SUPER_MAGIC: -  case CIFS_MAGIC_NUMBER: -    return false; -  default: -    return true; -  } -#else -  return (info.f_flags & MNT_LOCAL) != 0; -#endif -} -#endif - -#if defined(__NetBSD__) -bool FileSystem::IsLocal(const FileSpec &spec) { -  struct statvfs statfs_info; -  std::string path(spec.GetPath()); -  if (statvfs(path.c_str(), &statfs_info) == 0) -    return ::IsLocal(statfs_info); -  return false; -} -#else -bool FileSystem::IsLocal(const FileSpec &spec) { -  struct statfs statfs_info; -  std::string path(spec.GetPath()); -  if (statfs(path.c_str(), &statfs_info) == 0) -    return ::IsLocal(statfs_info); -  return false; -} -#endif -  FILE *FileSystem::Fopen(const char *path, const char *mode) {    return ::fopen(path, mode);  } - -int FileSystem::Stat(const char *path, struct stat *stats) { -  return ::stat(path, stats); -} diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index 38aac59ecc40..da9e1fb366cc 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -11,8 +11,8 @@  #include "Plugins/ScriptInterpreter/Python/lldb-python.h"  #endif -#include "lldb/Core/Log.h"  #include "lldb/Host/posix/HostInfoPosix.h" +#include "lldb/Utility/Log.h"  #include "clang/Basic/Version.h"  #include "clang/Config/config.h" diff --git a/source/Host/posix/HostThreadPosix.cpp b/source/Host/posix/HostThreadPosix.cpp index ac398998c20f..073b7b0b11e8 100644 --- a/source/Host/posix/HostThreadPosix.cpp +++ b/source/Host/posix/HostThreadPosix.cpp @@ -8,7 +8,7 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/posix/HostThreadPosix.h" -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h"  #include <errno.h>  #include <pthread.h> diff --git a/source/Host/posix/MainLoopPosix.cpp b/source/Host/posix/MainLoopPosix.cpp index 08c969e72a26..a73187e730f0 100644 --- a/source/Host/posix/MainLoopPosix.cpp +++ b/source/Host/posix/MainLoopPosix.cpp @@ -8,13 +8,13 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/posix/MainLoopPosix.h" -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h"  #include <algorithm>  #include <cassert>  #include <cerrno>  #include <csignal> -#include <vector>  #include <sys/select.h> +#include <vector>  using namespace lldb;  using namespace lldb_private; diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index 4e0810c1a9b3..3ac5d480de89 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -8,7 +8,6 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/posix/PipePosix.h" -#include "lldb/Host/FileSystem.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Utility/SelectHelper.h"  #include "llvm/ADT/SmallString.h" @@ -231,7 +230,7 @@ void PipePosix::Close() {  }  Error PipePosix::Delete(llvm::StringRef name) { -  return FileSystem::Unlink(FileSpec{name.data(), true}); +  return llvm::sys::fs::remove(name);  }  bool PipePosix::CanRead() const { diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp new file mode 100644 index 000000000000..91c32d6e6426 --- /dev/null +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -0,0 +1,231 @@ +//===-- ProcessLauncherLinux.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/posix/ProcessLauncherPosixFork.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/Pipe.h" +#include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" + +#include <limits.h> +#include <sys/ptrace.h> +#include <sys/wait.h> + +#include <sstream> + +#ifdef __ANDROID__ +#include <android/api-level.h> +#define PT_TRACE_ME PTRACE_TRACEME +#endif + +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +#include <linux/personality.h> +#elif defined(__linux__) +#include <sys/personality.h> +#endif + +using namespace lldb; +using namespace lldb_private; + +static void FixupEnvironment(Args &env) { +#ifdef __ANDROID__ +  // If there is no PATH variable specified inside the environment then set the +  // path to /system/bin. It is required because the default path used by +  // execve() is wrong on android. +  static const char *path = "PATH="; +  for (auto &entry : env.entries()) { +    if (entry.ref.startswith(path)) +      return; +  } +  env.AppendArgument(llvm::StringRef("PATH=/system/bin")); +#endif +} + +static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd, +                                                  const char *operation) { +  std::ostringstream os; +  os << operation << " failed: " << strerror(errno); +  write(error_fd, os.str().data(), os.str().size()); +  close(error_fd); +  _exit(1); +} + +static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info) { +#if defined(__linux__) +  if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) { +    const unsigned long personality_get_current = 0xffffffff; +    int value = personality(personality_get_current); +    if (value == -1) +      ExitWithError(error_fd, "personality get"); + +    value = personality(ADDR_NO_RANDOMIZE | value); +    if (value == -1) +      ExitWithError(error_fd, "personality set"); +  } +#endif +} + +static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, +                          int flags) { +  int target_fd = ::open(file_spec.GetCString(), flags, 0666); + +  if (target_fd == -1) +    ExitWithError(error_fd, "DupDescriptor-open"); + +  if (target_fd == fd) +    return; + +  if (::dup2(target_fd, fd) == -1) +    ExitWithError(error_fd, "DupDescriptor-dup2"); + +  ::close(target_fd); +  return; +} + +static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, +                                              const ProcessLaunchInfo &info) { +  // First, make sure we disable all logging. If we are logging to stdout, our +  // logs can be mistaken for inferior output. +  Log::DisableAllLogChannels(); + +  // Do not inherit setgid powers. +  if (setgid(getgid()) != 0) +    ExitWithError(error_fd, "setgid"); + +  if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) { +    if (setpgid(0, 0) != 0) +      ExitWithError(error_fd, "setpgid"); +  } + +  for (size_t i = 0; i < info.GetNumFileActions(); ++i) { +    const FileAction &action = *info.GetFileActionAtIndex(i); +    switch (action.GetAction()) { +    case FileAction::eFileActionClose: +      if (close(action.GetFD()) != 0) +        ExitWithError(error_fd, "close"); +      break; +    case FileAction::eFileActionDuplicate: +      if (dup2(action.GetFD(), action.GetActionArgument()) == -1) +        ExitWithError(error_fd, "dup2"); +      break; +    case FileAction::eFileActionOpen: +      DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(), +                    action.GetActionArgument()); +      break; +    case FileAction::eFileActionNone: +      break; +    } +  } + +  const char **argv = info.GetArguments().GetConstArgumentVector(); + +  // Change working directory +  if (info.GetWorkingDirectory() && +      0 != ::chdir(info.GetWorkingDirectory().GetCString())) +    ExitWithError(error_fd, "chdir"); + +  DisableASLRIfRequested(error_fd, info); +  Args env = info.GetEnvironmentEntries(); +  FixupEnvironment(env); +  const char **envp = env.GetConstArgumentVector(); + +  // Clear the signal mask to prevent the child from being affected by +  // any masking done by the parent. +  sigset_t set; +  if (sigemptyset(&set) != 0 || +      pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) +    ExitWithError(error_fd, "pthread_sigmask"); + +  if (info.GetFlags().Test(eLaunchFlagDebug)) { +    // HACK: +    // Close everything besides stdin, stdout, and stderr that has no file +    // action to avoid leaking. Only do this when debugging, as elsewhere we +    // actually rely on +    // passing open descriptors to child processes. +    for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) +      if (!info.GetFileActionForFD(fd) && fd != error_fd) +        close(fd); + +    // Start tracing this child that is about to exec. +    if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) +      ExitWithError(error_fd, "ptrace"); +  } + +  // Execute.  We should never return... +  execve(argv[0], const_cast<char *const *>(argv), +         const_cast<char *const *>(envp)); + +#if defined(__linux__) +  if (errno == ETXTBSY) { +    // On android M and earlier we can get this error because the adb deamon 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 running the test suite. (The file remains open when +    // someone does +    // an "adb shell" command in the fork() child before it has had a chance to +    // exec.) Since +    // this state should clear up quickly, wait a while and then give it one +    // more go. +    usleep(50000); +    execve(argv[0], const_cast<char *const *>(argv), +           const_cast<char *const *>(envp)); +  } +#endif + +  // ...unless exec fails.  In which case we definitely need to end the child +  // here. +  ExitWithError(error_fd, "execve"); +} + +HostProcess +ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, +                                        Error &error) { +  char exe_path[PATH_MAX]; +  launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + +  // A pipe used by the child process to report errors. +  PipePosix pipe; +  const bool child_processes_inherit = false; +  error = pipe.CreateNew(child_processes_inherit); +  if (error.Fail()) +    return HostProcess(); + +  ::pid_t pid = ::fork(); +  if (pid == -1) { +    // Fork failed +    error.SetErrorStringWithFormat("Fork failed with error message: %s", +                                   strerror(errno)); +    return HostProcess(LLDB_INVALID_PROCESS_ID); +  } +  if (pid == 0) { +    // child process +    pipe.CloseReadFileDescriptor(); +    ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info); +  } + +  // parent process + +  pipe.CloseWriteFileDescriptor(); +  char buf[1000]; +  int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf); + +  if (r == 0) +    return HostProcess(pid); // No error. We're done. + +  error.SetErrorString(buf); + +  waitpid(pid, nullptr, 0); + +  return HostProcess(); +} diff --git a/source/Host/windows/ConnectionGenericFileWindows.cpp b/source/Host/windows/ConnectionGenericFileWindows.cpp index 5d48a1c867ad..8fc038f3f9b6 100644 --- a/source/Host/windows/ConnectionGenericFileWindows.cpp +++ b/source/Host/windows/ConnectionGenericFileWindows.cpp @@ -8,8 +8,9 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/windows/ConnectionGenericFileWindows.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Timeout.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringRef.h" diff --git a/source/Host/windows/FileSystem.cpp b/source/Host/windows/FileSystem.cpp index f0ba7376876d..092b70b1f4dc 100644 --- a/source/Host/windows/FileSystem.cpp +++ b/source/Host/windows/FileSystem.cpp @@ -15,6 +15,7 @@  #include "lldb/Host/FileSystem.h"  #include "lldb/Host/windows/AutoHandle.h" +#include "lldb/Host/windows/PosixApi.h"  #include "llvm/Support/ConvertUTF.h"  #include "llvm/Support/FileSystem.h" @@ -26,126 +27,6 @@ const char *FileSystem::DEV_NULL = "nul";  const char *FileSystem::PATH_CONVERSION_ERROR =      "Error converting path between UTF-8 and native encoding"; -FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { -  return FileSpec::ePathSyntaxWindows; -} - -Error FileSystem::MakeDirectory(const FileSpec &file_spec, -                                uint32_t file_permissions) { -  // On Win32, the mode parameter is ignored, as Windows files and directories -  // support a -  // different permission model than POSIX. -  Error error; -  const auto err_code = -      llvm::sys::fs::create_directories(file_spec.GetPath(), true); -  if (err_code) { -    error.SetErrorString(err_code.message().c_str()); -  } - -  return error; -} - -Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { -  Error error; -  std::wstring path_buffer; -  if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) { -    error.SetErrorString(PATH_CONVERSION_ERROR); -    return error; -  } -  if (!recurse) { -    BOOL result = ::RemoveDirectoryW(path_buffer.c_str()); -    if (!result) -      error.SetError(::GetLastError(), lldb::eErrorTypeWin32); -  } else { -    // SHFileOperation() accepts a list of paths, and so must be -    // double-null-terminated to -    // indicate the end of the list. The first null terminator is there only in -    // the backing -    // store but not the actual vector contents, and so we need to push twice. -    path_buffer.push_back(0); -    path_buffer.push_back(0); - -    SHFILEOPSTRUCTW shfos = {}; -    shfos.wFunc = FO_DELETE; -    shfos.pFrom = (LPCWSTR)path_buffer.data(); -    shfos.fFlags = FOF_NO_UI; - -    int result = ::SHFileOperationW(&shfos); -    // TODO(zturner): Correctly handle the intricacies of SHFileOperation return -    // values. -    if (result != 0) -      error.SetErrorStringWithFormat("SHFileOperation failed"); -  } -  return error; -} - -Error FileSystem::GetFilePermissions(const FileSpec &file_spec, -                                     uint32_t &file_permissions) { -  Error error; -  // Beware that Windows's permission model is different from Unix's, and it's -  // not clear if this API is supposed to check ACLs.  To match the caller's -  // expectations as closely as possible, we'll use Microsoft's _stat, which -  // attempts to emulate POSIX stat.  This should be good enough for basic -  // checks like FileSpec::Readable. -  struct _stat file_stats; -  if (::_stat(file_spec.GetCString(), &file_stats) == 0) { -    // The owner permission bits in "st_mode" currently match the definitions -    // for the owner file mode bits. -    file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC); -  } else { -    error.SetErrorToErrno(); -  } - -  return error; -} - -Error FileSystem::SetFilePermissions(const FileSpec &file_spec, -                                     uint32_t file_permissions) { -  Error error; -  error.SetErrorStringWithFormat("%s is not supported on this host", -                                 LLVM_PRETTY_FUNCTION); -  return error; -} - -lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { -  return file_spec.GetByteSize(); -} - -bool FileSystem::GetFileExists(const FileSpec &file_spec) { -  return file_spec.Exists(); -} - -Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { -  Error error; -  std::wstring wsrc, wdst; -  if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || -      !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) -    error.SetErrorString(PATH_CONVERSION_ERROR); -  else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr)) -    error.SetError(::GetLastError(), lldb::eErrorTypeWin32); -  return error; -} - -int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { -  std::wstring path; -  if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) -    return -1; - -  HANDLE file_handle = -      ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, -                    nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - -  if (file_handle == INVALID_HANDLE_VALUE) -    return -1; - -  AutoHandle auto_file_handle(file_handle); -  BY_HANDLE_FILE_INFORMATION file_info; -  if (::GetFileInformationByHandle(file_handle, &file_info)) -    return file_info.nNumberOfLinks; - -  return -1; -} -  Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {    Error error;    std::wstring wsrc, wdst; @@ -167,19 +48,6 @@ Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {    return error;  } -Error FileSystem::Unlink(const FileSpec &file_spec) { -  Error error; -  std::wstring path; -  if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) { -    error.SetErrorString(PATH_CONVERSION_ERROR); -    return error; -  } -  BOOL result = ::DeleteFileW(path.c_str()); -  if (!result) -    error.SetError(::GetLastError(), lldb::eErrorTypeWin32); -  return error; -} -  Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {    Error error;    std::wstring wsrc; @@ -217,15 +85,6 @@ Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {    return Error("ResolveSymbolicLink() isn't implemented on Windows");  } -bool FileSystem::IsLocal(const FileSpec &spec) { -  if (spec) { -    // TODO: return true if the file is on a locally mounted file system -    return true; -  } - -  return false; -} -  FILE *FileSystem::Fopen(const char *path, const char *mode) {    std::wstring wpath, wmode;    if (!llvm::ConvertUTF8toWide(path, wpath)) @@ -237,25 +96,3 @@ FILE *FileSystem::Fopen(const char *path, const char *mode) {      return nullptr;    return file;  } - -int FileSystem::Stat(const char *path, struct stat *stats) { -  std::wstring wpath; -  if (!llvm::ConvertUTF8toWide(path, wpath)) { -    errno = EINVAL; -    return -EINVAL; -  } -  int stat_result; -#ifdef _USE_32BIT_TIME_T -  struct _stat32 file_stats; -  stat_result = ::_wstat32(wpath.c_str(), &file_stats); -#else -  struct _stat64i32 file_stats; -  stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); -#endif -  if (stat_result == 0) { -    static_assert(sizeof(struct stat) == sizeof(file_stats), -                  "stat and _stat32/_stat64i32 must have the same layout"); -    *stats = *reinterpret_cast<struct stat *>(&file_stats); -  } -  return stat_result; -} diff --git a/source/Host/windows/Host.cpp b/source/Host/windows/Host.cpp index 3da073605dcb..9a6957b2a1ff 100644 --- a/source/Host/windows/Host.cpp +++ b/source/Host/windows/Host.cpp @@ -15,16 +15,16 @@  // C++ Includes  // Other libraries and framework includes  // Project includes -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h"  #include "lldb/Target/Process.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h"  #include "lldb/Core/StreamFile.h"  #include "lldb/Core/StructuredData.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h"  #include "llvm/Support/ConvertUTF.h" @@ -97,14 +97,6 @@ void GetProcessExecutableAndTriple(const AutoHandle &handle,  }  } -lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { -  return 0; -} - -lldb::tid_t Host::GetCurrentThreadID() { -  return lldb::tid_t(::GetCurrentThreadId()); -} -  lldb::thread_t Host::GetCurrentThread() {    return lldb::thread_t(::GetCurrentThread());  } diff --git a/source/Host/windows/HostInfoWindows.cpp b/source/Host/windows/HostInfoWindows.cpp index a965ec0ea4e2..53a24ad1893e 100644 --- a/source/Host/windows/HostInfoWindows.cpp +++ b/source/Host/windows/HostInfoWindows.cpp @@ -14,10 +14,12 @@  #include <mutex> // std::once  #include "lldb/Host/windows/HostInfoWindows.h" +#include "lldb/Host/windows/PosixApi.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Support/ConvertUTF.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/Path.h" +#include "llvm/Support/Threading.h"  #include "llvm/Support/raw_ostream.h"  using namespace lldb_private; @@ -90,8 +92,8 @@ bool HostInfoWindows::GetHostname(std::string &s) {  }  FileSpec HostInfoWindows::GetProgramFileSpec() { -  static std::once_flag g_once_flag; -  std::call_once(g_once_flag, []() { +  static llvm::once_flag g_once_flag; +  llvm::call_once(g_once_flag, []() {      std::vector<wchar_t> buffer(PATH_MAX);      ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());      std::string path; diff --git a/source/Host/windows/HostProcessWindows.cpp b/source/Host/windows/HostProcessWindows.cpp index 8201d53bd27c..3bbc84a4ca59 100644 --- a/source/Host/windows/HostProcessWindows.cpp +++ b/source/Host/windows/HostProcessWindows.cpp @@ -8,10 +8,10 @@  //===----------------------------------------------------------------------===//  #include "lldb/Host/windows/HostProcessWindows.h" -#include "lldb/Host/FileSpec.h"  #include "lldb/Host/HostThread.h"  #include "lldb/Host/ThreadLauncher.h"  #include "lldb/Host/windows/windows.h" +#include "lldb/Utility/FileSpec.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/Support/ConvertUTF.h" diff --git a/source/Host/windows/HostThreadWindows.cpp b/source/Host/windows/HostThreadWindows.cpp index 41be21bfa304..aa791714c338 100644 --- a/source/Host/windows/HostThreadWindows.cpp +++ b/source/Host/windows/HostThreadWindows.cpp @@ -7,7 +7,7 @@  //  //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h"  #include "lldb/Host/windows/HostThreadWindows.h"  #include "lldb/Host/windows/windows.h" diff --git a/source/Host/windows/ThisThread.cpp b/source/Host/windows/ThisThread.cpp deleted file mode 100644 index 8db12f05b0ba..000000000000 --- a/source/Host/windows/ThisThread.cpp +++ /dev/null @@ -1,63 +0,0 @@ -//===-- ThisThread.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/Core/Error.h" - -#include "lldb/Host/ThisThread.h" -#include "lldb/Host/windows/windows.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" - -using namespace lldb; -using namespace lldb_private; - -#if defined(_MSC_VER) && !defined(__clang__) - -namespace { -static const DWORD MS_VC_EXCEPTION = 0x406D1388; - -#pragma pack(push, 8) -struct THREADNAME_INFO { -  DWORD dwType;     // Must be 0x1000. -  LPCSTR szName;    // Pointer to thread name -  DWORD dwThreadId; // Thread ID (-1 == current thread) -  DWORD dwFlags;    // Reserved.  Do not use. -}; -#pragma pack(pop) -} - -#endif - -void ThisThread::SetName(llvm::StringRef name) { -// Other compilers don't yet support SEH, so we can only set the thread if -// compiling with MSVC. -// TODO(zturner): Once clang-cl supports SEH, relax this conditional. -#if defined(_MSC_VER) && !defined(__clang__) -  THREADNAME_INFO info; -  info.dwType = 0x1000; -  info.szName = name.data(); -  info.dwThreadId = ::GetCurrentThreadId(); -  info.dwFlags = 0; - -  __try { -    ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), -                     (ULONG_PTR *)&info); -  } __except (EXCEPTION_EXECUTE_HANDLER) { -  } -#endif -} - -void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { -  // Getting the thread name is not supported on Windows. -  // TODO(zturner): In SetName(), make a TLS entry that contains the thread's -  // name, and in this function -  // try to extract that TLS entry. -  name.clear(); -} diff --git a/source/Host/windows/Windows.cpp b/source/Host/windows/Windows.cpp index 21afc6d85da5..9d0e70e6d126 100644 --- a/source/Host/windows/Windows.cpp +++ b/source/Host/windows/Windows.cpp @@ -23,13 +23,6 @@  #include <stdlib.h>  #include <string.h> -// These prototypes are defined in <direct.h>, but it also defines chdir() and -// getcwd(), giving multiply defined errors -extern "C" { -char *_getcwd(char *buffer, int maxlen); -int _chdir(const char *path); -} -  namespace {  bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) {    const llvm::UTF8 *sourceStart = reinterpret_cast<const llvm::UTF8 *>(utf8); @@ -190,31 +183,6 @@ char *basename(char *path) {    return &l1[1];  } -// use _getcwd() instead of GetCurrentDirectory() because it updates errno -char *getcwd(char *path, int max) { -  assert(path == NULL || max <= PATH_MAX); -  wchar_t wpath[PATH_MAX]; -  if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) { -    // Caller is allowed to pass in NULL for `path`. -    // In that case, we're supposed to allocate a -    // buffer on the caller's behalf. -    if (path == NULL) { -      max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1; -      path = (char *)malloc(max); -      if (path == NULL) { -        errno = ENOMEM; -        return NULL; -      } -    } -    if (wideToUtf8(wresult, path, max)) -      return path; -  } -  return NULL; -} - -// use _chdir() instead of SetCurrentDirectory() because it updates errno -int chdir(const char *path) { return _chdir(path); } -  char *dirname(char *path) {    char *l1 = strrchr(path, '\\');    char *l2 = strrchr(path, '/');  | 
