diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
| commit | f73363f1dd94996356cefbf24388f561891acf0b (patch) | |
| tree | e3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Host | |
| parent | 160ee69dd7ae18978f4068116777639ea98dc951 (diff) | |
Notes
Diffstat (limited to 'source/Host')
49 files changed, 858 insertions, 1444 deletions
diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index 2b6f0e48a3f20..5a92447edf308 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -3,6 +3,18 @@ macro(add_host_subdirectory group) source_group(${group} FILES ${ARGN}) endmacro() +# Removes all module flags from the current CMAKE_CXX_FLAGS. Used for +# the Objective-C++ code in lldb which we don't want to build with modules. +# Reasons for this are that modules with Objective-C++ would require that +# all LLVM/Clang modules are Objective-C++ compatible (which they are likely +# not) and we would have rebuild a second set of modules just for the few +# Objective-C++ files in lldb (which slows down the build process). +macro(remove_module_flags) + string(REGEX REPLACE "-fmodules-cache-path=[^ ]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "-fmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "-fcxx-modules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endmacro() + add_host_subdirectory(common common/File.cpp common/FileCache.cpp @@ -39,11 +51,6 @@ add_host_subdirectory(common common/UDPSocket.cpp ) -# Keep track of whether we want to provide a define for the -# Python's architecture-specific lib path (i.e. where a -# Python lldb module would go). -set (get_python_libdir 0) - if (NOT LLDB_DISABLE_LIBEDIT) add_host_subdirectory(common common/Editline.cpp @@ -54,10 +61,6 @@ 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 @@ -74,11 +77,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") windows/Windows.cpp ) else() - if (NOT LLDB_DISABLE_PYTHON) - # We'll grab the arch-specific python libdir on POSIX systems. - set (get_python_libdir 1) - endif() - add_host_subdirectory(posix posix/DomainSocket.cpp posix/FileSystem.cpp @@ -92,10 +90,9 @@ else() if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) - add_host_subdirectory(macosx - macosx/Host.mm - macosx/HostInfoMacOSX.mm - macosx/HostThreadMacOSX.mm + add_subdirectory(macosx/objcxx) + set(LLDBObjCLibs lldbHostMacOSXObjCXX) + add_host_subdirectory(maqcosx macosx/Symbols.cpp macosx/cfcpp/CFCBundle.cpp macosx/cfcpp/CFCData.cpp @@ -144,19 +141,6 @@ else() endif() endif() -if (${get_python_libdir}) - # Call a python script to gather the arch-specific libdir for - # modules like the lldb module. - execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/get_relative_lib_dir.py - RESULT_VARIABLE get_libdir_status - OUTPUT_VARIABLE relative_libdir - ) - if (get_libdir_status EQUAL 0) - add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${relative_libdir}") - endif() -endif() - set(EXTRA_LIBS) if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") list(APPEND EXTRA_LIBS kvm) @@ -177,16 +161,16 @@ endif() add_lldb_library(lldbHost ${HOST_SOURCES} - + LINK_LIBS lldbCore - lldbInterpreter lldbSymbol lldbTarget lldbUtility - ${LLDB_PLUGINS} ${EXTRA_LIBS} - + ${LLDBObjCLibs} + LINK_COMPONENTS + Object Support ) diff --git a/source/Host/android/HostInfoAndroid.cpp b/source/Host/android/HostInfoAndroid.cpp index 27ce17a76d70c..a960332832126 100644 --- a/source/Host/android/HostInfoAndroid.cpp +++ b/source/Host/android/HostInfoAndroid.cpp @@ -79,13 +79,10 @@ bool HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) { bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); // On Android, there is no path which is guaranteed to be writable. If the - // user has not - // provided a path via an environment variable, the generic algorithm will - // deduce /tmp, which - // is plain wrong. In that case we have an invalid directory, we substitute - // the path with - // /data/local/tmp, which is correct at least in some cases (i.e., when - // running as shell user). + // user has not provided a path via an environment variable, the generic + // algorithm will deduce /tmp, which is plain wrong. In that case we have an + // invalid directory, we substitute the path with /data/local/tmp, which is + // correct at least in some cases (i.e., when running as shell user). if (!success || !file_spec.Exists()) file_spec = FileSpec("/data/local/tmp", false); diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index 7b580dde656ac..329c0c1f3b707 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -33,8 +33,8 @@ using namespace lldb_private::line_editor; // doesn't explicitly initialize the curses termcap library, which it gets away // with until TERM is set to VT100 where it stumbles over an implementation // assumption that may not exist on other platforms. The setupterm() function -// would normally require headers that don't work gracefully in this context, so -// the function declaraction has been hoisted here. +// would normally require headers that don't work gracefully in this context, +// so the function declaraction has been hoisted here. #if defined(__APPLE__) extern "C" { int setupterm(char *term, int fildes, int *errret); @@ -43,12 +43,10 @@ int setupterm(char *term, int fildes, int *errret); #endif // Editline uses careful cursor management to achieve the illusion of editing a -// multi-line block of text -// with a single line editor. Preserving this illusion requires fairly careful -// management of cursor -// state. Read and understand the relationship between DisplayInput(), -// MoveCursor(), SetCurrentLine(), -// and SaveEditedLine() before making changes. +// multi-line block of text with a single line editor. Preserving this +// illusion requires fairly careful management of cursor state. Read and +// understand the relationship between DisplayInput(), MoveCursor(), +// SetCurrentLine(), and SaveEditedLine() before making changes. #define ESCAPE "\x1b" #define ANSI_FAINT ESCAPE "[2m" @@ -70,8 +68,7 @@ int setupterm(char *term, int fildes, int *errret); #define EditLineStringFormatSpec "%s" // use #defines so wide version functions and structs will resolve to old -// versions -// for case of libedit not built with wide char support +// versions for case of libedit not built with wide char support #define history_w history #define history_winit history_init #define history_wend history_end @@ -145,10 +142,8 @@ bool IsInputPending(FILE *file) { // FIXME: This will be broken on Windows if we ever re-enable Editline. You // can't use select // on something that isn't a socket. This will have to be re-written to not - // use a FILE*, but - // instead use some kind of yet-to-be-created abstraction that select-like - // functionality on - // non-socket objects. + // use a FILE*, but instead use some kind of yet-to-be-created abstraction + // that select-like functionality on non-socket objects. const int fd = fileno(file); SelectHelper select_helper; select_helper.SetTimeout(std::chrono::microseconds(0)); @@ -160,13 +155,13 @@ namespace lldb_private { namespace line_editor { typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP; -// EditlineHistory objects are sometimes shared between multiple -// Editline instances with the same program name. +// EditlineHistory objects are sometimes shared between multiple Editline +// instances with the same program name. class EditlineHistory { private: - // Use static GetHistory() function to get a EditlineHistorySP to one of these - // objects + // Use static GetHistory() function to get a EditlineHistorySP to one of + // these objects EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) : m_history(NULL), m_event(), m_prefix(prefix), m_path() { m_history = history_winit(); @@ -436,11 +431,10 @@ unsigned char Editline::RecallHistory(bool earlier) { if (history_w(pHistory, &history_event, H_FIRST) == -1) return CC_ERROR; - // Save any edits to the "live" entry in case we return by moving forward in - // history - // (it would be more bash-like to save over any current entry, but libedit - // doesn't - // offer the ability to add entries anywhere except the end.) + // Save any edits to the "live" entry in case we return by moving forward + // in history (it would be more bash-like to save over any current entry, + // but libedit doesn't offer the ability to add entries anywhere except the + // end.) SaveEditedLine(); m_live_history_lines = m_input_lines; m_in_history = true; @@ -466,8 +460,7 @@ unsigned char Editline::RecallHistory(bool earlier) { DisplayInput(); // Prepare to edit the last line when moving to previous entry, or the first - // line - // when moving to next entry + // line when moving to next entry SetCurrentLine(m_current_line_index = earlier ? (int)m_input_lines.size() - 1 : 0); MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); @@ -490,8 +483,8 @@ int Editline::GetCharacter(EditLineGetCharType *c) { } if (m_multiline_enabled) { - // Detect when the number of rows used for this input line changes due to an - // edit + // Detect when the number of rows used for this input line changes due to + // an edit int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); int new_line_rows = (lineLength / m_terminal_width) + 1; if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) { @@ -510,12 +503,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) { char ch = 0; // This mutex is locked by our caller (GetLine). Unlock it while we read a - // character - // (blocking operation), so we do not hold the mutex indefinitely. This - // gives a chance - // for someone to interrupt us. After Read returns, immediately lock the - // mutex again and - // check if we were interrupted. + // character (blocking operation), so we do not hold the mutex + // indefinitely. This gives a chance for someone to interrupt us. After + // Read returns, immediately lock the mutex again and check if we were + // interrupted. m_output_mutex.unlock(); int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); m_output_mutex.lock(); @@ -614,7 +605,8 @@ unsigned char Editline::EndOrAddLineCommand(int ch) { // Save any edits to this line SaveEditedLine(); - // If this is the end of the last line, consider whether to add a line instead + // If this is the end of the last line, consider whether to add a line + // instead const LineInfoW *info = el_wline(m_editline); if (m_current_line_index == m_input_lines.size() - 1 && info->cursor == info->lastchar) { @@ -653,8 +645,8 @@ unsigned char Editline::DeleteNextCharCommand(int ch) { return CC_REFRESH; } - // Fail when at the end of the last line, except when ^D is pressed on - // the line is empty, in which case it is treated as EOF + // Fail when at the end of the last line, except when ^D is pressed on the + // line is empty, in which case it is treated as EOF if (m_current_line_index == m_input_lines.size() - 1) { if (ch == 4 && info->buffer == info->lastchar) { fprintf(m_output_file, "^D\n"); @@ -685,7 +677,8 @@ unsigned char Editline::DeleteNextCharCommand(int ch) { unsigned char Editline::DeletePreviousCharCommand(int ch) { LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); - // Just delete the previous character normally when not at the start of a line + // Just delete the previous character normally when not at the start of a + // line if (info->cursor > info->buffer) { el_deletestr(m_editline, 1); return CC_REFRESH; @@ -709,8 +702,7 @@ unsigned char Editline::DeletePreviousCharCommand(int ch) { DisplayInput(m_current_line_index); // Put the cursor back where libedit expects it to be before returning to - // editing - // by telling libedit about the newly inserted text + // editing by telling libedit about the newly inserted text MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); el_winsertstr(m_editline, priorLine.c_str()); return CC_REDISPLAY; @@ -762,7 +754,8 @@ unsigned char Editline::NextLineCommand(int ch) { EditLineStringType(indentation, EditLineCharType(' '))); } - // Move down past the current line using newlines to force scrolling if needed + // Move down past the current line using newlines to force scrolling if + // needed SetCurrentLine(m_current_line_index + 1); const LineInfoW *info = el_wline(m_editline); int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); @@ -824,8 +817,7 @@ unsigned char Editline::FixIndentationCommand(int ch) { DisplayInput(m_current_line_index); // Reposition the cursor back on the original line and prepare to restart - // editing - // with a new cursor position + // editing with a new cursor position SetCurrentLine(m_current_line_index); MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); m_revert_cursor_index = cursor_position + indent_correction; @@ -945,9 +937,9 @@ void Editline::ConfigureEditor(bool multiline) { m_multiline_enabled = multiline; if (m_editline) { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. + // Disable edit mode to stop the terminal from flushing all input during + // the call to el_end() since we expect to have multiple editline instances + // in this program. el_set(m_editline, EL_EDITMODE, 0); el_end(m_editline); } @@ -973,7 +965,8 @@ void Editline::ConfigureEditor(bool multiline) { return Editline::InstanceFor(editline)->GetCharacter(c); })); - // Commands used for multiline support, registered whether or not they're used + // Commands used for multiline support, registered whether or not they're + // used el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), EditLineConstString("Insert a line break"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { @@ -1031,13 +1024,11 @@ void Editline::ConfigureEditor(bool multiline) { return Editline::InstanceFor(editline)->FixIndentationCommand(ch); })); - // Register the complete callback under two names for compatibility with older - // clients using - // custom .editrc files (largely because libedit has a bad bug where if you - // have a bind command - // that tries to bind to a function name that doesn't exist, it can corrupt - // the heap and - // crash your process later.) + // Register the complete callback under two names for compatibility with + // older clients using custom .editrc files (largely because libedit has a + // bad bug where if you have a bind command that tries to bind to a function + // name that doesn't exist, it can corrupt the heap and crash your process + // later.) EditlineCommandCallbackType complete_callback = [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->TabCommand(ch); @@ -1118,8 +1109,7 @@ void Editline::ConfigureEditor(bool multiline) { NULL); // Escape is absorbed exiting edit mode, so re-register important - // sequences - // without the prefix + // sequences without the prefix el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); @@ -1176,18 +1166,18 @@ Editline::Editline(const char *editline_name, FILE *input_file, Editline::~Editline() { if (m_editline) { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. + // Disable edit mode to stop the terminal from flushing all input during + // the call to el_end() since we expect to have multiple editline instances + // in this program. el_set(m_editline, EL_EDITMODE, 0); el_end(m_editline); m_editline = nullptr; } - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. So just release - // our shared pointer and if we are the last owner, it will save the - // history to the history save file automatically. + // EditlineHistory objects are sometimes shared between multiple Editline + // instances with the same program name. So just release our shared pointer + // and if we are the last owner, it will save the history to the history save + // file automatically. m_history_sp.reset(); } @@ -1313,8 +1303,8 @@ bool Editline::GetLines(int first_line_number, StringList &lines, bool &interrupted) { ConfigureEditor(true); - // Print the initial input lines, then move the cursor back up to the start of - // input + // Print the initial input lines, then move the cursor back up to the start + // of input SetBaseLineNumber(first_line_number); m_input_lines = std::vector<EditLineStringType>(); m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 6ee4e894756b7..3c3d55df22079 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -100,7 +100,7 @@ int File::GetDescriptor() const { // Don't open the file descriptor if we don't need to, just get it from the // stream if we have one. if (StreamIsValid()) { -#if defined(LLVM_ON_WIN32) +#if defined(_WIN32) return _fileno(m_stream); #else return fileno(m_stream); @@ -126,8 +126,8 @@ FILE *File::GetStream() { const char *mode = GetStreamOpenModeFromOptions(m_options); if (mode) { if (!m_should_close_fd) { -// We must duplicate the file descriptor if we don't own it because -// when you call fdopen, the stream will own the fd +// We must duplicate the file descriptor if we don't own it because when you +// call fdopen, the stream will own the fd #ifdef _WIN32 m_descriptor = ::_dup(GetDescriptor()); #else @@ -139,8 +139,8 @@ FILE *File::GetStream() { m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); - // If we got a stream, then we own the stream and should no - // longer own the descriptor because fclose() will close it for us + // If we got a stream, then we own the stream and should no longer own + // the descriptor because fclose() will close it for us if (m_stream) { m_own_stream = true; @@ -315,7 +315,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const { if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) error.SetErrorToErrno(); else - file_spec.SetFile(path, false); + file_spec.SetFile(path, false, FileSpec::Style::native); } else { error.SetErrorString("invalid file handle"); } @@ -330,7 +330,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const { error.SetErrorToErrno(); else { path[len] = '\0'; - file_spec.SetFile(path, false); + file_spec.SetFile(path, false, FileSpec::Style::native); } } #else diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 97581185ad9e6..d2848254779e8 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -59,7 +59,6 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -120,9 +119,8 @@ HostThread Host::StartMonitoringChildProcess( #ifndef __linux__ //------------------------------------------------------------------ -// Scoped class that will disable thread canceling when it is -// constructed, and exception safely restore the previous value it -// when it goes out of scope. +// Scoped class that will disable thread canceling when it is constructed, and +// exception safely restore the previous value it when it goes out of scope. //------------------------------------------------------------------ class ScopedPThreadCancelDisabler { public: @@ -271,8 +269,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { __FUNCTION__, arg); break; } - // If the callback returns true, it means this process should - // exit + // If the callback returns true, it means this process should exit if (callback_return) { if (log) log->Printf("%s (arg = %p) thread exiting because callback " @@ -423,7 +420,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { Dl_info info; if (::dladdr(host_addr, &info)) { if (info.dli_fname) - module_filespec.SetFile(info.dli_fname, true); + module_filespec.SetFile(info.dli_fname, true, FileSpec::Style::native); } #endif return module_filespec; @@ -466,15 +463,17 @@ MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid, Status Host::RunShellCommand(const char *command, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, - uint32_t timeout_sec, bool run_in_default_shell) { + const Timeout<std::micro> &timeout, + bool run_in_default_shell) { return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, - command_output_ptr, timeout_sec, run_in_default_shell); + command_output_ptr, timeout, run_in_default_shell); } Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, - uint32_t timeout_sec, bool run_in_default_shell) { + const Timeout<std::micro> &timeout, + bool run_in_default_shell) { Status error; ProcessLaunchInfo launch_info; launch_info.SetArchitecture(HostInfo::GetArchitecture()); @@ -498,11 +497,10 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, llvm::SmallString<PATH_MAX> output_file_path; if (command_output_ptr) { - // Create a temporary file to get the stdout/stderr and redirect the - // output of the command into this file. We will later read this file - // if all goes well and fill the data into "command_output_ptr" - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { + // Create a temporary file to get the stdout/stderr and redirect the output + // of the command into this file. We will later read this file if all goes + // well and fill the data into "command_output_ptr" + if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) { tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(), output_file_path); @@ -539,18 +537,14 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, error.SetErrorString("failed to get process ID"); if (error.Success()) { - bool timed_out = false; - shell_info_sp->process_reaped.WaitForValueEqualTo( - true, std::chrono::seconds(timeout_sec), &timed_out); - if (timed_out) { + if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) { error.SetErrorString("timed out waiting for shell command to complete"); // Kill the process since it didn't complete within the timeout specified Kill(pid, SIGKILL); // Wait for the monitor callback to get the message - timed_out = false; shell_info_sp->process_reaped.WaitForValueEqualTo( - true, std::chrono::seconds(1), &timed_out); + true, std::chrono::seconds(1)); } else { if (status_ptr) *status_ptr = shell_info_sp->status; @@ -581,7 +575,8 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, return error; } -// The functions below implement process launching for non-Apple-based platforms +// The functions below implement process launching for non-Apple-based +// platforms #if !defined(__APPLE__) Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { std::unique_ptr<ProcessLauncher> delegate_launcher; @@ -596,8 +591,7 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { HostProcess process = launcher.LaunchProcess(launch_info, error); // TODO(zturner): It would be better if the entire HostProcess were returned - // instead of writing - // it into this structure. + // instead of writing it into this structure. launch_info.SetProcessID(process.GetProcessId()); return error; diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index aff887f9f1d2e..4de6953a91e35 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -33,19 +33,19 @@ using namespace lldb_private; namespace { //---------------------------------------------------------------------- -// The HostInfoBaseFields is a work around for windows not supporting -// static variables correctly in a thread safe way. Really each of the -// variables in HostInfoBaseFields should live in the functions in which -// they are used and each one should be static, but the work around is -// in place to avoid this restriction. Ick. +// The HostInfoBaseFields is a work around for windows not supporting static +// variables correctly in a thread safe way. Really each of the variables in +// HostInfoBaseFields should live in the functions in which they are used and +// each one should be static, but the work around is in place to avoid this +// restriction. Ick. //---------------------------------------------------------------------- struct HostInfoBaseFields { ~HostInfoBaseFields() { if (m_lldb_process_tmp_dir.Exists()) { // Remove the LLDB temporary directory if we have one. Set "recurse" to - // true to all files that were created for the LLDB process can be cleaned - // up. + // true to all files that were created for the LLDB process can be + // cleaned up. llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath()); } } @@ -58,7 +58,6 @@ struct HostInfoBaseFields { FileSpec m_lldb_so_dir; FileSpec m_lldb_support_exe_dir; FileSpec m_lldb_headers_dir; - FileSpec m_lldb_python_dir; FileSpec m_lldb_clang_resource_dir; FileSpec m_lldb_system_plugin_dir; FileSpec m_lldb_user_plugin_dir; @@ -111,152 +110,88 @@ llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKi .Default(llvm::None); } -bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { - file_spec.Clear(); +FileSpec HostInfoBase::GetShlibDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir); + }); + return success ? g_fields->m_lldb_so_dir : FileSpec(); +} -#if defined(LLDB_DISABLE_PYTHON) - if (type == lldb::ePathTypePythonDir) - return false; -#endif +FileSpec HostInfoBase::GetSupportExeDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = + HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir); + }); + return success ? g_fields->m_lldb_support_exe_dir : FileSpec(); +} - FileSpec *result = nullptr; - switch (type) { - case lldb::ePathTypeLLDBShlibDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = - HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", - g_fields->m_lldb_so_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_so_dir; - } break; - case lldb::ePathTypeSupportExecutableDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeSupportExeDirectory( - g_fields->m_lldb_support_exe_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf( - "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", - g_fields->m_lldb_support_exe_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_support_exe_dir; - } break; - case lldb::ePathTypeHeaderDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - 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) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", - g_fields->m_lldb_headers_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_headers_dir; - } break; - case lldb::ePathTypePythonDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - 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) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", - g_fields->m_lldb_python_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_python_dir; - } break; - case lldb::ePathTypeClangDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = - HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf( - "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", - g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_clang_resource_dir; - } break; - case lldb::ePathTypeLLDBSystemPlugins: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeSystemPluginsDirectory( - g_fields->m_lldb_system_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf( - "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", - g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_system_plugin_dir; - } break; - case lldb::ePathTypeLLDBUserPlugins: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeUserPluginsDirectory( - g_fields->m_lldb_user_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf( - "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", - g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_user_plugin_dir; - } break; - case lldb::ePathTypeLLDBTempSystemDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeProcessTempFileDirectory( - g_fields->m_lldb_process_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf( - "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", - g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_process_tmp_dir; - } break; - case lldb::ePathTypeGlobalLLDBTempSystemDir: { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeGlobalTempFileDirectory( - g_fields->m_lldb_global_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(" - "ePathTypeGlobalLLDBTempSystemDir) => '%s'", - g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_global_tmp_dir; - } break; - } +FileSpec HostInfoBase::GetHeaderDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir); + }); + return success ? g_fields->m_lldb_headers_dir : FileSpec(); +} - if (!result) - return false; - file_spec = *result; - return true; +FileSpec HostInfoBase::GetSystemPluginDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = HostInfo::ComputeSystemPluginsDirectory( + g_fields->m_lldb_system_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "system plugin dir -> `{0}`", + g_fields->m_lldb_system_plugin_dir); + }); + return success ? g_fields->m_lldb_system_plugin_dir : FileSpec(); +} + +FileSpec HostInfoBase::GetUserPluginDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = + HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir); + }); + return success ? g_fields->m_lldb_user_plugin_dir : FileSpec(); +} + +FileSpec HostInfoBase::GetProcessTempDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = HostInfo::ComputeProcessTempFileDirectory( + g_fields->m_lldb_process_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "process temp dir -> `{0}`", + g_fields->m_lldb_process_tmp_dir); + }); + return success ? g_fields->m_lldb_process_tmp_dir : FileSpec(); +} + +FileSpec HostInfoBase::GetGlobalTempDir() { + static llvm::once_flag g_once_flag; + static bool success = false; + llvm::call_once(g_once_flag, []() { + success = HostInfo::ComputeGlobalTempFileDirectory( + g_fields->m_lldb_global_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir); + }); + return success ? g_fields->m_lldb_global_tmp_dir : FileSpec(); } ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { @@ -282,14 +217,12 @@ ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { // To get paths related to LLDB we get the path to the executable that - // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", - // on linux this is assumed to be the "lldb" main executable. If LLDB on - // linux is actually in a shared library (liblldb.so) then this function will - // need to be modified to "do the right thing". + // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". + // On other posix systems, we will get .../lib(64|32)?/liblldb.so. - FileSpec lldb_file_spec( - Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>( - reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath)))); + FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress( + reinterpret_cast<void *>(reinterpret_cast<intptr_t>( + HostInfoBase::ComputeSharedLibraryDirectory)))); // This is necessary because when running the testsuite the shlib might be a // symbolic link inside the Python resource dir. @@ -302,7 +235,8 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { } bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { - return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); + file_spec = GetShlibDir(); + return bool(file_spec); } bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { @@ -353,11 +287,9 @@ bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { return false; } -bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; } - bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { - // TODO(zturner): Figure out how to compute the user plugins directory for all - // platforms. + // TODO(zturner): Figure out how to compute the user plugins directory for + // all platforms. return false; } @@ -375,6 +307,7 @@ void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, case llvm::Triple::aarch64: case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: case llvm::Triple::x86_64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 6cbb5a8425623..65158c942934f 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -26,7 +26,7 @@ #if HAVE_SYS_EVENT_H #include <sys/event.h> -#elif defined(LLVM_ON_WIN32) +#elif defined(_WIN32) #include <winsock2.h> #elif defined(__ANDROID__) #include <sys/syscall.h> @@ -34,14 +34,14 @@ #include <poll.h> #endif -#ifdef LLVM_ON_WIN32 +#ifdef _WIN32 #define POLL WSAPoll #else #define POLL poll #endif #if SIGNAL_POLLING_UNSUPPORTED -#ifdef LLVM_ON_WIN32 +#ifdef _WIN32 typedef int sigset_t; typedef int siginfo_t; #endif @@ -209,8 +209,8 @@ Status MainLoop::RunImpl::Poll() { void MainLoop::RunImpl::ProcessEvents() { #ifdef __ANDROID__ - // Collect first all readable file descriptors into a separate vector and then - // iterate over it to invoke callbacks. Iterating directly over + // Collect first all readable file descriptors into a separate vector and + // then iterate over it to invoke callbacks. Iterating directly over // loop.m_read_fds is not possible because the callbacks can modify the // container which could invalidate the iterator. std::vector<IOObject::WaitableHandle> fds; @@ -262,7 +262,7 @@ MainLoop::~MainLoop() { MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Status &error) { -#ifdef LLVM_ON_WIN32 +#ifdef _WIN32 if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) { error.SetErrorString("MainLoop: non-socket types unsupported on Windows"); return nullptr; @@ -285,8 +285,7 @@ MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp, } // We shall block the signal, then install the signal handler. The signal will -// be unblocked in -// the Run() function to check for signal delivery. +// be unblocked in the Run() function to check for signal delivery. MainLoop::SignalHandleUP MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { #ifdef SIGNAL_POLLING_UNSUPPORTED @@ -321,9 +320,9 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { assert(ret == 0); #endif - // If we're using kqueue, the signal needs to be unblocked in order to recieve - // it. If using pselect/ppoll, we need to block it, and later unblock it as a - // part of the system call. + // If we're using kqueue, the signal needs to be unblocked in order to + // recieve it. If using pselect/ppoll, we need to block it, and later unblock + // it as a part of the system call. ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK, &new_action.sa_mask, &old_set); assert(ret == 0 && "pthread_sigmask failed"); diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp index f1fcd0b44c150..76c11454f573c 100644 --- a/source/Host/common/MonitoringProcessLauncher.cpp +++ b/source/Host/common/MonitoringProcessLauncher.cpp @@ -8,11 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/MonitoringProcessLauncher.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/Log.h" #include "lldb/Utility/Status.h" @@ -32,36 +28,23 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, ProcessLaunchInfo resolved_info(launch_info); error.Clear(); - char exe_path[PATH_MAX]; - - PlatformSP host_platform_sp(Platform::GetHostPlatform()); - - const ArchSpec &arch_spec = resolved_info.GetArchitecture(); FileSpec exe_spec(resolved_info.GetExecutableFile()); 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 = - host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); - - if (error.Fail()) - return HostProcess(); - - if (exe_module_sp) { - exe_spec = exe_module_sp->GetFileSpec(); - status(exe_spec.GetPath(), stats); - } + if (!exists(stats)) { + exe_spec.ResolvePath(); + status(exe_spec.GetPath(), stats); + } + if (!exists(stats)) { + exe_spec.ResolveExecutableLocation(); + status(exe_spec.GetPath(), stats); } - if (exists(stats)) { - exe_spec.GetPath(exe_path, sizeof(exe_path)); - } else { - resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + if (!exists(stats)) { + error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'", + exe_spec); return HostProcess(); } @@ -74,18 +57,9 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - Host::MonitorChildProcessCallback callback = - launch_info.GetMonitorProcessCallback(); - - bool monitor_signals = false; - if (callback) { - // If the ProcessLaunchInfo specified a callback, use that. - monitor_signals = launch_info.GetMonitorSignals(); - } else { - callback = Process::SetProcessExitStatus; - } - - process.StartMonitoring(callback, monitor_signals); + assert(launch_info.GetMonitorProcessCallback()); + process.StartMonitoring(launch_info.GetMonitorProcessCallback(), + launch_info.GetMonitorSignals()); if (log) log->PutCString("started monitoring child process."); } else { diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp index ce5eb94a8d1fb..cfcbe0831064b 100644 --- a/source/Host/common/NativeBreakpointList.cpp +++ b/source/Host/common/NativeBreakpointList.cpp @@ -104,8 +104,8 @@ Status NativeBreakpointList::DecRef(lldb::addr_t addr) { return error; } - // Breakpoint has no more references. Disable it if it's not - // already disabled. + // Breakpoint has no more references. Disable it if it's not already + // disabled. if (log) log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 1fcb11b8b6f5d..3e8648f814739 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -8,14 +8,11 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Host/common/SoftwareBreakpoint.h" -#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" @@ -139,29 +136,28 @@ NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { - // This default implementation assumes setting the watchpoint for - // the process will require setting the watchpoint for each of the - // threads. Furthermore, it will track watchpoints set for the - // process and will add them to each thread that is attached to - // via the (FIXME implement) OnThreadAttached () method. + // This default implementation assumes setting the watchpoint for the process + // will require setting the watchpoint for each of the threads. Furthermore, + // it will track watchpoints set for the process and will add them to each + // thread that is attached to via the (FIXME implement) OnThreadAttached () + // method. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // Update the thread list UpdateThreads(); - // Keep track of the threads we successfully set the watchpoint - // for. If one of the thread watchpoint setting operations fails, - // back off and remove the watchpoint for all the threads that - // were successfully set so we get back to a consistent state. + // Keep track of the threads we successfully set the watchpoint for. If one + // of the thread watchpoint setting operations fails, back off and remove the + // watchpoint for all the threads that were successfully set so we get back + // to a consistent state. std::vector<NativeThreadProtocol *> watchpoint_established_threads; - // Tell each thread to set a watchpoint. In the event that - // hardware watchpoints are requested but the SetWatchpoint fails, - // try to set a software watchpoint as a fallback. It's - // conceivable that if there are more threads than hardware - // watchpoints available, some of the threads will fail to set - // hardware watchpoints while software ones may be available. + // Tell each thread to set a watchpoint. In the event that hardware + // watchpoints are requested but the SetWatchpoint fails, try to set a + // software watchpoint as a fallback. It's conceivable that if there are + // more threads than hardware watchpoints available, some of the threads will + // fail to set hardware watchpoints while software ones may be available. std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); for (const auto &thread : m_threads) { assert(thread && "thread list should not have a NULL thread!"); @@ -169,8 +165,8 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, Status thread_error = thread->SetWatchpoint(addr, size, watch_flags, hardware); if (thread_error.Fail() && hardware) { - // Try software watchpoints since we failed on hardware watchpoint setting - // and we may have just run out of hardware watchpoints. + // Try software watchpoints since we failed on hardware watchpoint + // setting and we may have just run out of hardware watchpoints. thread_error = thread->SetWatchpoint(addr, size, watch_flags, false); if (thread_error.Success()) LLDB_LOG(log, @@ -178,13 +174,12 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, } if (thread_error.Success()) { - // Remember that we set this watchpoint successfully in - // case we need to clear it later. + // Remember that we set this watchpoint successfully in case we need to + // clear it later. watchpoint_established_threads.push_back(thread.get()); } else { - // Unset the watchpoint for each thread we successfully - // set so that we get back to a consistent state of "not - // set" for the watchpoint. + // Unset the watchpoint for each thread we successfully set so that we + // get back to a consistent state of "not set" for the watchpoint. for (auto unwatch_thread_sp : watchpoint_established_threads) { Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); if (remove_error.Fail()) @@ -210,9 +205,9 @@ Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { const Status thread_error = thread->RemoveWatchpoint(addr); if (thread_error.Fail()) { - // Keep track of the first thread error if any threads - // fail. We want to try to remove the watchpoint from - // every thread, though, even if one or more have errors. + // Keep track of the first thread error if any threads fail. We want to + // try to remove the watchpoint from every thread, though, even if one or + // more have errors. if (!overall_error.Fail()) overall_error = thread_error; } @@ -228,9 +223,9 @@ NativeProcessProtocol::GetHardwareBreakpointMap() const { Status 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. + // 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 @@ -256,13 +251,13 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, Status thread_error = thread->SetHardwareBreakpoint(addr, size); if (thread_error.Success()) { - // Remember that we set this breakpoint successfully in - // case we need to clear it later. + // Remember that we set this breakpoint successfully in case we need to + // clear it later. breakpoint_established_threads.push_back(thread.get()); } 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. + // 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) { Status remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); @@ -322,8 +317,8 @@ bool NativeProcessProtocol::UnregisterNativeDelegate( remove(m_delegates.begin(), m_delegates.end(), &native_delegate), m_delegates.end()); - // We removed the delegate if the count of delegates shrank after - // removing all copies of the given native_delegate from the vector. + // We removed the delegate if the count of delegates shrank after removing + // all copies of the given native_delegate from the vector. return m_delegates.size() < initial_size; } @@ -412,8 +407,8 @@ void NativeProcessProtocol::SetState(lldb::StateType state, // Give process a chance to do any stop id bump processing, such as // clearing cached data that is invalidated each time the process runs. - // Note if/when we support some threads running, we'll end up needing - // to manage this per thread and per process. + // Note if/when we support some threads running, we'll end up needing to + // manage this per thread and per process. DoStopIDBumped(m_stop_id); } @@ -431,26 +426,4 @@ void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { // Default implementation does nothing. } -Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, - ArchSpec &arch) { - // Grab process info for the running process. - ProcessInstanceInfo process_info; - if (!Host::GetProcessInfo(pid, process_info)) - return Status("failed to get process info"); - - // Resolve the executable module. - ModuleSpecList module_specs; - if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, - 0, module_specs)) - return Status("failed to get module specifications"); - lldbassert(module_specs.GetSize() == 1); - - arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); - if (arch.IsValid()) - return Status(); - else - return Status( - "failed to retrieve a valid architecture from the exe module"); -} - NativeProcessProtocol::Factory::~Factory() = default; diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 60eaebdc94cd2..49b8284da9703 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -28,13 +28,12 @@ NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) NativeRegisterContext::~NativeRegisterContext() {} // FIXME revisit invalidation, process stop ids, etc. Right now we don't -// support caching in NativeRegisterContext. We can do this later by -// utilizing NativeProcessProtocol::GetStopID () and adding a stop id to +// support caching in NativeRegisterContext. We can do this later by utilizing +// NativeProcessProtocol::GetStopID () and adding a stop id to // NativeRegisterContext. // void -// NativeRegisterContext::InvalidateIfNeeded (bool force) -// { +// NativeRegisterContext::InvalidateIfNeeded (bool force) { // ProcessSP process_sp (m_thread.GetProcess()); // bool invalidate = force; // uint32_t process_stop_id = UINT32_MAX; @@ -365,8 +364,8 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory( // We now have a memory buffer that contains the part or all of the register // value. Set the register value using this memory data. // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are assuming - // they are the same. + // order of the memory data doesn't match the process. For now we are + // assuming they are the same. reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(), error); @@ -385,8 +384,7 @@ Status NativeRegisterContext::WriteRegisterValueToMemory( // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are - // assuming - // they are the same. + // assuming they are the same. const size_t bytes_copied = reg_value.GetAsMemoryData( reg_info, dst, dst_len, process.GetByteOrder(), error); diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 3f3915e006da6..0c648e40eb5c6 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -19,36 +19,3 @@ using namespace lldb_private; NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol &process, lldb::tid_t tid) : m_process(process), m_tid(tid) {} - -Status NativeThreadProtocol::ReadRegister(uint32_t reg, - RegisterValue ®_value) { - NativeRegisterContext ®ister_context = GetRegisterContext(); - - const RegisterInfo *const reg_info = - register_context.GetRegisterInfoAtIndex(reg); - if (!reg_info) - return Status("no register info for reg num %" PRIu32, reg); - - return register_context.ReadRegister(reg_info, reg_value); - ; -} - -Status NativeThreadProtocol::WriteRegister(uint32_t reg, - const RegisterValue ®_value) { - NativeRegisterContext& register_context = GetRegisterContext(); - - const RegisterInfo *const reg_info = - register_context.GetRegisterInfoAtIndex(reg); - if (!reg_info) - return Status("no register info for reg num %" PRIu32, reg); - - return register_context.WriteRegister(reg_info, reg_value); -} - -Status NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) { - return GetRegisterContext().WriteAllRegisterValues(data_sp); -} - -Status NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) { - return GetRegisterContext().ReadAllRegisterValues(data_sp); -} diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp index 9657cb6523dce..c9b290078e182 100644 --- a/source/Host/common/PseudoTerminal.cpp +++ b/source/Host/common/PseudoTerminal.cpp @@ -35,10 +35,10 @@ PseudoTerminal::PseudoTerminal() //---------------------------------------------------------------------- // 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. +// 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(); @@ -66,15 +66,14 @@ void PseudoTerminal::CloseSlaveFileDescriptor() { } //---------------------------------------------------------------------- -// 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. +// 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. @@ -118,12 +117,12 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, } //---------------------------------------------------------------------- -// 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. +// 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. @@ -152,8 +151,8 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { } //---------------------------------------------------------------------- -// Get the name of the slave pseudo terminal. A master pseudo terminal -// should already be valid prior to calling this function (see +// Get the name of the slave pseudo terminal. A master pseudo terminal should +// already be valid prior to calling this function (see // OpenFirstAvailableMaster()). // // RETURNS: @@ -185,18 +184,16 @@ const char *PseudoTerminal::GetSlaveName(char *error_str, // 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. +// 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. +// 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. +// 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 @@ -261,49 +258,47 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { } //---------------------------------------------------------------------- -// 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. +// 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. +// 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. +// 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. +// 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!) + // 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. +// 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!) + // 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 4c23e4eb560c4..875291bc115f8 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -160,18 +160,17 @@ Status Socket::TcpListen(llvm::StringRef host_and_port, error = listen_socket->Listen(host_and_port, backlog); if (error.Success()) { - // We were asked to listen on port zero which means we - // must now read the actual port that was given to us - // as port zero is a special code for "find an open port - // for me". + // We were asked to listen on port zero which means we must now read the + // actual port that was given to us as port zero is a special code for + // "find an open port for me". if (port == 0) port = listen_socket->GetLocalPortNumber(); - // Set the port predicate since when doing a listen://<host>:<port> - // it often needs to accept the incoming connection which is a blocking - // system call. Allowing access to the bound port using a predicate allows - // us to wait for the port predicate to be set to a non-zero value from - // another thread in an efficient manor. + // Set the port predicate since when doing a listen://<host>:<port> it + // often needs to accept the incoming connection which is a blocking system + // call. Allowing access to the bound port using a predicate allows us to + // wait for the port predicate to be set to a non-zero value from another + // thread in an efficient manor. if (predicate) predicate->SetValue(port, eBroadcastAlways); socket = listen_socket.release(); @@ -282,8 +281,7 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, } // If this was unsuccessful, then check if it's simply a signed 32-bit - // integer, representing - // a port with an empty host. + // integer, representing a port with an empty host. host_str.clear(); port_str.clear(); bool ok = false; @@ -436,8 +434,8 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, error.Clear(); #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 + // 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. diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp index 14dbafd94c039..353dadf6ce6d6 100644 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ b/source/Host/common/SoftwareBreakpoint.cpp @@ -17,9 +17,8 @@ using namespace lldb_private; -// ------------------------------------------------------------------- -// static members -// ------------------------------------------------------------------- +// ------------------------------------------------------------------- static +// members ------------------------------------------------------------------- Status SoftwareBreakpoint::CreateSoftwareBreakpoint( NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, @@ -34,8 +33,7 @@ Status SoftwareBreakpoint::CreateSoftwareBreakpoint( __FUNCTION__); // Ask the NativeProcessProtocol subclass to fill in the correct software - // breakpoint - // trap for the breakpoint site. + // breakpoint trap for the breakpoint site. size_t bp_opcode_size = 0; const uint8_t *bp_opcode_bytes = NULL; Status error = process.GetSoftwareBreakpointTrapOpcode( @@ -98,9 +96,8 @@ Status SoftwareBreakpoint::CreateSoftwareBreakpoint( log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr); - // Set the breakpoint and verified it was written properly. Now - // create a breakpoint remover that understands how to undo this - // breakpoint. + // Set the breakpoint and verified it was written properly. Now create a + // breakpoint remover that understands how to undo this breakpoint. breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes, bp_opcode_bytes, bp_opcode_size)); return Status(); @@ -280,8 +277,8 @@ Status SoftwareBreakpoint::DoDisable() { // Make sure the breakpoint opcode exists at this address if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) { break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore - // the saved opcode. + // We found a valid breakpoint opcode at this address, now restore the + // saved opcode. size_t bytes_written = 0; error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size, bytes_written); diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index 3f70fdc4bf951..d7e0c13112aaf 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Symbols.h" -#include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" @@ -91,7 +91,7 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1); - dsym_fspec.SetFile(path, false); + dsym_fspec.SetFile(path, false, FileSpec::Style::native); ModuleSpecList module_specs; ModuleSpec matched_module_spec; @@ -111,15 +111,15 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, // Add a ".dSYM" name to each directory component of the path, // stripping off components. e.g. we may have a binary like - // /S/L/F/Foundation.framework/Versions/A/Foundation - // and + // /S/L/F/Foundation.framework/Versions/A/Foundation and // /S/L/F/Foundation.framework.dSYM // - // so we'll need to start with /S/L/F/Foundation.framework/Versions/A, - // add the .dSYM part to the "A", and if that doesn't exist, strip off - // the "A" and try it again with "Versions", etc., until we find a - // dSYM bundle or we've stripped off enough path components that - // there's no need to continue. + // so we'll need to start with + // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the + // "A", and if that doesn't exist, strip off the "A" and try it again + // with "Versions", etc., until we find a dSYM bundle or we've + // stripped off enough path components that there's no need to + // continue. for (int i = 0; i < 4; i++) { // Does this part of the path have a "." character - could it be a @@ -131,7 +131,8 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, dsym_fspec = parent_dirs; dsym_fspec.RemoveLastPathComponent(); - // If the current directory name is "Foundation.framework", see if + // If the current directory name is "Foundation.framework", see + // if // "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation" // exists & has the right uuid. std::string dsym_fn = fn; @@ -222,14 +223,18 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { Target::GetDefaultDebugFileSearchPaths()); // Add module directory. - const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory(); + FileSpec module_file_spec = module_spec.GetFileSpec(); + // We keep the unresolved pathname if it fails. + FileSystem::ResolveSymbolicLink(module_file_spec, module_file_spec); + + const ConstString &file_dir = module_file_spec.GetDirectory(); debug_file_search_paths.AppendIfUnique( FileSpec(file_dir.AsCString("."), true)); // Add current working directory. debug_file_search_paths.AppendIfUnique(FileSpec(".", true)); -#ifndef LLVM_ON_WIN32 +#ifndef _WIN32 #if defined(__NetBSD__) // Add /usr/libdata/debug directory. debug_file_search_paths.AppendIfUnique( @@ -238,7 +243,7 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { // Add /usr/lib/debug directory. debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); #endif -#endif // LLVM_ON_WIN32 +#endif // _WIN32 std::string uuid_str; const UUID &module_uuid = module_spec.GetUUID(); @@ -246,6 +251,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { // Some debug files are stored in the .build-id directory like this: // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug uuid_str = module_uuid.GetAsString(""); + std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), + ::tolower); uuid_str.insert(2, 1, '/'); uuid_str = uuid_str + ".debug"; } @@ -275,7 +282,7 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { FileSpec file_spec(filename, true); if (llvm::sys::fs::equivalent(file_spec.GetPath(), - module_spec.GetFileSpec().GetPath())) + module_file_spec.GetPath())) continue; if (file_spec.Exists()) { @@ -287,10 +294,9 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { if (num_specs == 1) { ModuleSpec mspec; if (specs.GetModuleSpecAtIndex(0, mspec)) { - // Skip the uuids check if module_uuid is invalid. - // For example, this happens for *.dwp files since - // at the moment llvm-dwp doesn't output build ids, - // nor does binutils dwp. + // Skip the uuids check if module_uuid is invalid. For example, + // this happens for *.dwp files since at the moment llvm-dwp + // doesn't output build ids, nor does binutils dwp. if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) return file_spec; } diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp index f896944bb1b36..1a10336f1dfc5 100644 --- a/source/Host/common/TCPSocket.cpp +++ b/source/Host/common/TCPSocket.cpp @@ -26,11 +26,11 @@ #include <sys/socket.h> #endif -#if defined(LLVM_ON_WIN32) +#if defined(_WIN32) #include <winsock2.h> #endif -#ifdef LLVM_ON_WIN32 +#ifdef _WIN32 #define CLOSE_SOCKET closesocket typedef const char *set_socket_option_arg_type; #else diff --git a/source/Host/common/TaskPool.cpp b/source/Host/common/TaskPool.cpp index 156a079429985..c54b9a8ae56b1 100644 --- a/source/Host/common/TaskPool.cpp +++ b/source/Host/common/TaskPool.cpp @@ -49,8 +49,8 @@ void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) { TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {} unsigned GetHardwareConcurrencyHint() { - // std::thread::hardware_concurrency may return 0 - // if the value is not well defined or not computable. + // std::thread::hardware_concurrency may return 0 if the value is not well + // defined or not computable. static const unsigned g_hardware_concurrency = std::max(1u, std::thread::hardware_concurrency()); return g_hardware_concurrency; @@ -64,9 +64,8 @@ void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { if (m_thread_count < GetHardwareConcurrencyHint()) { m_thread_count++; // Note that this detach call needs to happen with the m_tasks_mutex held. - // This prevents the thread - // from exiting prematurely and triggering a linux libc bug - // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). + // This prevents the thread from exiting prematurely and triggering a linux + // libc bug (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, this, nullptr, min_stack_size) .Release(); diff --git a/source/Host/common/Terminal.cpp b/source/Host/common/Terminal.cpp index 022b3fa50a8fe..be912fbe61554 100644 --- a/source/Host/common/Terminal.cpp +++ b/source/Host/common/Terminal.cpp @@ -9,6 +9,7 @@ #include "lldb/Host/Terminal.h" +#include "lldb/Host/Config.h" #include "lldb/Host/PosixApi.h" #include "llvm/ADT/STLExtras.h" @@ -107,9 +108,9 @@ void TerminalState::Clear() { } //---------------------------------------------------------------------- -// Save the current state of the TTY for the file descriptor "fd" -// and if "save_process_group" is true, attempt to save the process -// group info for the TTY. +// Save the current state of the TTY for the file descriptor "fd" and if +// "save_process_group" is true, attempt to save the process group info for the +// TTY. //---------------------------------------------------------------------- bool TerminalState::Save(int fd, bool save_process_group) { m_tty.SetFileDescriptor(fd); @@ -142,8 +143,8 @@ bool TerminalState::Save(int fd, bool save_process_group) { } //---------------------------------------------------------------------- -// Restore the state of the TTY using the cached values from a -// previous call to Save(). +// Restore the state of the TTY using the cached values from a previous call to +// Save(). //---------------------------------------------------------------------- bool TerminalState::Restore() const { #ifndef LLDB_DISABLE_POSIX @@ -173,8 +174,8 @@ bool TerminalState::Restore() const { } //---------------------------------------------------------------------- -// Returns true if this object has valid saved TTY state settings -// that can be used to restore a previous state. +// Returns true if this object has valid saved TTY state settings that can be +// used to restore a previous state. //---------------------------------------------------------------------- bool TerminalState::IsValid() const { return m_tty.FileDescriptorIsValid() && @@ -236,21 +237,20 @@ bool TerminalStateSwitcher::Restore(uint32_t idx) const { m_ttystates[idx].IsValid()) return true; - // Set the state to match the index passed in and only update the - // current state if there are no errors. + // Set the state to match the index passed in and only update the current + // state if there are no errors. if (m_ttystates[idx].Restore()) { m_currentState = idx; return true; } - // We failed to set the state. The tty state was invalid or not - // initialized. + // We failed to set the state. The tty state was invalid or not initialized. return false; } //------------------------------------------------------------------ -// Save the state at index "idx" for file descriptor "fd" and -// save the process group if requested. +// Save the state at index "idx" for file descriptor "fd" and save the process +// group if requested. // // Returns true if the restore was successful, false otherwise. //------------------------------------------------------------------ diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp index 21dacbc626eee..96bcc6a150a9e 100644 --- a/source/Host/common/UDPSocket.cpp +++ b/source/Host/common/UDPSocket.cpp @@ -69,8 +69,8 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) return error; - // At this point we have setup the receive port, now we need to - // setup the UDP send socket + // At this point we have setup the receive port, now we need to setup the UDP + // send socket struct addrinfo hints; struct addrinfo *service_info_list = nullptr; diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index c3169bd6e08d1..7468a3d7ac65e 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -151,6 +151,18 @@ llvm::StringRef XMLNode::GetAttributeValue(const char *name, return llvm::StringRef(); } +bool XMLNode::GetAttributeValueAsUnsigned(const char *name, uint64_t &value, + uint64_t fail_value, int base) const { +#if defined(LIBXML2_DEFINED) + llvm::StringRef str_value = GetAttributeValue(name, ""); +#else + llvm::StringRef str_value; +#endif + bool success = false; + value = StringConvert::ToUInt64(str_value.data(), fail_value, base, &success); + return success; +} + void XMLNode::ForEachChildNode(NodeCallback const &callback) const { #if defined(LIBXML2_DEFINED) if (IsValid()) @@ -240,8 +252,8 @@ void XMLNode::ForEachSiblingElementWithName( if (node->type != XML_ELEMENT_NODE) continue; - // If name is nullptr, we take all nodes of type "t", else - // just the ones whose name matches + // If name is nullptr, we take all nodes of type "t", else just the ones + // whose name matches if (name) { if (strcmp((const char *)node->name, name) != 0) continue; // Name mismatch, ignore this one diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 124a8a760133a..87552bc2a27ed 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -26,12 +26,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Module.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.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" @@ -78,9 +75,11 @@ GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, size_t pathname_len = sizeof(pathname); mib[2] = KERN_PROC_PATHNAME; if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0) - process_info.GetExecutableFile().SetFile(pathname, false); + process_info.GetExecutableFile().SetFile(pathname, false, + FileSpec::Style::native); else - process_info.GetExecutableFile().SetFile(cstr, false); + process_info.GetExecutableFile().SetFile(cstr, false, + FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), @@ -195,9 +194,8 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, continue; // Every thread is a process in FreeBSD, but all the threads of a single - // process have the same pid. Do not store the process info in the - // result list if a process with given identifier is already registered - // there. + // process have the same pid. Do not store the process info in the result + // list if a process with given identifier is already registered there. bool already_registered = false; for (uint32_t pi = 0; !already_registered && (const int)kinfo.ki_numthreads > 1 && @@ -243,14 +241,7 @@ bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { return false; } -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; -} +Environment Host::GetEnvironment() { return Environment(environ); } Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { return Status("unimplemented"); diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index 9c82fcca75637..18eae3eb76060 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -18,16 +18,17 @@ using namespace lldb_private; -bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoFreeBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(utsname)); if (uname(&un) < 0) - return false; + return llvm::VersionTuple(); - int status = sscanf(un.release, "%u.%u", &major, &minor); - return status == 2; + unsigned major, minor; + if (2 == sscanf(un.release, "%u.%u", &major, &minor)) + return llvm::VersionTuple(major, minor); + return llvm::VersionTuple(); } bool HostInfoFreeBSD::GetOSBuildString(std::string &s) { @@ -68,9 +69,9 @@ FileSpec HostInfoFreeBSD::GetProgramFileSpec() { if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) { char *exe_path = new char[exe_path_size]; if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) - g_program_filespec.SetFile(exe_path, false); + g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native); delete[] exe_path; } } return g_program_filespec; -}
\ No newline at end of file +} diff --git a/source/Host/linux/Host.cpp b/source/Host/linux/Host.cpp index f43090eadf812..1a0eb767eb34b 100644 --- a/source/Host/linux/Host.cpp +++ b/source/Host/linux/Host.cpp @@ -20,7 +20,9 @@ // C++ Includes // Other libraries and framework includes +#include "llvm/Object/ELF.h" #include "llvm/Support/ScopedPrinter.h" + // Project includes #include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" @@ -29,12 +31,9 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/linux/Support.h" -#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/DataExtractor.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Symbol/ObjectFile.h" - using namespace lldb; using namespace lldb_private; @@ -123,28 +122,27 @@ static bool IsDirNumeric(const char *dname) { return true; } -static bool GetELFProcessCPUType(llvm::StringRef exe_path, - ProcessInstanceInfo &process_info) { - // Clear the architecture. - process_info.GetArchitecture().Clear(); +static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - 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; - } + auto buffer_sp = DataBufferLLVM::CreateSliceFromPath(exe_path, 0x20, 0); + if (!buffer_sp) + return ArchSpec(); + + uint8_t exe_class = + llvm::object::getElfArchType( + {buffer_sp->GetChars(), size_t(buffer_sp->GetByteSize())}) + .first; + + switch (exe_class) { + case llvm::ELF::ELFCLASS32: + return HostInfo::GetArchitecture(HostInfo::eArchKind32); + case llvm::ELF::ELFCLASS64: + return HostInfo::GetArchitecture(HostInfo::eArchKind64); + default: + LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class, exe_path); + return ArchSpec(); } - return false; } static bool GetProcessAndStatInfo(::pid_t pid, @@ -173,7 +171,7 @@ static bool GetProcessAndStatInfo(::pid_t pid, llvm::StringRef PathRef = ExePath; PathRef.consume_back(" (deleted)"); - GetELFProcessCPUType(PathRef, process_info); + process_info.SetArchitecture(GetELFProcessCPUType(PathRef)); // Get the process environment. auto BufferOrError = getProcFile(pid, "environ"); @@ -192,14 +190,14 @@ static bool GetProcessAndStatInfo(::pid_t pid, return false; process_info.SetProcessID(pid); - process_info.GetExecutableFile().SetFile(PathRef, false); - process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture()); + process_info.GetExecutableFile().SetFile(PathRef, false, + FileSpec::Style::native); llvm::StringRef Rest = Environ->getBuffer(); while (!Rest.empty()) { llvm::StringRef Var; std::tie(Var, Rest) = Rest.split('\0'); - process_info.GetEnvironmentEntries().AppendArgument(Var); + process_info.GetEnvironment().insert(Var); } llvm::StringRef Arg0; @@ -249,8 +247,8 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, if (State == ProcessState::Zombie) continue; - // Check for user match if we're not matching all users and not running as - // root. + // Check for user match if we're not matching all users and not running + // as root. if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid)) continue; @@ -297,14 +295,7 @@ bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { return GetProcessAndStatInfo(pid, process_info, State, tracerpid); } -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; -} +Environment Host::GetEnvironment() { return Environment(environ); } Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { return Status("unimplemented"); diff --git a/source/Host/linux/HostInfoLinux.cpp b/source/Host/linux/HostInfoLinux.cpp index 8d59cda249e83..1d95010e2f736 100644 --- a/source/Host/linux/HostInfoLinux.cpp +++ b/source/Host/linux/HostInfoLinux.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" #include "lldb/Host/linux/HostInfoLinux.h" #include "lldb/Utility/Log.h" @@ -25,12 +26,8 @@ using namespace lldb_private; namespace { struct HostInfoLinuxFields { - HostInfoLinuxFields() : m_os_major(0), m_os_minor(0), m_os_update(0) {} - std::string m_distribution_id; - uint32_t m_os_major; - uint32_t m_os_minor; - uint32_t m_os_update; + llvm::VersionTuple m_os_version; }; HostInfoLinuxFields *g_fields = nullptr; @@ -42,35 +39,21 @@ void HostInfoLinux::Initialize() { g_fields = new HostInfoLinuxFields(); } -bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - static bool success = false; +llvm::VersionTuple HostInfoLinux::GetOSVersion() { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { - struct utsname un; - if (uname(&un) == 0) { - int status = sscanf(un.release, "%u.%u.%u", &g_fields->m_os_major, - &g_fields->m_os_minor, &g_fields->m_os_update); - if (status == 3) - success = true; - else { - // Some kernels omit the update version, so try looking for just "X.Y" - // and - // set update to 0. - g_fields->m_os_update = 0; - status = sscanf(un.release, "%u.%u", &g_fields->m_os_major, - &g_fields->m_os_minor); - if (status == 2) - success = true; - } - } + if (uname(&un) != 0) + return; + + llvm::StringRef release = un.release; + // The kernel release string can include a lot of stuff (e.g. + // 4.9.0-6-amd64). We're only interested in the numbered prefix. + release = release.substr(0, release.find_first_not_of("0123456789.")); + g_fields->m_os_version.tryParse(release); }); - major = g_fields->m_os_major; - minor = g_fields->m_os_minor; - update = g_fields->m_os_update; - return success; + return g_fields->m_os_version; } bool HostInfoLinux::GetOSBuildString(std::string &s) { @@ -99,8 +82,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. + // Try to run 'lbs_release -i', and use that response for the distribution + // id. static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { @@ -108,8 +91,7 @@ llvm::StringRef HostInfoLinux::GetDistributionId() { if (log) log->Printf("attempting to determine Linux distribution..."); - // check if the lsb_release command exists at one of the - // following paths + // check if the lsb_release command exists at one of the following paths const char *const exe_paths[] = {"/bin/lsb_release", "/usr/bin/lsb_release"}; @@ -188,7 +170,7 @@ FileSpec HostInfoLinux::GetProgramFileSpec() { ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); if (len > 0) { exe_path[len] = 0; - g_program_filespec.SetFile(exe_path, false); + g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native); } } @@ -204,15 +186,15 @@ bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) { } bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) { - FileSpec temp_file("/usr/lib/lldb/plugins", true); + FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins", true); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; } bool HostInfoLinux::ComputeUserPluginsDirectory(FileSpec &file_spec) { // XDG Base Directory Specification - // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html - // If XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb. + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html If + // XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb. const char *xdg_data_home = getenv("XDG_DATA_HOME"); if (xdg_data_home && xdg_data_home[0]) { std::string user_plugin_dir(xdg_data_home); diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp index 98c110b1bed67..b01c48e51d900 100644 --- a/source/Host/macosx/Symbols.cpp +++ b/source/Host/macosx/Symbols.cpp @@ -23,7 +23,7 @@ #include "Host/macosx/cfcpp/CFCData.h" #include "Host/macosx/cfcpp/CFCReleaser.h" #include "Host/macosx/cfcpp/CFCString.h" -#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" @@ -55,6 +55,13 @@ CFDictionaryRef DBGCopyDSYMPropertyLists(CFURLRef dsym_url); int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, ModuleSpec &return_module_spec) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + if (log) + log->Printf("Spotlight lookup for .dSYM bundles is disabled."); + return 0; + } + return_module_spec = module_spec; return_module_spec.GetFileSpec().Clear(); return_module_spec.GetSymbolFileSpec().Clear(); @@ -69,8 +76,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (uuid && uuid->IsValid()) { // Try and locate the dSYM file using DebugSymbols first - const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes(); - if (module_uuid != NULL) { + llvm::ArrayRef<uint8_t> module_uuid = uuid->GetBytes(); + if (module_uuid.size() == 16) { CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes( NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], @@ -80,7 +87,6 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (module_uuid_ref.get()) { CFCReleaser<CFURLRef> exec_url; const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (exec_fspec) { char exec_cf_path[PATH_MAX]; if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) @@ -241,52 +247,53 @@ FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, const lldb_private::UUID *uuid, const ArchSpec *arch) { char path[PATH_MAX]; + if (dsym_bundle_fspec.GetPath(path, sizeof(path)) == 0) + return {}; - FileSpec dsym_fspec; + ::strncat(path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1); - if (dsym_bundle_fspec.GetPath(path, sizeof(path))) { - ::strncat(path, "/Contents/Resources/DWARF", - sizeof(path) - strlen(path) - 1); + DIR *dirp = opendir(path); + if (!dirp) + return {}; - lldb_utility::CleanUp<DIR *, int> dirp(opendir(path), NULL, closedir); - if (dirp.is_valid()) { - dsym_fspec.GetDirectory().SetCString(path); - struct dirent *dp; - while ((dp = readdir(dirp.get())) != NULL) { - // Only search directories - if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) { - if (dp->d_namlen == 1 && dp->d_name[0] == '.') - continue; + // Make sure we close the directory before exiting this scope. + CleanUp cleanup_dir(closedir, dirp); - if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') - continue; - } + FileSpec dsym_fspec; + dsym_fspec.GetDirectory().SetCString(path); + struct dirent *dp; + while ((dp = readdir(dirp)) != NULL) { + // Only search directories + if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) { + if (dp->d_namlen == 1 && dp->d_name[0] == '.') + continue; - if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN) { - dsym_fspec.GetFilename().SetCString(dp->d_name); - ModuleSpecList module_specs; - if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, - module_specs)) { - ModuleSpec spec; - for (size_t i = 0; i < module_specs.GetSize(); ++i) { - 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)))) { - return dsym_fspec; - } - } + if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') + continue; + } + + if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN) { + dsym_fspec.GetFilename().SetCString(dp->d_name); + ModuleSpecList module_specs; + if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs)) { + ModuleSpec spec; + for (size_t i = 0; i < module_specs.GetSize(); ++i) { + 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)))) { + return dsym_fspec; } } } } } - dsym_fspec.Clear(); - return dsym_fspec; + + return {}; } static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, @@ -302,7 +309,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { - module_spec.GetFileSpec().SetFile(str.c_str(), true); + module_spec.GetFileSpec().SetFile(str.c_str(), true, + FileSpec::Style::native); if (log) { log->Printf( "From dsymForUUID plist: Symbol rich executable is at '%s'", @@ -315,7 +323,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, CFSTR("DBGDSYMPath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { - module_spec.GetSymbolFileSpec().SetFile(str.c_str(), true); + module_spec.GetSymbolFileSpec().SetFile(str.c_str(), true, + FileSpec::Style::native); success = true; if (log) { log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); @@ -333,28 +342,13 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, std::string DBGBuildSourcePath; std::string DBGSourcePath; - cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, - CFSTR("DBGBuildSourcePath")); - if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { - CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); - } - - cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, - CFSTR("DBGSourcePath")); - if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { - CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); - } - - if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { - if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path(DBGSourcePath.c_str(), true); - DBGSourcePath = resolved_source_path.GetPath(); - } - module_spec.GetSourceMappingList().Append( - ConstString(DBGBuildSourcePath.c_str()), - ConstString(DBGSourcePath.c_str()), true); - } - + // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping. + // If DBGVersion 2, strip last two components of path remappings from + // entries to fix an issue with a specific set of + // DBGSourcePathRemapping entries that lldb worked + // with. + // If DBGVersion 3, trust & use the source path remappings as-is. + // cf_dict = (CFDictionaryRef)CFDictionaryGetValue( (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping")); if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) { @@ -401,10 +395,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, } if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { // In the "old style" DBGSourcePathRemapping dictionary, the - // DBGSourcePath values - // (the "values" half of key-value path pairs) were wrong. Ignore - // them and use the - // universal DBGSourcePath string from earlier. + // DBGSourcePath values (the "values" half of key-value path pairs) + // were wrong. Ignore them and use the universal DBGSourcePath + // string from earlier. if (new_style_source_remapping_dictionary == true && !original_DBGSourcePath_value.empty()) { DBGSourcePath = original_DBGSourcePath_value; @@ -414,9 +407,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, DBGSourcePath = resolved_source_path.GetPath(); } // With version 2 of DBGSourcePathRemapping, we can chop off the - // last two filename parts from the source remapping and get a - // more general source remapping that still works. Add this as - // another option in addition to the full source path remap. + // last two filename parts from the source remapping and get a more + // general source remapping that still works. Add this as another + // option in addition to the full source path remap. module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); @@ -439,6 +432,32 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, free(values); } } + + + // If we have a DBGBuildSourcePath + DBGSourcePath pair, append them to the + // source remappings list. + + cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, + CFSTR("DBGBuildSourcePath")); + if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); + } + + cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, + CFSTR("DBGSourcePath")); + if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); + } + + if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { + if (DBGSourcePath[0] == '~') { + FileSpec resolved_source_path(DBGSourcePath.c_str(), true); + DBGSourcePath = resolved_source_path.GetPath(); + } + module_spec.GetSourceMappingList().Append( + ConstString(DBGBuildSourcePath.c_str()), + ConstString(DBGSourcePath.c_str()), true); + } } return success; } @@ -450,8 +469,7 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); // It's expensive to check for the DBGShellCommands defaults setting, only do - // it once per - // lldb run and cache the result. + // it once per lldb run and cache the result. static bool g_have_checked_for_dbgshell_command = false; static const char *g_dbgshell_command = NULL; if (g_have_checked_for_dbgshell_command == false) { @@ -473,8 +491,7 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, } // When g_dbgshell_command is NULL, the user has not enabled the use of an - // external program - // to find the symbols, don't run it for them. + // external program to find the symbols, don't run it for them. if (force_lookup == false && g_dbgshell_command == NULL) { return false; } @@ -489,12 +506,14 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE"); FileSpec dsym_for_uuid_exe_spec; if (dsym_for_uuid_exe_path_cstr) { - dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true); + dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true, + FileSpec::Style::native); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } if (!g_dsym_for_uuid_exe_exists) { - dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false); + dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false, + FileSpec::Style::native); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); if (!g_dsym_for_uuid_exe_exists) { long bufsize; @@ -508,14 +527,16 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, tilde_rc && tilde_rc->pw_dir) { std::string dsymforuuid_path(tilde_rc->pw_dir); dsymforuuid_path += "/bin/dsymForUUID"; - dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false); + dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false, + FileSpec::Style::native); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } } } } if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) { - dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true); + dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true, + FileSpec::Style::native); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } @@ -561,8 +582,9 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, &exit_status, // Exit status &signo, // Signal int * &command_output, // Command output - 30, // Large timeout to allow for long dsym download times - false); // Don't run in a shell (we don't need shell expansion) + std::chrono::seconds( + 30), // Large timeout to allow for long dsym download times + false); // Don't run in a shell (we don't need shell expansion) if (error.Success() && exit_status == 0 && !command_output.empty()) { CFCData data(CFDataCreateWithBytesNoCopy( NULL, (const UInt8 *)command_output.data(), command_output.size(), diff --git a/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp b/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp index 201ec9a8f5c24..0c52aa3ed0517 100644 --- a/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp +++ b/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp @@ -352,9 +352,8 @@ bool CFCMutableDictionary::AddValueUInt64(CFStringRef key, uint64_t value, CFMutableDictionaryRef dict = Dictionary(can_create); if (dict != NULL) { // The number may appear negative if the MSBit is set in "value". Due to a - // limitation of - // CFNumber, there isn't a way to have it show up otherwise as of this - // writing. + // limitation of CFNumber, there isn't a way to have it show up otherwise + // as of this writing. CFCReleaser<CFNumberRef> cf_number( ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); if (cf_number.get()) { @@ -371,9 +370,8 @@ bool CFCMutableDictionary::SetValueUInt64(CFStringRef key, uint64_t value, CFMutableDictionaryRef dict = Dictionary(can_create); if (dict != NULL) { // The number may appear negative if the MSBit is set in "value". Due to a - // limitation of - // CFNumber, there isn't a way to have it show up otherwise as of this - // writing. + // limitation of CFNumber, there isn't a way to have it show up otherwise + // as of this writing. CFCReleaser<CFNumberRef> cf_number( ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); if (cf_number.get()) { @@ -390,9 +388,8 @@ bool CFCMutableDictionary::AddValueDouble(CFStringRef key, double value, CFMutableDictionaryRef dict = Dictionary(can_create); if (dict != NULL) { // The number may appear negative if the MSBit is set in "value". Due to a - // limitation of - // CFNumber, there isn't a way to have it show up otherwise as of this - // writing. + // limitation of CFNumber, there isn't a way to have it show up otherwise + // as of this writing. CFCReleaser<CFNumberRef> cf_number( ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); if (cf_number.get()) { @@ -409,9 +406,8 @@ bool CFCMutableDictionary::SetValueDouble(CFStringRef key, double value, CFMutableDictionaryRef dict = Dictionary(can_create); if (dict != NULL) { // The number may appear negative if the MSBit is set in "value". Due to a - // limitation of - // CFNumber, there isn't a way to have it show up otherwise as of this - // writing. + // limitation of CFNumber, there isn't a way to have it show up otherwise + // as of this writing. CFCReleaser<CFNumberRef> cf_number( ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); if (cf_number.get()) { diff --git a/source/Host/macosx/cfcpp/CFCString.cpp b/source/Host/macosx/cfcpp/CFCString.cpp index 0d3853c60a72f..6191f873c98a2 100644 --- a/source/Host/macosx/cfcpp/CFCString.cpp +++ b/source/Host/macosx/cfcpp/CFCString.cpp @@ -88,9 +88,8 @@ const char *CFCString::UTF8(std::string &str) { return CFCString::UTF8(get(), str); } -// Static function that puts a copy of the UTF8 contents of CF_STR into STR -// and returns the C string pointer that is contained in STR when successful, -// else +// Static function that puts a copy of the UTF8 contents of CF_STR into STR and +// returns the C string pointer that is contained in STR when successful, else // NULL is returned. This allows the std::string parameter to own the extracted // string, // and also allows that string to be returned as a C string pointer that can be @@ -129,9 +128,9 @@ const char *CFCString::ExpandTildeInPath(const char *path, // Static function that puts a copy of the file system representation of CF_STR // into STR and returns the C string pointer that is contained in STR when -// successful, else NULL is returned. This allows the std::string parameter -// to own the extracted string, and also allows that string to be returned as -// a C string pointer that can be used. +// successful, else NULL is returned. This allows the std::string parameter to +// own the extracted string, and also allows that string to be returned as a C +// string pointer that can be used. const char *CFCString::FileSystemRepresentation(CFStringRef cf_str, std::string &str) { diff --git a/source/Host/macosx/objcxx/CMakeLists.txt b/source/Host/macosx/objcxx/CMakeLists.txt new file mode 100644 index 0000000000000..77e3091dc4fed --- /dev/null +++ b/source/Host/macosx/objcxx/CMakeLists.txt @@ -0,0 +1,20 @@ + +remove_module_flags() +include_directories(..) + +add_lldb_library(lldbHostMacOSXObjCXX + Host.mm + HostInfoMacOSX.mm + HostThreadMacOSX.mm + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbUtility + ${EXTRA_LIBS} + + LINK_COMPONENTS + Object + Support + ) diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/objcxx/Host.mm index 7359815fdf704..a70bf0421ec48 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/objcxx/Host.mm @@ -54,13 +54,10 @@ #include <sys/types.h> #include <unistd.h> -#include "lldb/Core/Communication.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/Platform.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Process.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/CleanUp.h" @@ -72,15 +69,16 @@ #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-defines.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Errno.h" -#include "cfcpp/CFCBundle.h" -#include "cfcpp/CFCMutableArray.h" -#include "cfcpp/CFCMutableDictionary.h" -#include "cfcpp/CFCReleaser.h" -#include "cfcpp/CFCString.h" +#include "../cfcpp/CFCBundle.h" +#include "../cfcpp/CFCMutableArray.h" +#include "../cfcpp/CFCMutableDictionary.h" +#include "../cfcpp/CFCReleaser.h" +#include "../cfcpp/CFCString.h" #include <objc/objc-auto.h> @@ -107,7 +105,7 @@ bool Host::GetBundleDirectory(const FileSpec &file, if (file.GetPath(path, sizeof(path))) { CFCBundle bundle(path); if (bundle.GetPath(path, sizeof(path))) { - bundle_directory.SetFile(path, false); + bundle_directory.SetFile(path, false, FileSpec::Style::native); return true; } } @@ -127,7 +125,7 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) { if (url.get()) { if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path, sizeof(path))) { - file.SetFile(path, false); + file.SetFile(path, false, FileSpec::Style::native); return true; } } @@ -184,175 +182,6 @@ static bool WaitForProcessToSIGSTOP(const lldb::pid_t pid, } #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) -// static lldb::pid_t -// LaunchInNewTerminalWithCommandFile -//( -// const char **argv, -// const char **envp, -// const char *working_dir, -// const ArchSpec *arch_spec, -// bool stop_at_entry, -// bool disable_aslr -//) -//{ -// if (!argv || !argv[0]) -// return LLDB_INVALID_PROCESS_ID; -// -// OSStatus error = 0; -// -// FileSpec program (argv[0], false); -// -// -// std::string unix_socket_name; -// -// char temp_file_path[PATH_MAX]; -// const char *tmpdir = ::getenv ("TMPDIR"); -// if (tmpdir == NULL) -// tmpdir = "/tmp/"; -// ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, -// program.GetFilename().AsCString()); -// -// if (::mktemp (temp_file_path) == NULL) -// return LLDB_INVALID_PROCESS_ID; -// -// unix_socket_name.assign (temp_file_path); -// -// ::strlcat (temp_file_path, ".command", sizeof (temp_file_path)); -// -// StreamFile command_file; -// command_file.GetFile().Open (temp_file_path, -// File::eOpenOptionWrite | -// File::eOpenOptionCanCreate, -// lldb::eFilePermissionsDefault); -// -// if (!command_file.GetFile().IsValid()) -// return LLDB_INVALID_PROCESS_ID; -// -// FileSpec darwin_debug_file_spec; -// if (!HostInfo::GetLLDBPath (ePathTypeSupportExecutableDir, -// darwin_debug_file_spec)) -// return LLDB_INVALID_PROCESS_ID; -// darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); -// -// if (!darwin_debug_file_spec.Exists()) -// return LLDB_INVALID_PROCESS_ID; -// -// char launcher_path[PATH_MAX]; -// darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); -// command_file.Printf("\"%s\" ", launcher_path); -// -// command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str()); -// -// if (arch_spec && arch_spec->IsValid()) -// { -// command_file.Printf("--arch=%s ", arch_spec->GetArchitectureName()); -// } -// -// if (disable_aslr) -// { -// command_file.PutCString("--disable-aslr "); -// } -// -// command_file.PutCString("-- "); -// -// if (argv) -// { -// for (size_t i=0; argv[i] != NULL; ++i) -// { -// command_file.Printf("\"%s\" ", argv[i]); -// } -// } -// command_file.PutCString("\necho Process exited with status $?\n"); -// command_file.GetFile().Close(); -// if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0) -// return LLDB_INVALID_PROCESS_ID; -// -// CFCMutableDictionary cf_env_dict; -// -// const bool can_create = true; -// if (envp) -// { -// for (size_t i=0; envp[i] != NULL; ++i) -// { -// const char *env_entry = envp[i]; -// const char *equal_pos = strchr(env_entry, '='); -// if (equal_pos) -// { -// std::string env_key (env_entry, equal_pos); -// std::string env_val (equal_pos + 1); -// CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8); -// CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8); -// cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), -// can_create); -// } -// } -// } -// -// LSApplicationParameters app_params; -// ::memset (&app_params, 0, sizeof (app_params)); -// app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync; -// app_params.argv = NULL; -// app_params.environment = (CFDictionaryRef)cf_env_dict.get(); -// -// CFCReleaser<CFURLRef> command_file_url -// (::CFURLCreateFromFileSystemRepresentation (NULL, -// (const UInt8 *)temp_file_path, -// strlen(temp_file_path), -// false)); -// -// CFCMutableArray urls; -// -// // Terminal.app will open the ".command" file we have created -// // and run our process inside it which will wait at the entry point -// // for us to attach. -// urls.AppendValue(command_file_url.get()); -// -// -// lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; -// -// Status lldb_error; -// // Sleep and wait a bit for debugserver to start to listen... -// char connect_url[128]; -// ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", -// unix_socket_name.c_str()); -// -// // Spawn a new thread to accept incoming connection on the connect_url -// // so we can grab the pid from the inferior -// lldb::thread_t accept_thread = Host::ThreadCreate -// (unix_socket_name.c_str(), -// AcceptPIDFromInferior, -// connect_url, -// &lldb_error); -// -// ProcessSerialNumber psn; -// error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, -// &psn, 1); -// if (error == noErr) -// { -// thread_result_t accept_thread_result = NULL; -// if (Host::ThreadJoin (accept_thread, &accept_thread_result, -// &lldb_error)) -// { -// if (accept_thread_result) -// { -// pid = (intptr_t)accept_thread_result; -// -// // Wait for process to be stopped the entry point by watching -// // for the process status to be set to SSTOP which indicates -// it it -// // SIGSTOP'ed at the entry point -// WaitForProcessToSIGSTOP (pid, 5); -// } -// } -// } -// else -// { -// Host::ThreadCancel (accept_thread, &lldb_error); -// } -// -// return pid; -//} - const char *applscript_in_new_tty = "tell application \"Terminal\"\n" " activate\n" " do script \"/bin/bash -c '%s';exit\"\n" @@ -388,9 +217,8 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path, } StreamString command; - FileSpec darwin_debug_file_spec; - if (!HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, - darwin_debug_file_spec)) { + FileSpec darwin_debug_file_spec = HostInfo::GetSupportExeDir(); + if (!darwin_debug_file_spec) { error.SetErrorString("can't locate the 'darwin-debug' executable"); return error; } @@ -431,33 +259,16 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path, command.PutCString(" --disable-aslr"); // We are launching on this host in a terminal. So compare the environment on - // the host - // to what is supplied in the launch_info. Any items that aren't in the host - // environment - // need to be sent to darwin-debug. If we send all environment entries, we - // might blow the - // max command line length, so we only send user modified entries. - const char **envp = - launch_info.GetEnvironmentEntries().GetConstArgumentVector(); - - StringList host_env; - const size_t host_env_count = Host::GetEnvironment(host_env); + // the host to what is supplied in the launch_info. Any items that aren't in + // the host environment need to be sent to darwin-debug. If we send all + // environment entries, we might blow the max command line length, so we only + // send user modified entries. + Environment host_env = Host::GetEnvironment(); - if (envp && envp[0]) { - const char *env_entry; - for (size_t env_idx = 0; (env_entry = envp[env_idx]) != NULL; ++env_idx) { - bool add_entry = true; - for (size_t i = 0; i < host_env_count; ++i) { - const char *host_env_entry = host_env.GetStringAtIndex(i); - if (strcmp(env_entry, host_env_entry) == 0) { - add_entry = false; - break; - } - } - if (add_entry) { - command.Printf(" --env='%s'", env_entry); - } - } + for (const auto &KV : launch_info.GetEnvironment()) { + auto host_entry = host_env.find(KV.first()); + if (host_entry == host_env.end() || host_entry->second != KV.second) + command.Format(" --env='{0}'", Environment::compose(KV)); } command.PutCString(" -- "); @@ -479,19 +290,8 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path, StreamString applescript_source; - // if (tty_name && tty_name[0]) - // { - // applescript_source.Printf (applscript_in_existing_tty, - // tty_command, - // tty_name); - // } - // else - // { applescript_source.Printf(applscript_in_new_tty, command.GetString().str().c_str()); - // } - - // puts (script_source); NSAppleScript *applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:applescript_source.GetString() .str() @@ -641,14 +441,7 @@ bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, #endif // #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) } -size_t Host::GetEnvironment(StringList &env) { - char **host_env = *_NSGetEnviron(); - char *env_entry; - size_t i; - for (i = 0; (env_entry = host_env[i]) != NULL; ++i) - env.AppendString(env_entry); - return i; -} +Environment Host::GetEnvironment() { return Environment(*_NSGetEnviron()); } static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { @@ -748,7 +541,8 @@ static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, triple_arch == llvm::Triple::x86_64); const char *cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false); + process_info.GetExecutableFile().SetFile(cstr, false, + FileSpec::Style::native); if (match_info_ptr == NULL || NameMatches( @@ -770,7 +564,7 @@ static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, proc_args.AppendArgument(llvm::StringRef(cstr)); } - Args &proc_env = process_info.GetEnvironmentEntries(); + Environment &proc_env = process_info.GetEnvironment(); while ((cstr = data.GetCStr(&offset))) { if (cstr[0] == '\0') break; @@ -785,7 +579,7 @@ static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, llvm::Triple::MacOSX); } - proc_env.AppendArgument(llvm::StringRef(cstr)); + proc_env.insert(cstr); } return true; } @@ -939,6 +733,17 @@ static void PackageXPCArguments(xpc_object_t message, const char *prefix, } } +static void PackageXPCEnvironment(xpc_object_t message, llvm::StringRef prefix, + const Environment &env) { + xpc_dictionary_set_int64(message, (prefix + "Count").str().c_str(), + env.size()); + size_t i = 0; + for (const auto &KV : env) { + xpc_dictionary_set_string(message, (prefix + llvm::Twine(i)).str().c_str(), + Environment::compose(KV).c_str()); + } +} + /* A valid authorizationRef means that - there is the LaunchUsingXPCRightName rights in the /etc/authorization @@ -1045,14 +850,11 @@ static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { if (g_use_close_on_exec_flag == eLazyBoolCalculate) { g_use_close_on_exec_flag = eLazyBoolNo; - uint32_t major, minor, update; - if (HostInfo::GetOSVersion(major, minor, update)) { + llvm::VersionTuple version = HostInfo::GetOSVersion(); + if (version > llvm::VersionTuple(10, 7)) { // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or // earlier - if (major > 10 || (major == 10 && minor > 7)) { - // Only enable for 10.8 and later OS versions - g_use_close_on_exec_flag = eLazyBoolYes; - } + g_use_close_on_exec_flag = eLazyBoolYes; } } #else @@ -1141,8 +943,8 @@ static Status LaunchProcessXPC(const char *exe_path, PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments()); - PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, - launch_info.GetEnvironmentEntries()); + PackageXPCEnvironment(message, LauncherXPCServiceEnvPrefxKey, + launch_info.GetEnvironment()); // Posix spawn stuff. xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, @@ -1294,10 +1096,8 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, return error; } - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup( - &attr, posix_spawnattr_destroy); + // Make sure we clean up the posix spawn attributes before exiting this scope. + CleanUp cleanup_attr(posix_spawnattr_destroy, &attr); sigset_t no_signals; sigset_t all_signals; @@ -1356,8 +1156,7 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, const char *tmp_argv[2]; char *const *argv = const_cast<char *const *>( launch_info.GetArguments().GetConstArgumentVector()); - char *const *envp = const_cast<char *const *>( - launch_info.GetEnvironmentEntries().GetConstArgumentVector()); + Environment::Envp envp = launch_info.GetEnvironment().getEnvp(); if (argv == NULL) { // posix_spawn gets very unhappy if it doesn't have at least the program // name in argv[0]. One of the side affects I have noticed is the @@ -1400,11 +1199,8 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, return error; } - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp<posix_spawn_file_actions_t *, int> - posix_spawn_file_actions_cleanup(&file_actions, - posix_spawn_file_actions_destroy); + // Make sure we clean up the posix file actions before exiting this scope. + CleanUp cleanup_fileact(posix_spawn_file_actions_destroy, &file_actions); for (size_t i = 0; i < num_file_actions; ++i) { const FileAction *launch_file_action = @@ -1425,7 +1221,8 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, "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); + error, result_pid, exe_path, &file_actions, &attr, argv, + envp.get()); if (log) { for (int ii = 0; argv[ii]; ++ii) LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); @@ -1441,7 +1238,7 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, 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); + error, result_pid, exe_path, &attr, argv, envp.get()); if (log) { for (int ii = 0; argv[ii]; ++ii) LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); @@ -1476,36 +1273,28 @@ static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) { Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; - char exe_path[PATH_MAX]; - PlatformSP host_platform_sp(Platform::GetHostPlatform()); - - ModuleSpec exe_module_spec(launch_info.GetExecutableFile(), - launch_info.GetArchitecture()); - - 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); - - if (error.Fail()) - return error; + FileSpec exe_spec(launch_info.GetExecutableFile()); - if (exe_module_sp) - exe_module_spec.GetFileSpec() = exe_module_sp->GetFileSpec(); + llvm::sys::fs::file_status stats; + status(exe_spec.GetPath(), stats); + if (!exists(stats)) { + exe_spec.ResolvePath(); + status(exe_spec.GetPath(), stats); } - - if (exe_module_spec.GetFileSpec().Exists()) { - exe_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - } else { - launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + if (!exists(stats)) { + exe_spec.ResolveExecutableLocation(); + status(exe_spec.GetPath(), stats); + } + if (!exists(stats)) { + error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'", + launch_info.GetExecutableFile()); return error; } if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) { #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) - return LaunchInNewTerminalWithAppleScript(exe_path, launch_info); + return LaunchInNewTerminalWithAppleScript(exe_spec.GetPath().c_str(), + launch_info); #else error.SetErrorString("launching a process in a new terminal is not " "supported on iOS devices"); @@ -1516,9 +1305,10 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (ShouldLaunchUsingXPC(launch_info)) { - error = LaunchProcessXPC(exe_path, launch_info, pid); + error = LaunchProcessXPC(exe_spec.GetPath().c_str(), launch_info, pid); } else { - error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); + error = + LaunchProcessPosixSpawn(exe_spec.GetPath().c_str(), launch_info, pid); } if (pid != LLDB_INVALID_PROCESS_ID) { @@ -1526,15 +1316,9 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { launch_info.SetProcessID(pid); // Make sure we reap any processes we spawn or we will have zombies. - if (!launch_info.MonitorProcess()) { - const bool monitor_signals = false; - Host::MonitorChildProcessCallback callback = nullptr; - - if (!launch_info.GetFlags().Test(lldb::eLaunchFlagDontSetExitStatus)) - callback = Process::SetProcessExitStatus; - - StartMonitoringChildProcess(callback, pid, monitor_signals); - } + bool monitoring = launch_info.MonitorProcess(); + UNUSED_IF_ASSERT_DISABLED(monitoring); + assert(monitoring); } else { // Invalid process ID, something didn't go well if (error.Success()) @@ -1546,9 +1330,8 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { Status error; if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { - FileSpec expand_tool_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, - expand_tool_spec)) { + FileSpec expand_tool_spec = HostInfo::GetSupportExeDir(); + if (!expand_tool_spec) { error.SetErrorString( "could not get support executable directory for lldb-argdumper tool"); return error; @@ -1583,7 +1366,8 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { launch_info.SetWorkingDirectory(working_dir); } } - RunShellCommand(expand_command, cwd, &status, nullptr, &output, 10); + RunShellCommand(expand_command, cwd, &status, nullptr, &output, + std::chrono::seconds(10)); if (status != 0) { error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", diff --git a/source/Host/macosx/HostInfoMacOSX.mm b/source/Host/macosx/objcxx/HostInfoMacOSX.mm index 8774c76ef2dad..a39d26aa31ae4 100644 --- a/source/Host/macosx/HostInfoMacOSX.mm +++ b/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -7,18 +7,15 @@ // //===----------------------------------------------------------------------===// -#if !defined(LLDB_DISABLE_PYTHON) -#include "Plugins/ScriptInterpreter/Python/lldb-python.h" -#endif - #include "lldb/Host/HostInfo.h" #include "lldb/Host/macosx/HostInfoMacOSX.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Utility/Args.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/SafeMachO.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" // C++ Includes @@ -30,7 +27,7 @@ #include <sys/syslimits.h> #include <sys/types.h> -// Objective C/C++ includes +// Objective-C/C++ includes #include <CoreFoundation/CoreFoundation.h> #include <Foundation/Foundation.h> #include <mach-o/dyld.h> @@ -75,32 +72,21 @@ bool HostInfoMacOSX::GetOSKernelDescription(std::string &s) { return false; } -bool HostInfoMacOSX::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - static uint32_t g_major = 0; - static uint32_t g_minor = 0; - static uint32_t g_update = 0; +llvm::VersionTuple HostInfoMacOSX::GetOSVersion() { + static llvm::VersionTuple g_version; - if (g_major == 0) { + if (g_version.empty()) { @autoreleasepool { NSDictionary *version_info = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/CoreServices/SystemVersion.plist"]; NSString *version_value = [version_info objectForKey:@"ProductVersion"]; const char *version_str = [version_value UTF8String]; - if (version_str) - Args::StringToVersion(llvm::StringRef(version_str), g_major, g_minor, - g_update); + g_version.tryParse(version_str); } } - if (g_major != 0) { - major = g_major; - minor = g_minor; - update = g_update; - return true; - } - return false; + return g_version; } FileSpec HostInfoMacOSX::GetProgramFileSpec() { @@ -111,13 +97,15 @@ FileSpec HostInfoMacOSX::GetProgramFileSpec() { uint32_t len = sizeof(program_fullpath); int err = _NSGetExecutablePath(program_fullpath, &len); if (err == 0) - g_program_filespec.SetFile(program_fullpath, false); + g_program_filespec.SetFile(program_fullpath, false, + FileSpec::Style::native); else if (err == -1) { char *large_program_fullpath = (char *)::malloc(len + 1); err = _NSGetExecutablePath(large_program_fullpath, &len); if (err == 0) - g_program_filespec.SetFile(large_program_fullpath, false); + g_program_filespec.SetFile(large_program_fullpath, false, + FileSpec::Style::native); ::free(large_program_fullpath); } @@ -126,8 +114,8 @@ FileSpec HostInfoMacOSX::GetProgramFileSpec() { } bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) { - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + FileSpec lldb_file_spec = GetShlibDir(); + if (!lldb_file_spec) return false; std::string raw_path = lldb_file_spec.GetPath(); @@ -179,8 +167,8 @@ bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) { } bool HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) { - FileSpec lldb_file_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + FileSpec lldb_file_spec = GetShlibDir(); + if (!lldb_file_spec) return false; std::string raw_path = lldb_file_spec.GetPath(); @@ -196,58 +184,9 @@ bool HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) { return true; } -bool HostInfoMacOSX::ComputePythonDirectory(FileSpec &file_spec) { -#ifndef LLDB_DISABLE_PYTHON - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - - std::string raw_path = lldb_file_spec.GetPath(); - - size_t framework_pos = raw_path.find("LLDB.framework"); - if (framework_pos != std::string::npos) { - framework_pos += strlen("LLDB.framework"); - raw_path.resize(framework_pos); - raw_path.append("/Resources/Python"); - } else { - llvm::SmallString<256> python_version_dir; - llvm::raw_svector_ostream os(python_version_dir); - os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION - << "/site-packages"; - - // We may get our string truncated. Should we protect this with an assert? - raw_path.append(python_version_dir.c_str()); - } - file_spec.GetDirectory().SetString( - llvm::StringRef(raw_path.c_str(), raw_path.size())); - return true; -#else - return false; -#endif -} - -bool HostInfoMacOSX::ComputeClangDirectory(FileSpec &file_spec) { - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - - std::string raw_path = lldb_file_spec.GetPath(); - - size_t framework_pos = raw_path.find("LLDB.framework"); - if (framework_pos == std::string::npos) - return HostInfoPosix::ComputeClangDirectory(file_spec); - - framework_pos += strlen("LLDB.framework"); - raw_path.resize(framework_pos); - raw_path.append("/Resources/Clang"); - - file_spec.SetFile(raw_path.c_str(), true); - return true; -} - bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) { - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + FileSpec lldb_file_spec = GetShlibDir(); + if (!lldb_file_spec) return false; std::string raw_path = lldb_file_spec.GetPath(); diff --git a/source/Host/macosx/HostThreadMacOSX.mm b/source/Host/macosx/objcxx/HostThreadMacOSX.mm index c5051cdf30d77..c5051cdf30d77 100644 --- a/source/Host/macosx/HostThreadMacOSX.mm +++ b/source/Host/macosx/objcxx/HostThreadMacOSX.mm diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp index d927f95f06753..bfd5a74ffcc21 100644 --- a/source/Host/netbsd/Host.cpp +++ b/source/Host/netbsd/Host.cpp @@ -25,12 +25,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Module.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.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" @@ -48,14 +45,7 @@ extern char **environ; using namespace lldb; using namespace lldb_private; -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; -} +Environment Host::GetEnvironment() { return Environment(environ); } static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { @@ -80,7 +70,8 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, if (!cstr) return false; - process_info.GetExecutableFile().SetFile(cstr, false); + process_info.GetExecutableFile().SetFile(cstr, false, + FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), @@ -202,9 +193,8 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, continue; // Every thread is a process in NetBSD, but all the threads of a single - // process have the same pid. Do not store the process info in the - // result list if a process with given identifier is already registered - // there. + // process have the same pid. Do not store the process info in the result + // list if a process with given identifier is already registered there. if (proc_kinfo[i].p_nlwps > 1) { bool already_registered = false; for (size_t pi = 0; pi < process_infos.GetSize(); pi++) { diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp index 428183bbe2c3f..dfbce310509dc 100644 --- a/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/source/Host/netbsd/HostInfoNetBSD.cpp @@ -21,30 +21,26 @@ using namespace lldb_private; -bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoNetBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(un)); if (::uname(&un) < 0) - return false; + return llvm::VersionTuple(); /* Accept versions like 7.99.21 and 6.1_STABLE */ + uint32_t major, minor, update; int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, &minor, &update); switch (status) { - case 0: - return false; case 1: - minor = 0; - /* FALLTHROUGH */ + return llvm::VersionTuple(major); case 2: - update = 0; - /* FALLTHROUGH */ + return llvm::VersionTuple(major, minor); case 3: - default: - return true; + return llvm::VersionTuple(major, minor, update); } + return llvm::VersionTuple(); } bool HostInfoNetBSD::GetOSBuildString(std::string &s) { @@ -89,7 +85,7 @@ FileSpec HostInfoNetBSD::GetProgramFileSpec() { len = sizeof(path); if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1) { - g_program_filespec.SetFile(path, false); + g_program_filespec.SetFile(path, false, FileSpec::Style::native); } } return g_program_filespec; diff --git a/source/Host/openbsd/Host.cpp b/source/Host/openbsd/Host.cpp index 0535256b9aa1f..49e9c290a027e 100644 --- a/source/Host/openbsd/Host.cpp +++ b/source/Host/openbsd/Host.cpp @@ -22,12 +22,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Module.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.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" @@ -45,16 +42,17 @@ extern char **environ; using namespace lldb; using namespace lldb_private; -size_t Host::GetEnvironment(StringList &env) { +Environment Host::GetEnvironment() { + Environment env; char *v; char **var = environ; for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; - env.AppendString(v); + env.insert(v); } - return env.GetSize(); + return env; } static bool @@ -74,7 +72,8 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false); + process_info.GetExecutableFile().SetFile(cstr, false, + FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches( diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 3797650105ce3..c21bb786a8962 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -189,15 +189,14 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, } #ifndef LLDB_DISABLE_POSIX else if ((addr = GetURLAddress(path, FD_SCHEME))) { - // Just passing a native file descriptor within this current process - // that is already opened (possibly from a service or other source). + // Just passing a native file descriptor within this current process that + // is already opened (possibly from a service or other source). int fd = -1; if (!addr->getAsInteger(0, fd)) { - // We have what looks to be a valid file descriptor, but we - // should make sure it is. We currently are doing this by trying to - // get the flags from the file descriptor and making sure it - // isn't a bad fd. + // We have what looks to be a valid file descriptor, but we should make + // sure it is. We currently are doing this by trying to get the flags + // from the file descriptor and making sure it isn't a bad fd. errno = 0; int flags = ::fcntl(fd, F_GETFL, 0); if (flags == -1 || errno == EBADF) { @@ -208,20 +207,18 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, m_write_sp.reset(); return eConnectionStatusError; } else { - // Don't take ownership of a file descriptor that gets passed - // to us since someone else opened the file descriptor and - // handed it to us. + // Don't take ownership of a file descriptor that gets passed to us + // since someone else opened the file descriptor and handed it to us. // TODO: Since are using a URL to open connection we should - // eventually parse options using the web standard where we - // have "fd://123?opt1=value;opt2=value" and we can have an - // option be "owns=1" or "owns=0" or something like this to - // allow us to specify this. For now, we assume we must - // assume we don't own it. + // eventually parse options using the web standard where we have + // "fd://123?opt1=value;opt2=value" and we can have an option be + // "owns=1" or "owns=0" or something like this to allow us to specify + // this. For now, we assume we must assume we don't own it. std::unique_ptr<TCPSocket> tcp_socket; tcp_socket.reset(new TCPSocket(fd, false, false)); - // Try and get a socket option from this file descriptor to - // see if this is a socket and set m_is_socket accordingly. + // Try and get a socket option from this file descriptor to see if + // this is a socket and set m_is_socket accordingly. int resuse; bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); @@ -320,13 +317,11 @@ ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { m_read_sp->GetFdType() == IOObject::eFDTypeSocket) static_cast<Socket &>(*m_read_sp).PreDisconnect(); - // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite - // likely - // because somebody is doing a blocking read on our file descriptor. If - // that's the case, - // then send the "q" char to the command file channel so the read will wake up - // and the connection - // will then know to shut down. + // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is + // quite likely because somebody is doing a blocking read on our file + // descriptor. If that's the case, then send the "q" char to the command + // file channel so the read will wake up and the connection will then know to + // shut down. m_shutting_down = true; @@ -430,11 +425,11 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, case EINVAL: // The pointer associated with fildes was negative. case EIO: // An I/O error occurred while reading from the file system. // The process group is orphaned. - // The file is a regular file, nbyte is greater than 0, - // the starting position is before the end-of-file, and - // the starting position is greater than or equal to the - // offset maximum established for the open file - // descriptor associated with fildes. + // The file is a regular file, nbyte is greater than 0, the + // starting position is before the end-of-file, and the + // starting position is greater than or equal to the offset + // maximum established for the open file descriptor + // associated with fildes. case EISDIR: // An attempt is made to read a directory. case ENOBUFS: // An attempt to allocate a memory buffer fails. case ENOMEM: // Insufficient memory is available. @@ -550,15 +545,15 @@ ConnectionStatus ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, Status *error_ptr) { // Don't need to take the mutex here separately since we are only called from - // Read. If we - // ever get used more generally we will need to lock here as well. + // Read. If we ever get used more generally we will need to lock here as + // well. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); 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 - // and cause problems in the loop below where like in FS_SET() + // Make a copy of the file descriptors to make sure we don't have another + // thread change these values out from under us and cause problems in the + // loop below where like in FS_SET() const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); const int pipe_fd = m_pipe.GetReadFileDescriptor(); @@ -570,10 +565,9 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, select_helper.FDSetRead(handle); #if defined(_MSC_VER) // select() won't accept pipes on Windows. The entire Windows codepath - // needs to be - // converted over to using WaitForMultipleObjects and event HANDLEs, but for - // now at least - // this will allow ::select() to not return an error. + // needs to be converted over to using WaitForMultipleObjects and event + // HANDLEs, but for now at least this will allow ::select() to not return + // an error. const bool have_pipe_fd = false; #else const bool have_pipe_fd = pipe_fd >= 0; @@ -603,11 +597,10 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, return eConnectionStatusTimedOut; case EAGAIN: // The kernel was (perhaps temporarily) unable to - // allocate the requested number of file descriptors, - // or we have non-blocking IO + // allocate the requested number of file descriptors, or + // we have non-blocking IO case EINTR: // A signal was delivered before the time limit - // expired and before any of the selected events - // occurred. + // expired and before any of the selected events occurred. break; // Lets keep reading to until we timeout } } else { @@ -615,8 +608,8 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, return eConnectionStatusSuccess; if (select_helper.FDIsSetRead(pipe_fd)) { - // There is an interrupt or exit command in the command pipe - // Read the data from that pipe: + // There is an interrupt or exit command in the command pipe Read the + // data from that pipe: char c; ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); @@ -753,14 +746,10 @@ ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s, return eConnectionStatusSuccess; } -uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) { - uint16_t bound_port = 0; - if (timeout_sec == UINT32_MAX) - m_port_predicate.WaitForValueNotEqualTo(0, bound_port); - else - m_port_predicate.WaitForValueNotEqualTo(0, bound_port, - std::chrono::seconds(timeout_sec)); - return bound_port; +uint16_t +ConnectionFileDescriptor::GetListeningPort(const Timeout<std::micro> &timeout) { + auto Result = m_port_predicate.WaitForValueNotEqualTo(0, timeout); + return Result ? *Result : 0; } bool ConnectionFileDescriptor::GetChildProcessesInherit() const { diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp index 3ece0677f991d..60be642df6087 100644 --- a/source/Host/posix/FileSystem.cpp +++ b/source/Host/posix/FileSystem.cpp @@ -16,11 +16,6 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> -#ifdef __linux__ -#include <linux/magic.h> -#include <sys/mount.h> -#include <sys/statfs.h> -#endif #if defined(__NetBSD__) #include <sys/statvfs.h> #endif @@ -52,7 +47,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { error.SetErrorToErrno(); else { buf[count] = '\0'; // Success - dst.SetFile(buf, false); + dst.SetFile(buf, false, FileSpec::Style::native); } return error; } diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index da9e1fb366cc2..62c70fa3edc12 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -7,15 +7,9 @@ // //===----------------------------------------------------------------------===// -#if !defined(LLDB_DISABLE_PYTHON) -#include "Plugins/ScriptInterpreter/Python/lldb-python.h" -#endif - #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/Log.h" -#include "clang/Basic/Version.h" -#include "clang/Config/config.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Path.h" @@ -103,8 +97,7 @@ const char *HostInfoPosix::LookupGroupName(uint32_t gid, } } else { // The threadsafe version isn't currently working for me on darwin, but the - // non-threadsafe version - // is, so I am calling it below. + // non-threadsafe version is, so I am calling it below. group_info_ptr = ::getgrgid(gid); if (group_info_ptr) { group_name.assign(group_info_ptr->gr_name); @@ -132,8 +125,8 @@ bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec, llvm::StringRef dir) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + FileSpec lldb_file_spec = GetShlibDir(); + if (!lldb_file_spec) return false; std::string raw_path = lldb_file_spec.GetPath(); @@ -141,8 +134,8 @@ bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec, llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with - // */bin as the base directory for helper exe programs. This will fail if the - // /lib and /bin directories are rooted in entirely different trees. + // */bin as the base directory for helper exe programs. This will fail if + // the /lib and /bin directories are rooted in entirely different trees. if (log) log->Printf("HostInfoPosix::ComputePathRelativeToLibrary() attempting to " "derive the %s path from this path: %s", @@ -169,59 +162,12 @@ bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { return ComputePathRelativeToLibrary(file_spec, "/bin"); } -bool HostInfoPosix::ComputeClangDirectory(FileSpec &file_spec) { - return ComputePathRelativeToLibrary( - file_spec, (llvm::Twine("/lib") + CLANG_LIBDIR_SUFFIX + "/clang/" + - CLANG_VERSION_STRING) - .str()); -} - bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) { FileSpec temp_file("/opt/local/include/lldb", false); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; } -bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) { -#ifndef LLDB_DISABLE_PYTHON - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - - char raw_path[PATH_MAX]; - lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); - -#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) - // Build the path by backing out of the lib dir, then building - // with whatever the real python interpreter uses. (e.g. lib - // for most, lib64 on RHEL x86_64). - char python_path[PATH_MAX]; - ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, - LLDB_PYTHON_RELATIVE_LIBDIR); - - char final_path[PATH_MAX]; - realpath(python_path, final_path); - file_spec.GetDirectory().SetCString(final_path); - - return true; -#else - llvm::SmallString<256> python_version_dir; - llvm::raw_svector_ostream os(python_version_dir); - os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION - << "/site-packages"; - - // We may get our string truncated. Should we protect this with an assert? - ::strncat(raw_path, python_version_dir.c_str(), - sizeof(raw_path) - strlen(raw_path) - 1); - - file_spec.GetDirectory().SetCString(raw_path); - return true; -#endif -#else - return false; -#endif -} - bool HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var) { if (const char *pvar = ::getenv(var_name.c_str())) { diff --git a/source/Host/posix/HostThreadPosix.cpp b/source/Host/posix/HostThreadPosix.cpp index 71abb76dc600b..13de42f763ec7 100644 --- a/source/Host/posix/HostThreadPosix.cpp +++ b/source/Host/posix/HostThreadPosix.cpp @@ -41,14 +41,11 @@ Status HostThreadPosix::Join(lldb::thread_result_t *result) { Status HostThreadPosix::Cancel() { Status error; if (IsJoinable()) { -#ifndef __ANDROID__ #ifndef __FreeBSD__ llvm_unreachable("someone is calling HostThread::Cancel()"); -#endif +#else int err = ::pthread_cancel(m_thread); error.SetError(err, eErrorTypePOSIX); -#else - error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); #endif } return error; diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index da99fd702424e..b321cad642758 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -127,18 +127,14 @@ Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix, llvm::SmallVectorImpl<char> &name) { llvm::SmallString<PATH_MAX> named_pipe_path; llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); - FileSpec tmpdir_file_spec; - tmpdir_file_spec.Clear(); - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } else { + FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir(); + if (!tmpdir_file_spec) tmpdir_file_spec.AppendPathComponent("/tmp"); - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } + tmpdir_file_spec.AppendPathComponent(pipe_spec); // It's possible that another process creates the target path after we've - // verified it's available but before we create it, in which case we - // should try again. + // verified it's available but before we create it, in which case we should + // try again. Status error; do { llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(), diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index ac1d9011c2b78..46ce3e3d224f6 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -38,17 +38,12 @@ using namespace lldb; using namespace lldb_private; -static void FixupEnvironment(Args &env) { +static void FixupEnvironment(Environment &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")); + env.try_emplace("PATH", "/system/bin"); #endif } @@ -95,10 +90,6 @@ static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, const ProcessLaunchInfo &info) { - // 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"); @@ -132,23 +123,26 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, ExitWithError(error_fd, "chdir"); DisableASLRIfRequested(error_fd, info); - Args env = info.GetEnvironmentEntries(); + Environment env = info.GetEnvironment(); FixupEnvironment(env); - const char **envp = env.GetConstArgumentVector(); + Environment::Envp envp = env.getEnvp(); - // Clear the signal mask to prevent the child from being affected by - // any masking done by the parent. + // 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)) { + // Do not inherit setgid powers. + if (setgid(getgid()) != 0) + ExitWithError(error_fd, "setgid"); + // 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. + // 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); @@ -159,26 +153,20 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, } // Execute. We should never return... - execve(argv[0], const_cast<char *const *>(argv), - const_cast<char *const *>(envp)); + execve(argv[0], const_cast<char *const *>(argv), 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. + // 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)); + execve(argv[0], const_cast<char *const *>(argv), envp); } #endif diff --git a/source/Host/windows/ConnectionGenericFileWindows.cpp b/source/Host/windows/ConnectionGenericFileWindows.cpp index 41bdb5f41fb6a..e59e190dcb2d5 100644 --- a/source/Host/windows/ConnectionGenericFileWindows.cpp +++ b/source/Host/windows/ConnectionGenericFileWindows.cpp @@ -21,12 +21,10 @@ using namespace lldb_private; namespace { // This is a simple helper class to package up the information needed to return -// from a Read/Write -// operation function. Since there is a lot of code to be run before exit -// regardless of whether the -// operation succeeded or failed, combined with many possible return paths, this -// is the cleanest -// way to represent it. +// from a Read/Write operation function. Since there is a lot of code to be +// run before exit regardless of whether the operation succeeded or failed, +// combined with many possible return paths, this is the cleanest way to +// represent it. class ReturnInfo { public: void Set(size_t bytes, ConnectionStatus status, DWORD error_code) { @@ -78,11 +76,9 @@ void ConnectionGenericFile::InitializeEventHandles() { m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL); // Note, we should use a manual reset event for the hEvent argument of the - // OVERLAPPED. This - // is because both WaitForMultipleObjects and GetOverlappedResult (if you set - // the bWait - // argument to TRUE) will wait for the event to be signalled. If we use an - // auto-reset event, + // OVERLAPPED. This is because both WaitForMultipleObjects and + // GetOverlappedResult (if you set the bWait argument to TRUE) will wait for + // the event to be signalled. If we use an auto-reset event, // WaitForMultipleObjects will reset the event, return successfully, and then // GetOverlappedResult will block since the event is no longer signalled. m_event_handles[kBytesAvailableEvent] = @@ -147,8 +143,7 @@ lldb::ConnectionStatus ConnectionGenericFile::Disconnect(Status *error_ptr) { return eConnectionStatusSuccess; // Reset the handle so that after we unblock any pending reads, subsequent - // calls to Read() will - // see a disconnected state. + // calls to Read() will see a disconnected state. HANDLE old_file = m_file; m_file = INVALID_HANDLE_VALUE; @@ -157,8 +152,7 @@ lldb::ConnectionStatus ConnectionGenericFile::Disconnect(Status *error_ptr) { ::CancelIoEx(old_file, &m_overlapped); // Close the file handle if we owned it, but don't close the event handles. - // We could always - // reconnect with the same Connection instance. + // We could always reconnect with the same Connection instance. if (m_owns_file) ::CloseHandle(old_file); @@ -190,8 +184,7 @@ size_t ConnectionGenericFile::Read(void *dst, size_t dst_len, if (result || ::GetLastError() == ERROR_IO_PENDING) { if (!result) { // The expected return path. The operation is pending. Wait for the - // operation to complete - // or be interrupted. + // operation to complete or be interrupted. DWORD milliseconds = timeout ? std::chrono::duration_cast<std::chrono::milliseconds>(*timeout) @@ -219,11 +212,9 @@ size_t ConnectionGenericFile::Read(void *dst, size_t dst_len, // The data is ready. Figure out how much was read and return; if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) { DWORD result_error = ::GetLastError(); - // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a - // blocking read. - // This triggers a call to CancelIoEx, which causes the operation to - // complete and the - // result to be ERROR_OPERATION_ABORTED. + // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during + // a blocking read. This triggers a call to CancelIoEx, which causes the + // operation to complete and the result to be ERROR_OPERATION_ABORTED. if (result_error == ERROR_HANDLE_EOF || result_error == ERROR_OPERATION_ABORTED || result_error == ERROR_BROKEN_PIPE) @@ -250,9 +241,9 @@ finish: if (error_ptr) *error_ptr = return_info.GetError(); - // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here - // so that any - // subsequent operations don't immediately see bytes available. + // kBytesAvailableEvent is a manual reset event. Make sure it gets reset + // here so that any subsequent operations don't immediately see bytes + // available. ResetEvent(m_event_handles[kBytesAvailableEvent]); IncrementFilePointer(return_info.GetBytes()); @@ -284,7 +275,8 @@ size_t ConnectionGenericFile::Write(const void *src, size_t src_len, m_overlapped.hEvent = NULL; - // Writes are not interruptible like reads are, so just block until it's done. + // Writes are not interruptible like reads are, so just block until it's + // done. result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped); if (!result && ::GetLastError() != ERROR_IO_PENDING) { return_info.Set(0, eConnectionStatusError, ::GetLastError()); diff --git a/source/Host/windows/EditLineWin.cpp b/source/Host/windows/EditLineWin.cpp index 133cd62254679..3bccc4e1a2c9c 100644 --- a/source/Host/windows/EditLineWin.cpp +++ b/source/Host/windows/EditLineWin.cpp @@ -316,8 +316,8 @@ int el_get(EditLine *el, int code, ...) { } int el_source(EditLine *el, const char *file) { - // init edit line by reading the contents of 'file' - // nothing to do here on windows... + // init edit line by reading the contents of 'file' nothing to do here on + // windows... return 0; } @@ -342,8 +342,8 @@ void history_end(History *) { } int history(History *, HistEvent *, int op, ...) { - // perform operation 'op' on the history list with - // optional arguments as needed by the operation. + // perform operation 'op' on the history list with optional arguments as + // needed by the operation. return 0; } diff --git a/source/Host/windows/FileSystem.cpp b/source/Host/windows/FileSystem.cpp index 02b7e550f86cd..9309b89f2baf8 100644 --- a/source/Host/windows/FileSystem.cpp +++ b/source/Host/windows/FileSystem.cpp @@ -75,7 +75,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { else if (!llvm::convertWideToUTF8(buf.data(), path)) error.SetErrorString(PATH_CONVERSION_ERROR); else - dst.SetFile(path, false); + dst.SetFile(path, false, FileSpec::Style::native); ::CloseHandle(h); return error; diff --git a/source/Host/windows/Host.cpp b/source/Host/windows/Host.cpp index 4458ce25e6079..cc6c454d36b11 100644 --- a/source/Host/windows/Host.cpp +++ b/source/Host/windows/Host.cpp @@ -35,8 +35,7 @@ using namespace lldb_private; namespace { bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) { // Open the PE File as a binary file, and parse just enough information to - // determine the - // machine type. + // determine the machine type. File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead, lldb::eFilePermissionsUserRead); imageBinary.SeekFromStart(0x3c); @@ -63,8 +62,8 @@ bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) { } bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) { - // Get the process image path. MAX_PATH isn't long enough, paths can actually - // be up to 32KB. + // Get the process image path. MAX_PATH isn't long enough, paths can + // actually be up to 32KB. std::vector<wchar_t> buffer(PATH_MAX); DWORD dwSize = buffer.size(); if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize)) @@ -75,10 +74,9 @@ bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) { void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process) { // We may not have permissions to read the path from the process. So start - // off by - // setting the executable file to whatever Toolhelp32 gives us, and then try - // to - // enhance this with more detailed information, but fail gracefully. + // off by setting the executable file to whatever Toolhelp32 gives us, and + // then try to enhance this with more detailed information, but fail + // gracefully. std::string executable; llvm::Triple triple; triple.setVendor(llvm::Triple::PC); @@ -124,7 +122,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { std::string path; if (!llvm::convertWideToUTF8(buffer.data(), path)) return module_filespec; - module_filespec.SetFile(path, false); + module_filespec.SetFile(path, false, FileSpec::Style::native); return module_filespec; } @@ -184,9 +182,8 @@ HostThread Host::StartMonitoringChildProcess( Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { Status error; if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { - FileSpec expand_tool_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, - expand_tool_spec)) { + FileSpec expand_tool_spec = HostInfo::GetSupportExeDir(); + if (!expand_tool_spec) { error.SetErrorString("could not find support executable directory for " "the lldb-argdumper tool"); return error; @@ -209,7 +206,7 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { std::string output; std::string command = expand_command.GetString(); RunShellCommand(command.c_str(), launch_info.GetWorkingDirectory(), &status, - nullptr, &output, 10); + nullptr, &output, std::chrono::seconds(10)); if (status != 0) { error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", @@ -258,13 +255,12 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { return error; } -size_t Host::GetEnvironment(StringList &env) { +Environment Host::GetEnvironment() { + Environment env; // The environment block on Windows is a contiguous buffer of NULL terminated - // strings, - // where the end of the environment block is indicated by two consecutive - // NULLs. + // strings, where the end of the environment block is indicated by two + // consecutive NULLs. LPWCH environment_block = ::GetEnvironmentStringsW(); - env.Clear(); while (*environment_block != L'\0') { std::string current_var; auto current_var_size = wcslen(environment_block) + 1; @@ -273,9 +269,9 @@ size_t Host::GetEnvironment(StringList &env) { continue; } if (current_var[0] != '=') - env.AppendString(current_var); + env.insert(current_var); environment_block += current_var_size; } - return env.GetSize(); + return env; } diff --git a/source/Host/windows/HostInfoWindows.cpp b/source/Host/windows/HostInfoWindows.cpp index 53a24ad1893ec..bd3f74f2e2f38 100644 --- a/source/Host/windows/HostInfoWindows.cpp +++ b/source/Host/windows/HostInfoWindows.cpp @@ -42,39 +42,33 @@ size_t HostInfoWindows::GetPageSize() { return systemInfo.dwPageSize; } -bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoWindows::GetOSVersion() { OSVERSIONINFOEX info; ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); #pragma warning(push) #pragma warning(disable : 4996) - // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in - // favor of the - // new Windows Version Helper APIs. Since we don't specify a minimum SDK - // version, it's easier - // to simply disable the warning rather than try to support both APIs. - if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) { - return false; - } + // Starting with Microsoft SDK for Windows 8.1, this function is deprecated + // in favor of the new Windows Version Helper APIs. Since we don't specify a + // minimum SDK version, it's easier to simply disable the warning rather than + // try to support both APIs. + if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) + return llvm::VersionTuple(); #pragma warning(pop) - major = info.dwMajorVersion; - minor = info.dwMinorVersion; - update = info.wServicePackMajor; - - return true; + return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, + info.wServicePackMajor); } bool HostInfoWindows::GetOSBuildString(std::string &s) { s.clear(); - uint32_t major, minor, update; - if (!GetOSVersion(major, minor, update)) + llvm::VersionTuple version = GetOSVersion(); + if (version.empty()) return false; llvm::raw_string_ostream stream(s); - stream << "Windows NT " << major << "." << minor << "." << update; + stream << "Windows NT " << version.getAsString(); return true; } @@ -98,27 +92,20 @@ FileSpec HostInfoWindows::GetProgramFileSpec() { ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); std::string path; llvm::convertWideToUTF8(buffer.data(), path); - m_program_filespec.SetFile(path, false); + m_program_filespec.SetFile(path, false, FileSpec::Style::native); }); return m_program_filespec; } FileSpec HostInfoWindows::GetDefaultShell() { + // Try to retrieve ComSpec from the environment. On the rare occasion + // that it fails, try a well-known path for ComSpec instead. + std::string shell; - GetEnvironmentVar("ComSpec", shell); - return FileSpec(shell, false); -} + if (GetEnvironmentVar("ComSpec", shell)) + return FileSpec(shell, false); -bool HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) { - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString()); - llvm::sys::path::remove_filename(path); - llvm::sys::path::append(path, "lib", "site-packages"); - std::replace(path.begin(), path.end(), '\\', '/'); - file_spec.GetDirectory().SetString(path.c_str()); - return true; + return FileSpec("C:\\Windows\\system32\\cmd.exe", false); } bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name, diff --git a/source/Host/windows/HostProcessWindows.cpp b/source/Host/windows/HostProcessWindows.cpp index 49d42ce054223..ce75c14cdcf4e 100644 --- a/source/Host/windows/HostProcessWindows.cpp +++ b/source/Host/windows/HostProcessWindows.cpp @@ -57,7 +57,7 @@ Status HostProcessWindows::GetMainModule(FileSpec &file_spec) const { if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) { std::string path; if (llvm::convertWideToUTF8(wpath.data(), path)) - file_spec.SetFile(path, false); + file_spec.SetFile(path, false, FileSpec::Style::native); else error.SetErrorString("Error converting path to UTF-8"); } else @@ -88,8 +88,8 @@ HostThread HostProcessWindows::StartMonitoring( info->callback = callback; // Since the life of this HostProcessWindows instance and the life of the - // process may be different, duplicate the handle so that - // the monitor thread can have ownership over its own copy of the handle. + // process may be different, duplicate the handle so that the monitor thread + // can have ownership over its own copy of the handle. HostThread result; if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) diff --git a/source/Host/windows/PipeWindows.cpp b/source/Host/windows/PipeWindows.cpp index e8f4753d11e2c..1951c9ca193ad 100644 --- a/source/Host/windows/PipeWindows.cpp +++ b/source/Host/windows/PipeWindows.cpp @@ -40,11 +40,9 @@ PipeWindows::PipeWindows() { PipeWindows::~PipeWindows() { Close(); } Status PipeWindows::CreateNew(bool child_process_inherit) { - // Even for anonymous pipes, we open a named pipe. This is because you cannot - // get - // overlapped i/o on Windows without using a named pipe. So we synthesize a - // unique - // name. + // Even for anonymous pipes, we open a named pipe. This is because you + // cannot get overlapped i/o on Windows without using a named pipe. So we + // synthesize a unique name. uint32_t serial = g_pipe_serial.fetch_add(1); std::string pipe_name; llvm::raw_string_ostream pipe_name_stream(pipe_name); @@ -65,8 +63,8 @@ Status PipeWindows::CreateNew(llvm::StringRef name, std::string pipe_path = "\\\\.\\Pipe\\"; pipe_path.append(name); - // Always open for overlapped i/o. We implement blocking manually in Read and - // Write. + // Always open for overlapped i/o. We implement blocking manually in Read + // and Write. DWORD read_mode = FILE_FLAG_OVERLAPPED; m_read = ::CreateNamedPipeA( pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, @@ -250,12 +248,10 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size, DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); if (wait_result != WAIT_OBJECT_0) { // The operation probably failed. However, if it timed out, we need to - // cancel the I/O. - // Between the time we returned from WaitForSingleObject and the time we - // call CancelIoEx, - // the operation may complete. If that hapens, CancelIoEx will fail and - // return ERROR_NOT_FOUND. - // If that happens, the original operation should be considered to have been + // cancel the I/O. Between the time we returned from WaitForSingleObject + // and the time we call CancelIoEx, the operation may complete. If that + // hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that + // happens, the original operation should be considered to have been // successful. bool failed = true; DWORD failure_error = ::GetLastError(); @@ -268,9 +264,8 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size, return Status(failure_error, eErrorTypeWin32); } - // Now we call GetOverlappedResult setting bWait to false, since we've already - // waited - // as long as we're willing to. + // Now we call GetOverlappedResult setting bWait to false, since we've + // already waited as long as we're willing to. if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) return Status(::GetLastError(), eErrorTypeWin32); diff --git a/source/Host/windows/ProcessLauncherWindows.cpp b/source/Host/windows/ProcessLauncherWindows.cpp index 56089742f0932..553dd9d286da8 100644 --- a/source/Host/windows/ProcessLauncherWindows.cpp +++ b/source/Host/windows/ProcessLauncherWindows.cpp @@ -21,14 +21,15 @@ using namespace lldb; using namespace lldb_private; namespace { -void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) { - if (env.GetArgumentCount() == 0) +void CreateEnvironmentBuffer(const Environment &env, + std::vector<char> &buffer) { + if (env.size() == 0) return; // Environment buffer is a null terminated list of null terminated strings - for (auto &entry : env.entries()) { + for (const auto &KV : env) { std::wstring warg; - if (llvm::ConvertUTF8toWide(entry.ref, warg)) { + if (llvm::ConvertUTF8toWide(Environment::compose(KV), warg)) { buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1)); } @@ -75,9 +76,8 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, if (launch_info.GetFlags().Test(eLaunchFlagDebug)) flags |= DEBUG_ONLY_THIS_PROCESS; - auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); LPVOID env_block = nullptr; - ::CreateEnvironmentBuffer(env, environment); + ::CreateEnvironmentBuffer(launch_info.GetEnvironment(), environment); if (!environment.empty()) env_block = environment.data(); @@ -96,6 +96,12 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi); + + if (!result) { + // Call GetLastError before we make any other system calls. + error.SetError(::GetLastError(), eErrorTypeWin32); + } + if (result) { // Do not call CloseHandle on pi.hProcess, since we want to pass that back // through the HostProcess. @@ -110,7 +116,8 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, ::CloseHandle(stderr_handle); if (!result) - error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(); + return HostProcess(pi.hProcess); } |
