diff options
Diffstat (limited to 'lldb/source/Host')
94 files changed, 15128 insertions, 17783 deletions
diff --git a/lldb/source/Host/android/HostInfoAndroid.cpp b/lldb/source/Host/android/HostInfoAndroid.cpp index 3fa50ec..27ce17a 100644 --- a/lldb/source/Host/android/HostInfoAndroid.cpp +++ b/lldb/source/Host/android/HostInfoAndroid.cpp @@ -15,90 +15,79 @@ using namespace lldb_private; using namespace llvm; -void -HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); - - if (arch_32.IsValid()) - { - arch_32.GetTriple().setEnvironment(llvm::Triple::Android); - } - if (arch_64.IsValid()) - { - arch_64.GetTriple().setEnvironment(llvm::Triple::Android); - } +void HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); + + if (arch_32.IsValid()) { + arch_32.GetTriple().setEnvironment(llvm::Triple::Android); + } + if (arch_64.IsValid()) { + arch_64.GetTriple().setEnvironment(llvm::Triple::Android); + } } -FileSpec -HostInfoAndroid::GetDefaultShell() -{ - return FileSpec("/system/bin/sh", false); +FileSpec HostInfoAndroid::GetDefaultShell() { + return FileSpec("/system/bin/sh", false); } -FileSpec -HostInfoAndroid::ResolveLibraryPath(const std::string& module_path, const ArchSpec& arch) -{ - static const char* const ld_library_path_separator = ":"; - static const char* const default_lib32_path[] = { - "/vendor/lib", - "/system/lib", - nullptr - }; - static const char* const default_lib64_path[] = { - "/vendor/lib64", - "/system/lib64", - nullptr - }; - - if (module_path.empty() || module_path[0] == '/') - return FileSpec(module_path.c_str(), true); - - SmallVector<StringRef, 4> ld_paths; - - if (const char* ld_library_path = ::getenv("LD_LIBRARY_PATH")) - StringRef(ld_library_path).split(ld_paths, StringRef(ld_library_path_separator), -1, false); - - const char* const* default_lib_path = nullptr; - switch (arch.GetAddressByteSize()) - { - case 4: - default_lib_path = default_lib32_path; - break; - case 8: - default_lib_path = default_lib64_path; - break; - default: - assert(false && "Unknown address byte size"); - return FileSpec(); - } - - for(const char* const* it = default_lib_path; *it; ++it) - ld_paths.push_back(StringRef(*it)); - - for (const StringRef& path : ld_paths) - { - FileSpec file_candidate(path.str().c_str(), true); - file_candidate.AppendPathComponent(module_path.c_str()); - - if (file_candidate.Exists()) - return file_candidate; - } - +FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path, + const ArchSpec &arch) { + static const char *const ld_library_path_separator = ":"; + static const char *const default_lib32_path[] = {"/vendor/lib", "/system/lib", + nullptr}; + static const char *const default_lib64_path[] = {"/vendor/lib64", + "/system/lib64", nullptr}; + + if (module_path.empty() || module_path[0] == '/') + return FileSpec(module_path.c_str(), true); + + SmallVector<StringRef, 4> ld_paths; + + if (const char *ld_library_path = ::getenv("LD_LIBRARY_PATH")) + StringRef(ld_library_path) + .split(ld_paths, StringRef(ld_library_path_separator), -1, false); + + const char *const *default_lib_path = nullptr; + switch (arch.GetAddressByteSize()) { + case 4: + default_lib_path = default_lib32_path; + break; + case 8: + default_lib_path = default_lib64_path; + break; + default: + assert(false && "Unknown address byte size"); return FileSpec(); -} + } + + for (const char *const *it = default_lib_path; *it; ++it) + ld_paths.push_back(StringRef(*it)); -bool -HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) -{ - bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + for (const StringRef &path : ld_paths) { + FileSpec file_candidate(path.str().c_str(), true); + file_candidate.AppendPathComponent(module_path.c_str()); - // On Android, there is no path which is guaranteed to be writable. If the user has not - // provided a path via an environment variable, the generic algorithm will deduce /tmp, which - // is plain wrong. In that case we have an invalid directory, we substitute the path with - // /data/local/tmp, which is correct at least in some cases (i.e., when running as shell user). - if (!success || !file_spec.Exists()) - file_spec = FileSpec("/data/local/tmp", false); + if (file_candidate.Exists()) + return file_candidate; + } + + return FileSpec(); +} - return file_spec.Exists(); +bool HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + + // On Android, there is no path which is guaranteed to be writable. If the + // user has not + // provided a path via an environment variable, the generic algorithm will + // deduce /tmp, which + // is plain wrong. In that case we have an invalid directory, we substitute + // the path with + // /data/local/tmp, which is correct at least in some cases (i.e., when + // running as shell user). + if (!success || !file_spec.Exists()) + file_spec = FileSpec("/data/local/tmp", false); + + return file_spec.Exists(); } diff --git a/lldb/source/Host/android/LibcGlue.cpp b/lldb/source/Host/android/LibcGlue.cpp index 091c11d..13437f9 100644 --- a/lldb/source/Host/android/LibcGlue.cpp +++ b/lldb/source/Host/android/LibcGlue.cpp @@ -15,21 +15,15 @@ #if __ANDROID_API__ < 21 -#include <sys/types.h> -#include <sys/stat.h> #include <fcntl.h> #include <signal.h> +#include <sys/stat.h> +#include <sys/types.h> #include "lldb/Host/Time.h" -time_t timegm(struct tm* t) -{ - return (time_t) timegm64(t); -} +time_t timegm(struct tm *t) { return (time_t)timegm64(t); } -int posix_openpt(int flags) -{ - return open("/dev/ptmx", flags); -} +int posix_openpt(int flags) { return open("/dev/ptmx", flags); } #endif diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index d23a481..6e12bfb 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -11,11 +11,11 @@ #include <iostream> #include <limits.h> -#include "lldb/Host/Editline.h" -#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Core/Error.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/StringList.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/Editline.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -34,14 +34,17 @@ using namespace lldb_private::line_editor; // the function declaraction has been hoisted here. #if defined(__APPLE__) extern "C" { - int setupterm(char *term, int fildes, int *errret); +int setupterm(char *term, int fildes, int *errret); } #define USE_SETUPTERM_WORKAROUND #endif -// Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text -// with a single line editor. Preserving this illusion requires fairly careful management of cursor -// state. Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(), +// Editline uses careful cursor management to achieve the illusion of editing a +// multi-line block of text +// with a single line editor. Preserving this illusion requires fairly careful +// management of cursor +// state. Read and understand the relationship between DisplayInput(), +// MoveCursor(), SetCurrentLine(), // and SaveEditedLine() before making changes. #define ESCAPE "\x1b" @@ -63,7 +66,8 @@ extern "C" { #define EditLineConstString(str) str #define EditLineStringFormatSpec "%s" -// use #defines so wide version functions and structs will resolve to old versions +// use #defines so wide version functions and structs will resolve to old +// versions // for case of libedit not built with wide char support #define history_w history #define history_winit history_init @@ -76,1430 +80,1290 @@ extern "C" { #define el_wgetc el_getc #define el_wpush el_push #define el_wparse el_parse -#define el_wset el_set -#define el_wget el_get +#define el_wset el_set +#define el_wget el_get #define el_wline el_line #define el_winsertstr el_insertstr -#define el_wdeletestr el_deletestr +#define el_wdeletestr el_deletestr #endif // #if LLDB_EDITLINE_USE_WCHAR -bool -IsOnlySpaces (const EditLineStringType & content) -{ - for (wchar_t ch : content) - { - if (ch != EditLineCharType(' ')) - return false; - } - return true; +bool IsOnlySpaces(const EditLineStringType &content) { + for (wchar_t ch : content) { + if (ch != EditLineCharType(' ')) + return false; + } + return true; } -EditLineStringType -CombineLines (const std::vector<EditLineStringType> & lines) -{ - EditLineStringStreamType combined_stream; - for (EditLineStringType line : lines) - { - combined_stream << line.c_str() << "\n"; - } - return combined_stream.str(); +EditLineStringType CombineLines(const std::vector<EditLineStringType> &lines) { + EditLineStringStreamType combined_stream; + for (EditLineStringType line : lines) { + combined_stream << line.c_str() << "\n"; + } + return combined_stream.str(); } -std::vector<EditLineStringType> -SplitLines (const EditLineStringType & input) -{ - std::vector<EditLineStringType> result; - size_t start = 0; - while (start < input.length()) - { - size_t end = input.find ('\n', start); - if (end == std::string::npos) - { - result.insert (result.end(), input.substr (start)); - break; - } - result.insert (result.end(), input.substr (start, end - start)); - start = end + 1; +std::vector<EditLineStringType> SplitLines(const EditLineStringType &input) { + std::vector<EditLineStringType> result; + size_t start = 0; + while (start < input.length()) { + size_t end = input.find('\n', start); + if (end == std::string::npos) { + result.insert(result.end(), input.substr(start)); + break; } - return result; + result.insert(result.end(), input.substr(start, end - start)); + start = end + 1; + } + return result; } -EditLineStringType -FixIndentation (const EditLineStringType & line, int indent_correction) -{ - if (indent_correction == 0) - return line; - if (indent_correction < 0) - return line.substr (-indent_correction); - return EditLineStringType (indent_correction, EditLineCharType(' ')) + line; +EditLineStringType FixIndentation(const EditLineStringType &line, + int indent_correction) { + if (indent_correction == 0) + return line; + if (indent_correction < 0) + return line.substr(-indent_correction); + return EditLineStringType(indent_correction, EditLineCharType(' ')) + line; } -int -GetIndentation (const EditLineStringType & line) -{ - int space_count = 0; - for (EditLineCharType ch : line) - { - if (ch != EditLineCharType(' ')) - break; - ++space_count; - } - return space_count; +int GetIndentation(const EditLineStringType &line) { + int space_count = 0; + for (EditLineCharType ch : line) { + if (ch != EditLineCharType(' ')) + break; + ++space_count; + } + return space_count; } -bool -IsInputPending (FILE * file) -{ - // FIXME: This will be broken on Windows if we ever re-enable Editline. You can't use select - // on something that isn't a socket. This will have to be re-written to not use a FILE*, but - // instead use some kind of yet-to-be-created abstraction that select-like functionality on - // non-socket objects. - const int fd = fileno (file); - SelectHelper select_helper; - select_helper.SetTimeout(std::chrono::microseconds(0)); - select_helper.FDSetRead(fd); - return select_helper.Select().Success(); +bool IsInputPending(FILE *file) { + // FIXME: This will be broken on Windows if we ever re-enable Editline. You + // can't use select + // on something that isn't a socket. This will have to be re-written to not + // use a FILE*, but + // instead use some kind of yet-to-be-created abstraction that select-like + // functionality on + // non-socket objects. + const int fd = fileno(file); + SelectHelper select_helper; + select_helper.SetTimeout(std::chrono::microseconds(0)); + select_helper.FDSetRead(fd); + return select_helper.Select().Success(); } -namespace lldb_private -{ - namespace line_editor - { - typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP; - - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. - - class EditlineHistory - { - private: - // Use static GetHistory() function to get a EditlineHistorySP to one of these objects - EditlineHistory (const std::string &prefix, uint32_t size, bool unique_entries) : - m_history (NULL), - m_event (), - m_prefix (prefix), - m_path () - { - m_history = history_winit(); - history_w (m_history, &m_event, H_SETSIZE, size); - if (unique_entries) - history_w (m_history, &m_event, H_SETUNIQUE, 1); - } - - const char * - GetHistoryFilePath() - { - if (m_path.empty() && m_history && !m_prefix.empty()) - { - FileSpec parent_path{"~/.lldb", true}; - char history_path[PATH_MAX]; - if (FileSystem::MakeDirectory(parent_path, lldb::eFilePermissionsDirectoryDefault).Success()) - { - snprintf (history_path, sizeof (history_path), "~/.lldb/%s-history", m_prefix.c_str()); - } - else - { - snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str()); - } - m_path = FileSpec (history_path, true).GetPath(); - } - if (m_path.empty()) - return NULL; - return m_path.c_str(); - } - - public: - - ~EditlineHistory() - { - Save(); - - if (m_history) - { - history_wend (m_history); - m_history = NULL; - } - } - - static EditlineHistorySP - GetHistory (const std::string &prefix) - { - typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap; - static std::recursive_mutex g_mutex; - static WeakHistoryMap g_weak_map; - std::lock_guard<std::recursive_mutex> guard(g_mutex); - WeakHistoryMap::const_iterator pos = g_weak_map.find (prefix); - EditlineHistorySP history_sp; - if (pos != g_weak_map.end()) - { - history_sp = pos->second.lock(); - if (history_sp) - return history_sp; - g_weak_map.erase (pos); - } - history_sp.reset (new EditlineHistory (prefix, 800, true)); - g_weak_map[prefix] = history_sp; - return history_sp; - } - - bool IsValid() const - { - return m_history != NULL; - } - - HistoryW * - GetHistoryPtr () - { - return m_history; - } - - void - Enter (const EditLineCharType *line_cstr) - { - if (m_history) - history_w (m_history, &m_event, H_ENTER, line_cstr); - } - - bool - Load () - { - if (m_history) - { - const char *path = GetHistoryFilePath(); - if (path) - { - history_w (m_history, &m_event, H_LOAD, path); - return true; - } - } - return false; - } - - bool - Save () - { - if (m_history) - { - const char *path = GetHistoryFilePath(); - if (path) - { - history_w (m_history, &m_event, H_SAVE, path); - return true; - } - } - return false; - } - - protected: - HistoryW * m_history; // The history object - HistEventW m_event; // The history event needed to contain all history events - std::string m_prefix; // The prefix name (usually the editline program name) to use when loading/saving history - std::string m_path; // Path to the history file - }; +namespace lldb_private { +namespace line_editor { +typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP; + +// EditlineHistory objects are sometimes shared between multiple +// Editline instances with the same program name. + +class EditlineHistory { +private: + // Use static GetHistory() function to get a EditlineHistorySP to one of these + // objects + EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) + : m_history(NULL), m_event(), m_prefix(prefix), m_path() { + m_history = history_winit(); + history_w(m_history, &m_event, H_SETSIZE, size); + if (unique_entries) + history_w(m_history, &m_event, H_SETUNIQUE, 1); + } + + const char *GetHistoryFilePath() { + if (m_path.empty() && m_history && !m_prefix.empty()) { + FileSpec parent_path{"~/.lldb", true}; + char history_path[PATH_MAX]; + if (FileSystem::MakeDirectory(parent_path, + lldb::eFilePermissionsDirectoryDefault) + .Success()) { + snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history", + m_prefix.c_str()); + } else { + snprintf(history_path, sizeof(history_path), "~/%s-widehistory", + m_prefix.c_str()); + } + m_path = FileSpec(history_path, true).GetPath(); + } + if (m_path.empty()) + return NULL; + return m_path.c_str(); + } + +public: + ~EditlineHistory() { + Save(); + + if (m_history) { + history_wend(m_history); + m_history = NULL; + } + } + + static EditlineHistorySP GetHistory(const std::string &prefix) { + typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap; + static std::recursive_mutex g_mutex; + static WeakHistoryMap g_weak_map; + std::lock_guard<std::recursive_mutex> guard(g_mutex); + WeakHistoryMap::const_iterator pos = g_weak_map.find(prefix); + EditlineHistorySP history_sp; + if (pos != g_weak_map.end()) { + history_sp = pos->second.lock(); + if (history_sp) + return history_sp; + g_weak_map.erase(pos); + } + history_sp.reset(new EditlineHistory(prefix, 800, true)); + g_weak_map[prefix] = history_sp; + return history_sp; + } + + bool IsValid() const { return m_history != NULL; } + + HistoryW *GetHistoryPtr() { return m_history; } + + void Enter(const EditLineCharType *line_cstr) { + if (m_history) + history_w(m_history, &m_event, H_ENTER, line_cstr); + } + + bool Load() { + if (m_history) { + const char *path = GetHistoryFilePath(); + if (path) { + history_w(m_history, &m_event, H_LOAD, path); + return true; + } + } + return false; + } + + bool Save() { + if (m_history) { + const char *path = GetHistoryFilePath(); + if (path) { + history_w(m_history, &m_event, H_SAVE, path); + return true; + } } + return false; + } + +protected: + HistoryW *m_history; // The history object + HistEventW m_event; // The history event needed to contain all history events + std::string m_prefix; // The prefix name (usually the editline program name) + // to use when loading/saving history + std::string m_path; // Path to the history file +}; +} } //------------------------------------------------------------------ // Editline private methods //------------------------------------------------------------------ -void -Editline::SetBaseLineNumber (int line_number) -{ - std::stringstream line_number_stream; - line_number_stream << line_number; - m_base_line_number = line_number; - m_line_number_digits = std::max (3, (int)line_number_stream.str().length() + 1); +void Editline::SetBaseLineNumber(int line_number) { + std::stringstream line_number_stream; + line_number_stream << line_number; + m_base_line_number = line_number; + m_line_number_digits = + std::max(3, (int)line_number_stream.str().length() + 1); } -std::string -Editline::PromptForIndex (int line_index) -{ - bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; - std::string prompt = m_set_prompt; - if (use_line_numbers && prompt.length() == 0) - { - prompt = ": "; - } - std::string continuation_prompt = prompt; - if (m_set_continuation_prompt.length() > 0) - { - continuation_prompt = m_set_continuation_prompt; - - // Ensure that both prompts are the same length through space padding - while (continuation_prompt.length() < prompt.length()) - { - continuation_prompt += ' '; - } - while (prompt.length() < continuation_prompt.length()) - { - prompt += ' '; - } +std::string Editline::PromptForIndex(int line_index) { + bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; + std::string prompt = m_set_prompt; + if (use_line_numbers && prompt.length() == 0) { + prompt = ": "; + } + std::string continuation_prompt = prompt; + if (m_set_continuation_prompt.length() > 0) { + continuation_prompt = m_set_continuation_prompt; + + // Ensure that both prompts are the same length through space padding + while (continuation_prompt.length() < prompt.length()) { + continuation_prompt += ' '; } - - if (use_line_numbers) - { - StreamString prompt_stream; - prompt_stream.Printf("%*d%s", m_line_number_digits, m_base_line_number + line_index, - (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); - return std::move (prompt_stream.GetString()); + while (prompt.length() < continuation_prompt.length()) { + prompt += ' '; } - return (line_index == 0) ? prompt : continuation_prompt; + } + + if (use_line_numbers) { + StreamString prompt_stream; + prompt_stream.Printf( + "%*d%s", m_line_number_digits, m_base_line_number + line_index, + (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); + return std::move(prompt_stream.GetString()); + } + return (line_index == 0) ? prompt : continuation_prompt; } -void -Editline::SetCurrentLine (int line_index) -{ - m_current_line_index = line_index; - m_current_prompt = PromptForIndex (line_index); +void Editline::SetCurrentLine(int line_index) { + m_current_line_index = line_index; + m_current_prompt = PromptForIndex(line_index); } -int -Editline::GetPromptWidth() -{ - return (int)PromptForIndex (0).length(); -} +int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); } -bool -Editline::IsEmacs() -{ - const char * editor; - el_get (m_editline, EL_EDITOR, &editor); - return editor[0] == 'e'; +bool Editline::IsEmacs() { + const char *editor; + el_get(m_editline, EL_EDITOR, &editor); + return editor[0] == 'e'; } -bool -Editline::IsOnlySpaces() -{ - const LineInfoW * info = el_wline (m_editline); - for (const EditLineCharType * character = info->buffer; character < info->lastchar; character++) - { - if (*character != ' ') - return false; - } - return true; +bool Editline::IsOnlySpaces() { + const LineInfoW *info = el_wline(m_editline); + for (const EditLineCharType *character = info->buffer; + character < info->lastchar; character++) { + if (*character != ' ') + return false; + } + return true; } -int -Editline::GetLineIndexForLocation (CursorLocation location, int cursor_row) -{ - int line = 0; - if (location == CursorLocation::EditingPrompt || location == CursorLocation::BlockEnd || - location == CursorLocation::EditingCursor) - { - for (unsigned index = 0; index < m_current_line_index; index++) - { - line += CountRowsForLine (m_input_lines[index]); - } - if (location == CursorLocation::EditingCursor) - { - line += cursor_row; - } - else if (location == CursorLocation::BlockEnd) - { - for (unsigned index = m_current_line_index; index < m_input_lines.size(); index++) - { - line += CountRowsForLine (m_input_lines[index]); - } - --line; - } +int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) { + int line = 0; + if (location == CursorLocation::EditingPrompt || + location == CursorLocation::BlockEnd || + location == CursorLocation::EditingCursor) { + for (unsigned index = 0; index < m_current_line_index; index++) { + line += CountRowsForLine(m_input_lines[index]); } - return line; -} - -void -Editline::MoveCursor (CursorLocation from, CursorLocation to) -{ - const LineInfoW * info = el_wline (m_editline); - int editline_cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); - int editline_cursor_row = editline_cursor_position / m_terminal_width; - - // Determine relative starting and ending lines - int fromLine = GetLineIndexForLocation (from, editline_cursor_row); - int toLine = GetLineIndexForLocation (to, editline_cursor_row); - if (toLine != fromLine) - { - fprintf (m_output_file, (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, std::abs (toLine - fromLine)); + if (location == CursorLocation::EditingCursor) { + line += cursor_row; + } else if (location == CursorLocation::BlockEnd) { + for (unsigned index = m_current_line_index; index < m_input_lines.size(); + index++) { + line += CountRowsForLine(m_input_lines[index]); + } + --line; } - - // Determine target column - int toColumn = 1; - if (to == CursorLocation::EditingCursor) - { - toColumn = editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; - } - else if (to == CursorLocation::BlockEnd) - { - toColumn = ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 80) + 1; - } - fprintf (m_output_file, ANSI_SET_COLUMN_N, toColumn); + } + return line; } -void -Editline::DisplayInput (int firstIndex) -{ - fprintf (m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); - int line_count = (int)m_input_lines.size(); - const char *faint = m_color_prompts ? ANSI_FAINT : ""; - const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; - - for (int index = firstIndex; index < line_count; index++) - { - fprintf (m_output_file, "%s" "%s" "%s" EditLineStringFormatSpec " ", - faint, - PromptForIndex (index).c_str(), - unfaint, - m_input_lines[index].c_str()); - if (index < line_count - 1) - fprintf (m_output_file, "\n"); - } +void Editline::MoveCursor(CursorLocation from, CursorLocation to) { + const LineInfoW *info = el_wline(m_editline); + int editline_cursor_position = + (int)((info->cursor - info->buffer) + GetPromptWidth()); + int editline_cursor_row = editline_cursor_position / m_terminal_width; + + // Determine relative starting and ending lines + int fromLine = GetLineIndexForLocation(from, editline_cursor_row); + int toLine = GetLineIndexForLocation(to, editline_cursor_row); + if (toLine != fromLine) { + fprintf(m_output_file, + (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, + std::abs(toLine - fromLine)); + } + + // Determine target column + int toColumn = 1; + if (to == CursorLocation::EditingCursor) { + toColumn = + editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; + } else if (to == CursorLocation::BlockEnd) { + toColumn = + ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % + 80) + + 1; + } + fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn); } +void Editline::DisplayInput(int firstIndex) { + fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); + int line_count = (int)m_input_lines.size(); + const char *faint = m_color_prompts ? ANSI_FAINT : ""; + const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; + + for (int index = firstIndex; index < line_count; index++) { + fprintf(m_output_file, "%s" + "%s" + "%s" EditLineStringFormatSpec " ", + faint, PromptForIndex(index).c_str(), unfaint, + m_input_lines[index].c_str()); + if (index < line_count - 1) + fprintf(m_output_file, "\n"); + } +} -int -Editline::CountRowsForLine (const EditLineStringType & content) -{ - auto prompt = PromptForIndex (0); // Prompt width is constant during an edit session - int line_length = (int)(content.length() + prompt.length()); - return (line_length / m_terminal_width) + 1; +int Editline::CountRowsForLine(const EditLineStringType &content) { + auto prompt = + PromptForIndex(0); // Prompt width is constant during an edit session + int line_length = (int)(content.length() + prompt.length()); + return (line_length / m_terminal_width) + 1; } -void -Editline::SaveEditedLine() -{ - const LineInfoW * info = el_wline (m_editline); - m_input_lines[m_current_line_index] = EditLineStringType (info->buffer, info->lastchar - info->buffer); +void Editline::SaveEditedLine() { + const LineInfoW *info = el_wline(m_editline); + m_input_lines[m_current_line_index] = + EditLineStringType(info->buffer, info->lastchar - info->buffer); } -StringList -Editline::GetInputAsStringList(int line_count) -{ - StringList lines; - for (EditLineStringType line : m_input_lines) - { - if (line_count == 0) - break; +StringList Editline::GetInputAsStringList(int line_count) { + StringList lines; + for (EditLineStringType line : m_input_lines) { + if (line_count == 0) + break; #if LLDB_EDITLINE_USE_WCHAR - lines.AppendString (m_utf8conv.to_bytes (line)); + lines.AppendString(m_utf8conv.to_bytes(line)); #else - lines.AppendString(line); + lines.AppendString(line); #endif - --line_count; - } - return lines; + --line_count; + } + return lines; } -unsigned char -Editline::RecallHistory (bool earlier) -{ - if (!m_history_sp || !m_history_sp->IsValid()) +unsigned char Editline::RecallHistory(bool earlier) { + if (!m_history_sp || !m_history_sp->IsValid()) + return CC_ERROR; + + HistoryW *pHistory = m_history_sp->GetHistoryPtr(); + HistEventW history_event; + std::vector<EditLineStringType> new_input_lines; + + // Treat moving from the "live" entry differently + if (!m_in_history) { + if (earlier == false) + return CC_ERROR; // Can't go newer than the "live" entry + if (history_w(pHistory, &history_event, H_FIRST) == -1) + return CC_ERROR; + + // Save any edits to the "live" entry in case we return by moving forward in + // history + // (it would be more bash-like to save over any current entry, but libedit + // doesn't + // offer the ability to add entries anywhere except the end.) + SaveEditedLine(); + m_live_history_lines = m_input_lines; + m_in_history = true; + } else { + if (history_w(pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) { + // Can't move earlier than the earliest entry + if (earlier) return CC_ERROR; - - HistoryW * pHistory = m_history_sp->GetHistoryPtr(); - HistEventW history_event; - std::vector<EditLineStringType> new_input_lines; - - // Treat moving from the "live" entry differently - if (!m_in_history) - { - if (earlier == false) - return CC_ERROR; // Can't go newer than the "live" entry - if (history_w (pHistory, &history_event, H_FIRST) == -1) - return CC_ERROR; - - // Save any edits to the "live" entry in case we return by moving forward in history - // (it would be more bash-like to save over any current entry, but libedit doesn't - // offer the ability to add entries anywhere except the end.) - SaveEditedLine(); - m_live_history_lines = m_input_lines; - m_in_history = true; - } - else - { - if (history_w (pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) - { - // Can't move earlier than the earliest entry - if (earlier) - return CC_ERROR; - - // ... but moving to newer than the newest yields the "live" entry - new_input_lines = m_live_history_lines; - m_in_history = false; - } + + // ... but moving to newer than the newest yields the "live" entry + new_input_lines = m_live_history_lines; + m_in_history = false; } - - // If we're pulling the lines from history, split them apart - if (m_in_history) - new_input_lines = SplitLines (history_event.str); - - // Erase the current edit session and replace it with a new one - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); - m_input_lines = new_input_lines; - DisplayInput(); - - // Prepare to edit the last line when moving to previous entry, or the first line - // when moving to next entry - SetCurrentLine (m_current_line_index = earlier ? (int)m_input_lines.size() - 1 : 0); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; + } + + // If we're pulling the lines from history, split them apart + if (m_in_history) + new_input_lines = SplitLines(history_event.str); + + // Erase the current edit session and replace it with a new one + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + m_input_lines = new_input_lines; + DisplayInput(); + + // Prepare to edit the last line when moving to previous entry, or the first + // line + // when moving to next entry + SetCurrentLine(m_current_line_index = + earlier ? (int)m_input_lines.size() - 1 : 0); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -int -Editline::GetCharacter (EditLineCharType * c) -{ - const LineInfoW * info = el_wline (m_editline); - - // Paint a faint version of the desired prompt over the version libedit draws - // (will only be requested if colors are supported) - if (m_needs_prompt_repaint) - { - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - fprintf (m_output_file, "%s" "%s" "%s", ANSI_FAINT, Prompt(), ANSI_UNFAINT); - MoveCursor (CursorLocation::EditingPrompt, CursorLocation::EditingCursor); - m_needs_prompt_repaint = false; +int Editline::GetCharacter(EditLineCharType *c) { + const LineInfoW *info = el_wline(m_editline); + + // Paint a faint version of the desired prompt over the version libedit draws + // (will only be requested if colors are supported) + if (m_needs_prompt_repaint) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + fprintf(m_output_file, "%s" + "%s" + "%s", + ANSI_FAINT, Prompt(), ANSI_UNFAINT); + MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor); + m_needs_prompt_repaint = false; + } + + if (m_multiline_enabled) { + // Detect when the number of rows used for this input line changes due to an + // edit + int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); + int new_line_rows = (lineLength / m_terminal_width) + 1; + if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) { + // Respond by repainting the current state from this line on + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + SaveEditedLine(); + DisplayInput(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); } - - if (m_multiline_enabled) - { - // Detect when the number of rows used for this input line changes due to an edit - int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); - int new_line_rows = (lineLength / m_terminal_width) + 1; - if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) - { - // Respond by repainting the current state from this line on - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - SaveEditedLine(); - DisplayInput (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); - } - m_current_line_rows = new_line_rows; + m_current_line_rows = new_line_rows; + } + + // Read an actual character + while (true) { + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char ch = 0; + + // This mutex is locked by our caller (GetLine). Unlock it while we read a + // character + // (blocking operation), so we do not hold the mutex indefinitely. This + // gives a chance + // for someone to interrupt us. After Read returns, immediately lock the + // mutex again and + // check if we were interrupted. + m_output_mutex.unlock(); + int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); + m_output_mutex.lock(); + if (m_editor_status == EditorStatus::Interrupted) { + while (read_count > 0 && status == lldb::eConnectionStatusSuccess) + read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); + lldbassert(status == lldb::eConnectionStatusInterrupted); + return 0; } - - // Read an actual character - while (true) - { - lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; - char ch = 0; - - // This mutex is locked by our caller (GetLine). Unlock it while we read a character - // (blocking operation), so we do not hold the mutex indefinitely. This gives a chance - // for someone to interrupt us. After Read returns, immediately lock the mutex again and - // check if we were interrupted. - m_output_mutex.unlock(); - int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); - m_output_mutex.lock(); - if (m_editor_status == EditorStatus::Interrupted) - { - while (read_count > 0 && status == lldb::eConnectionStatusSuccess) - read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); - lldbassert(status == lldb::eConnectionStatusInterrupted); - return 0; - } - if (read_count) - { + if (read_count) { #if LLDB_EDITLINE_USE_WCHAR - // After the initial interruptible read, this is guaranteed not to block - ungetc (ch, m_input_file); - *c = fgetwc (m_input_file); - if (*c != WEOF) - return 1; + // After the initial interruptible read, this is guaranteed not to block + ungetc(ch, m_input_file); + *c = fgetwc(m_input_file); + if (*c != WEOF) + return 1; #else - *c = ch; - if(ch != (char)EOF) - return 1; + *c = ch; + if (ch != (char)EOF) + return 1; #endif - } - else - { - switch (status) - { - case lldb::eConnectionStatusSuccess: // Success - break; - - case lldb::eConnectionStatusInterrupted: - lldbassert(0 && "Interrupts should have been handled above."); - - case lldb::eConnectionStatusError: // Check GetError() for details - case lldb::eConnectionStatusTimedOut: // Request timed out - case lldb::eConnectionStatusEndOfFile: // End-of-file encountered - case lldb::eConnectionStatusNoConnection: // No connection - case lldb::eConnectionStatusLostConnection: // Lost connection while connected to a valid connection - m_editor_status = EditorStatus::EndOfInput; - return 0; - } - } + } else { + switch (status) { + case lldb::eConnectionStatusSuccess: // Success + break; + + case lldb::eConnectionStatusInterrupted: + lldbassert(0 && "Interrupts should have been handled above."); + + case lldb::eConnectionStatusError: // Check GetError() for details + case lldb::eConnectionStatusTimedOut: // Request timed out + case lldb::eConnectionStatusEndOfFile: // End-of-file encountered + case lldb::eConnectionStatusNoConnection: // No connection + case lldb::eConnectionStatusLostConnection: // Lost connection while + // connected to a valid + // connection + m_editor_status = EditorStatus::EndOfInput; + return 0; + } } + } } -const char * -Editline::Prompt() -{ - if (m_color_prompts) - m_needs_prompt_repaint = true; - return m_current_prompt.c_str(); +const char *Editline::Prompt() { + if (m_color_prompts) + m_needs_prompt_repaint = true; + return m_current_prompt.c_str(); } -unsigned char -Editline::BreakLineCommand (int ch) -{ - // Preserve any content beyond the cursor, truncate and save the current line - const LineInfoW * info = el_wline (m_editline); - auto current_line = EditLineStringType (info->buffer, info->cursor - info->buffer); - auto new_line_fragment = EditLineStringType (info->cursor, info->lastchar - info->cursor); - m_input_lines[m_current_line_index] = current_line; - - // Ignore whitespace-only extra fragments when breaking a line - if (::IsOnlySpaces (new_line_fragment)) - new_line_fragment = EditLineConstString(""); - - // Establish the new cursor position at the start of a line when inserting a line break - m_revert_cursor_index = 0; - - // Don't perform automatic formatting when pasting - if (!IsInputPending (m_input_file)) - { - // Apply smart indentation - if (m_fix_indentation_callback) - { - StringList lines = GetInputAsStringList (m_current_line_index + 1); +unsigned char Editline::BreakLineCommand(int ch) { + // Preserve any content beyond the cursor, truncate and save the current line + const LineInfoW *info = el_wline(m_editline); + auto current_line = + EditLineStringType(info->buffer, info->cursor - info->buffer); + auto new_line_fragment = + EditLineStringType(info->cursor, info->lastchar - info->cursor); + m_input_lines[m_current_line_index] = current_line; + + // Ignore whitespace-only extra fragments when breaking a line + if (::IsOnlySpaces(new_line_fragment)) + new_line_fragment = EditLineConstString(""); + + // Establish the new cursor position at the start of a line when inserting a + // line break + m_revert_cursor_index = 0; + + // Don't perform automatic formatting when pasting + if (!IsInputPending(m_input_file)) { + // Apply smart indentation + if (m_fix_indentation_callback) { + StringList lines = GetInputAsStringList(m_current_line_index + 1); #if LLDB_EDITLINE_USE_WCHAR - lines.AppendString (m_utf8conv.to_bytes (new_line_fragment)); + lines.AppendString(m_utf8conv.to_bytes(new_line_fragment)); #else - lines.AppendString (new_line_fragment); + lines.AppendString(new_line_fragment); #endif - - int indent_correction = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); - new_line_fragment = FixIndentation(new_line_fragment, indent_correction); - m_revert_cursor_index = GetIndentation(new_line_fragment); - } + + int indent_correction = m_fix_indentation_callback( + this, lines, 0, m_fix_indentation_callback_baton); + new_line_fragment = FixIndentation(new_line_fragment, indent_correction); + m_revert_cursor_index = GetIndentation(new_line_fragment); } - - // Insert the new line and repaint everything from the split line on down - m_input_lines.insert (m_input_lines.begin() + m_current_line_index + 1, new_line_fragment); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - DisplayInput (m_current_line_index); - - // Reposition the cursor to the right line and prepare to edit the new line - SetCurrentLine (m_current_line_index + 1); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; + } + + // Insert the new line and repaint everything from the split line on down + m_input_lines.insert(m_input_lines.begin() + m_current_line_index + 1, + new_line_fragment); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput(m_current_line_index); + + // Reposition the cursor to the right line and prepare to edit the new line + SetCurrentLine(m_current_line_index + 1); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -unsigned char -Editline::EndOrAddLineCommand(int ch) -{ - // Don't perform end of input detection when pasting, always treat this as a line break - if (IsInputPending(m_input_file)) - { +unsigned char Editline::EndOrAddLineCommand(int ch) { + // Don't perform end of input detection when pasting, always treat this as a + // line break + if (IsInputPending(m_input_file)) { + return BreakLineCommand(ch); + } + + // Save any edits to this line + SaveEditedLine(); + + // If this is the end of the last line, consider whether to add a line instead + const LineInfoW *info = el_wline(m_editline); + if (m_current_line_index == m_input_lines.size() - 1 && + info->cursor == info->lastchar) { + if (m_is_input_complete_callback) { + auto lines = GetInputAsStringList(); + if (!m_is_input_complete_callback(this, lines, + m_is_input_complete_callback_baton)) { return BreakLineCommand(ch); - } - - // Save any edits to this line - SaveEditedLine(); + } - // If this is the end of the last line, consider whether to add a line instead - const LineInfoW *info = el_wline(m_editline); - if (m_current_line_index == m_input_lines.size() - 1 && info->cursor == info->lastchar) - { - if (m_is_input_complete_callback) - { - auto lines = GetInputAsStringList(); - if (!m_is_input_complete_callback(this, lines, m_is_input_complete_callback_baton)) - { - return BreakLineCommand(ch); - } - - // The completion test is allowed to change the input lines when complete - m_input_lines.clear(); - for (unsigned index = 0; index < lines.GetSize(); index++) - { + // The completion test is allowed to change the input lines when complete + m_input_lines.clear(); + for (unsigned index = 0; index < lines.GetSize(); index++) { #if LLDB_EDITLINE_USE_WCHAR - m_input_lines.insert(m_input_lines.end(), m_utf8conv.from_bytes(lines[index])); + m_input_lines.insert(m_input_lines.end(), + m_utf8conv.from_bytes(lines[index])); #else - m_input_lines.insert(m_input_lines.end(), lines[index]); + m_input_lines.insert(m_input_lines.end(), lines[index]); #endif - } - } + } } - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); - fprintf(m_output_file, "\n"); - m_editor_status = EditorStatus::Complete; - return CC_NEWLINE; + } + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); + fprintf(m_output_file, "\n"); + m_editor_status = EditorStatus::Complete; + return CC_NEWLINE; } -unsigned char -Editline::DeleteNextCharCommand(int ch) -{ - LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline)); - - // Just delete the next character normally if possible - if (info->cursor < info->lastchar) - { - info->cursor++; - el_deletestr (m_editline, 1); - return CC_REFRESH; - } +unsigned char Editline::DeleteNextCharCommand(int ch) { + LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); - // Fail when at the end of the last line, except when ^D is pressed on - // the line is empty, in which case it is treated as EOF - if (m_current_line_index == m_input_lines.size() - 1) - { - if (ch == 4 && info->buffer == info->lastchar) - { - fprintf (m_output_file, "^D\n"); - m_editor_status = EditorStatus::EndOfInput; - return CC_EOF; - } - return CC_ERROR; - } - - // Prepare to combine this line with the one below - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - - // Insert the next line of text at the cursor and restore the cursor position - const EditLineCharType * cursor = info->cursor; - el_winsertstr (m_editline, m_input_lines[m_current_line_index + 1].c_str()); - info->cursor = cursor; - SaveEditedLine(); - - // Delete the extra line - m_input_lines.erase (m_input_lines.begin() + m_current_line_index + 1); - - // Clear and repaint from this line on down - DisplayInput (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); + // Just delete the next character normally if possible + if (info->cursor < info->lastchar) { + info->cursor++; + el_deletestr(m_editline, 1); return CC_REFRESH; + } + + // Fail when at the end of the last line, except when ^D is pressed on + // the line is empty, in which case it is treated as EOF + if (m_current_line_index == m_input_lines.size() - 1) { + if (ch == 4 && info->buffer == info->lastchar) { + fprintf(m_output_file, "^D\n"); + m_editor_status = EditorStatus::EndOfInput; + return CC_EOF; + } + return CC_ERROR; + } + + // Prepare to combine this line with the one below + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Insert the next line of text at the cursor and restore the cursor position + const EditLineCharType *cursor = info->cursor; + el_winsertstr(m_editline, m_input_lines[m_current_line_index + 1].c_str()); + info->cursor = cursor; + SaveEditedLine(); + + // Delete the extra line + m_input_lines.erase(m_input_lines.begin() + m_current_line_index + 1); + + // Clear and repaint from this line on down + DisplayInput(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + return CC_REFRESH; } -unsigned char -Editline::DeletePreviousCharCommand (int ch) -{ - LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline)); - - // Just delete the previous character normally when not at the start of a line - if (info->cursor > info->buffer) - { - el_deletestr (m_editline, 1); - return CC_REFRESH; - } - - // No prior line and no prior character? Let the user know - if (m_current_line_index == 0) - return CC_ERROR; - - // No prior character, but prior line? Combine with the line above - SaveEditedLine(); - SetCurrentLine (m_current_line_index - 1); - auto priorLine = m_input_lines[m_current_line_index]; - m_input_lines.erase (m_input_lines.begin() + m_current_line_index); - m_input_lines[m_current_line_index] = priorLine + m_input_lines[m_current_line_index]; - - // Repaint from the new line down - fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, CountRowsForLine (priorLine), 1); - DisplayInput (m_current_line_index); - - // Put the cursor back where libedit expects it to be before returning to editing - // by telling libedit about the newly inserted text - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - el_winsertstr (m_editline, priorLine.c_str()); - return CC_REDISPLAY; +unsigned char Editline::DeletePreviousCharCommand(int ch) { + LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); + + // Just delete the previous character normally when not at the start of a line + if (info->cursor > info->buffer) { + el_deletestr(m_editline, 1); + return CC_REFRESH; + } + + // No prior line and no prior character? Let the user know + if (m_current_line_index == 0) + return CC_ERROR; + + // No prior character, but prior line? Combine with the line above + SaveEditedLine(); + SetCurrentLine(m_current_line_index - 1); + auto priorLine = m_input_lines[m_current_line_index]; + m_input_lines.erase(m_input_lines.begin() + m_current_line_index); + m_input_lines[m_current_line_index] = + priorLine + m_input_lines[m_current_line_index]; + + // Repaint from the new line down + fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, + CountRowsForLine(priorLine), 1); + DisplayInput(m_current_line_index); + + // Put the cursor back where libedit expects it to be before returning to + // editing + // by telling libedit about the newly inserted text + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + el_winsertstr(m_editline, priorLine.c_str()); + return CC_REDISPLAY; } -unsigned char -Editline::PreviousLineCommand (int ch) -{ - SaveEditedLine(); +unsigned char Editline::PreviousLineCommand(int ch) { + SaveEditedLine(); - if (m_current_line_index == 0) { - return RecallHistory (true); - } - - // Start from a known location - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - - // Treat moving up from a blank last line as a deletion of that line - if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) - { - m_input_lines.erase (m_input_lines.begin() + m_current_line_index); - fprintf (m_output_file, ANSI_CLEAR_BELOW); - } - - SetCurrentLine (m_current_line_index - 1); - fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, - CountRowsForLine (m_input_lines[m_current_line_index]), 1); - return CC_NEWLINE; + if (m_current_line_index == 0) { + return RecallHistory(true); + } + + // Start from a known location + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Treat moving up from a blank last line as a deletion of that line + if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) { + m_input_lines.erase(m_input_lines.begin() + m_current_line_index); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + } + + SetCurrentLine(m_current_line_index - 1); + fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, + CountRowsForLine(m_input_lines[m_current_line_index]), 1); + return CC_NEWLINE; } -unsigned char -Editline::NextLineCommand (int ch) -{ - SaveEditedLine(); +unsigned char Editline::NextLineCommand(int ch) { + SaveEditedLine(); - // Handle attempts to move down from the last line - if (m_current_line_index == m_input_lines.size() - 1) - { - // Don't add an extra line if the existing last line is blank, move through history instead - if (IsOnlySpaces()) - { - return RecallHistory (false); - } - - // Determine indentation for the new line - int indentation = 0; - if (m_fix_indentation_callback) - { - StringList lines = GetInputAsStringList(); - lines.AppendString(""); - indentation = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); - } - m_input_lines.insert (m_input_lines.end(), EditLineStringType (indentation, EditLineCharType(' '))); + // Handle attempts to move down from the last line + if (m_current_line_index == m_input_lines.size() - 1) { + // Don't add an extra line if the existing last line is blank, move through + // history instead + if (IsOnlySpaces()) { + return RecallHistory(false); } - - // Move down past the current line using newlines to force scrolling if needed - SetCurrentLine (m_current_line_index + 1); - const LineInfoW * info = el_wline (m_editline); - int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); - int cursor_row = cursor_position / m_terminal_width; - for (int line_count = 0; line_count < m_current_line_rows - cursor_row; line_count++) - { - fprintf (m_output_file, "\n"); + + // Determine indentation for the new line + int indentation = 0; + if (m_fix_indentation_callback) { + StringList lines = GetInputAsStringList(); + lines.AppendString(""); + indentation = m_fix_indentation_callback( + this, lines, 0, m_fix_indentation_callback_baton); } - return CC_NEWLINE; + m_input_lines.insert( + m_input_lines.end(), + EditLineStringType(indentation, EditLineCharType(' '))); + } + + // Move down past the current line using newlines to force scrolling if needed + SetCurrentLine(m_current_line_index + 1); + const LineInfoW *info = el_wline(m_editline); + int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); + int cursor_row = cursor_position / m_terminal_width; + for (int line_count = 0; line_count < m_current_line_rows - cursor_row; + line_count++) { + fprintf(m_output_file, "\n"); + } + return CC_NEWLINE; } -unsigned char -Editline::PreviousHistoryCommand(int ch) -{ - SaveEditedLine(); +unsigned char Editline::PreviousHistoryCommand(int ch) { + SaveEditedLine(); - return RecallHistory(true); + return RecallHistory(true); } -unsigned char -Editline::NextHistoryCommand(int ch) -{ - SaveEditedLine(); +unsigned char Editline::NextHistoryCommand(int ch) { + SaveEditedLine(); - return RecallHistory(false); + return RecallHistory(false); } -unsigned char -Editline::FixIndentationCommand(int ch) -{ - if (!m_fix_indentation_callback) - return CC_NORM; +unsigned char Editline::FixIndentationCommand(int ch) { + if (!m_fix_indentation_callback) + return CC_NORM; - // Insert the character typed before proceeding - EditLineCharType inserted[] = { (EditLineCharType)ch, 0 }; - el_winsertstr (m_editline, inserted); - LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline)); - int cursor_position = info->cursor - info->buffer; + // Insert the character typed before proceeding + EditLineCharType inserted[] = {(EditLineCharType)ch, 0}; + el_winsertstr(m_editline, inserted); + LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); + int cursor_position = info->cursor - info->buffer; - // Save the edits and determine the correct indentation level - SaveEditedLine(); - StringList lines = GetInputAsStringList (m_current_line_index + 1); - int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton); - - // If it is already correct no special work is needed - if (indent_correction == 0) - return CC_REFRESH; - - // Change the indentation level of the line - std::string currentLine = lines.GetStringAtIndex (m_current_line_index); - if (indent_correction > 0) - { - currentLine = currentLine.insert (0, indent_correction, ' '); - } - else - { - currentLine = currentLine.erase (0, -indent_correction); - } + // Save the edits and determine the correct indentation level + SaveEditedLine(); + StringList lines = GetInputAsStringList(m_current_line_index + 1); + int indent_correction = m_fix_indentation_callback( + this, lines, cursor_position, m_fix_indentation_callback_baton); + + // If it is already correct no special work is needed + if (indent_correction == 0) + return CC_REFRESH; + + // Change the indentation level of the line + std::string currentLine = lines.GetStringAtIndex(m_current_line_index); + if (indent_correction > 0) { + currentLine = currentLine.insert(0, indent_correction, ' '); + } else { + currentLine = currentLine.erase(0, -indent_correction); + } #if LLDB_EDITLINE_USE_WCHAR - m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine); + m_input_lines[m_current_line_index] = m_utf8conv.from_bytes(currentLine); #else - m_input_lines[m_current_line_index] = currentLine; + m_input_lines[m_current_line_index] = currentLine; #endif - // Update the display to reflect the change - MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - DisplayInput (m_current_line_index); - - // Reposition the cursor back on the original line and prepare to restart editing - // with a new cursor position - SetCurrentLine (m_current_line_index); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - m_revert_cursor_index = cursor_position + indent_correction; - return CC_NEWLINE; + // Update the display to reflect the change + MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput(m_current_line_index); + + // Reposition the cursor back on the original line and prepare to restart + // editing + // with a new cursor position + SetCurrentLine(m_current_line_index); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + m_revert_cursor_index = cursor_position + indent_correction; + return CC_NEWLINE; } -unsigned char -Editline::RevertLineCommand (int ch) -{ - el_winsertstr (m_editline, m_input_lines[m_current_line_index].c_str()); - if (m_revert_cursor_index >= 0) - { - LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline)); - info->cursor = info->buffer + m_revert_cursor_index; - if (info->cursor > info->lastchar) - { - info->cursor = info->lastchar; - } - m_revert_cursor_index = -1; +unsigned char Editline::RevertLineCommand(int ch) { + el_winsertstr(m_editline, m_input_lines[m_current_line_index].c_str()); + if (m_revert_cursor_index >= 0) { + LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); + info->cursor = info->buffer + m_revert_cursor_index; + if (info->cursor > info->lastchar) { + info->cursor = info->lastchar; } - return CC_REFRESH; + m_revert_cursor_index = -1; + } + return CC_REFRESH; } -unsigned char -Editline::BufferStartCommand (int ch) -{ - SaveEditedLine(); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); - SetCurrentLine (0); - m_revert_cursor_index = 0; - return CC_NEWLINE; +unsigned char Editline::BufferStartCommand(int ch) { + SaveEditedLine(); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + SetCurrentLine(0); + m_revert_cursor_index = 0; + return CC_NEWLINE; } -unsigned char -Editline::BufferEndCommand (int ch) -{ - SaveEditedLine(); - MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockEnd); - SetCurrentLine ((int)m_input_lines.size() - 1); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); - return CC_NEWLINE; +unsigned char Editline::BufferEndCommand(int ch) { + SaveEditedLine(); + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); + SetCurrentLine((int)m_input_lines.size() - 1); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } -unsigned char -Editline::TabCommand (int ch) -{ - if (m_completion_callback == nullptr) - return CC_ERROR; - - const LineInfo *line_info = el_line (m_editline); - StringList completions; - int page_size = 40; - - const int num_completions = m_completion_callback (line_info->buffer, - line_info->cursor, - line_info->lastchar, - 0, // Don't skip any matches (start at match zero) - -1, // Get all the matches - completions, - m_completion_callback_baton); - - if (num_completions == 0) - return CC_ERROR; - // if (num_completions == -1) - // { - // el_insertstr (m_editline, m_completion_key); - // return CC_REDISPLAY; - // } - // else - if (num_completions == -2) - { - // Replace the entire line with the first string... - el_deletestr (m_editline, line_info->cursor - line_info->buffer); - el_insertstr (m_editline, completions.GetStringAtIndex (0)); - return CC_REDISPLAY; - } - - // If we get a longer match display that first. - const char *completion_str = completions.GetStringAtIndex (0); - if (completion_str != nullptr && *completion_str != '\0') - { - el_insertstr (m_editline, completion_str); - return CC_REDISPLAY; - } - - if (num_completions > 1) - { - int num_elements = num_completions + 1; - fprintf (m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); - if (num_completions < page_size) - { - for (int i = 1; i < num_elements; i++) - { - completion_str = completions.GetStringAtIndex (i); - fprintf (m_output_file, "\n\t%s", completion_str); - } - fprintf (m_output_file, "\n"); +unsigned char Editline::TabCommand(int ch) { + if (m_completion_callback == nullptr) + return CC_ERROR; + + const LineInfo *line_info = el_line(m_editline); + StringList completions; + int page_size = 40; + + const int num_completions = m_completion_callback( + line_info->buffer, line_info->cursor, line_info->lastchar, + 0, // Don't skip any matches (start at match zero) + -1, // Get all the matches + completions, m_completion_callback_baton); + + if (num_completions == 0) + return CC_ERROR; + // if (num_completions == -1) + // { + // el_insertstr (m_editline, m_completion_key); + // return CC_REDISPLAY; + // } + // else + if (num_completions == -2) { + // Replace the entire line with the first string... + el_deletestr(m_editline, line_info->cursor - line_info->buffer); + el_insertstr(m_editline, completions.GetStringAtIndex(0)); + return CC_REDISPLAY; + } + + // If we get a longer match display that first. + const char *completion_str = completions.GetStringAtIndex(0); + if (completion_str != nullptr && *completion_str != '\0') { + el_insertstr(m_editline, completion_str); + return CC_REDISPLAY; + } + + if (num_completions > 1) { + int num_elements = num_completions + 1; + fprintf(m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); + if (num_completions < page_size) { + for (int i = 1; i < num_elements; i++) { + completion_str = completions.GetStringAtIndex(i); + fprintf(m_output_file, "\n\t%s", completion_str); + } + fprintf(m_output_file, "\n"); + } else { + int cur_pos = 1; + char reply; + int got_char; + while (cur_pos < num_elements) { + int endpoint = cur_pos + page_size; + if (endpoint > num_elements) + endpoint = num_elements; + for (; cur_pos < endpoint; cur_pos++) { + completion_str = completions.GetStringAtIndex(cur_pos); + fprintf(m_output_file, "\n\t%s", completion_str); } - else - { - int cur_pos = 1; - char reply; - int got_char; - while (cur_pos < num_elements) - { - int endpoint = cur_pos + page_size; - if (endpoint > num_elements) - endpoint = num_elements; - for (; cur_pos < endpoint; cur_pos++) - { - completion_str = completions.GetStringAtIndex (cur_pos); - fprintf (m_output_file, "\n\t%s", completion_str); - } - - if (cur_pos >= num_elements) - { - fprintf (m_output_file, "\n"); - break; - } - - fprintf (m_output_file, "\nMore (Y/n/a): "); - reply = 'n'; - got_char = el_getc(m_editline, &reply); - if (got_char == -1 || reply == 'n') - break; - if (reply == 'a') - page_size = num_elements - cur_pos; - } + + if (cur_pos >= num_elements) { + fprintf(m_output_file, "\n"); + break; } - DisplayInput(); - MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + + fprintf(m_output_file, "\nMore (Y/n/a): "); + reply = 'n'; + got_char = el_getc(m_editline, &reply); + if (got_char == -1 || reply == 'n') + break; + if (reply == 'a') + page_size = num_elements - cur_pos; + } } - return CC_REDISPLAY; + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + } + return CC_REDISPLAY; } -void -Editline::ConfigureEditor (bool multiline) -{ - if (m_editline && m_multiline_enabled == multiline) - return; - m_multiline_enabled = multiline; - - if (m_editline) - { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. - el_set (m_editline, EL_EDITMODE, 0); - el_end (m_editline); - } - - m_editline = el_init (m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); - TerminalSizeChanged(); - - if (m_history_sp && m_history_sp->IsValid()) - { - m_history_sp->Load(); - el_wset (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); - } - el_set (m_editline, EL_CLIENTDATA, this); - el_set (m_editline, EL_SIGNAL, 0); - el_set (m_editline, EL_EDITOR, "emacs"); - el_set (m_editline, EL_PROMPT, (EditlinePromptCallbackType)([] (EditLine *editline) { - return Editline::InstanceFor (editline)->Prompt(); - })); - - el_wset (m_editline, EL_GETCFN, - (EditlineGetCharCallbackType)([] (EditLine * editline, EditLineCharType * c) { - return Editline::InstanceFor (editline)->GetCharacter (c); - })); - - // Commands used for multiline support, registered whether or not they're used - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), EditLineConstString("Insert a line break"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BreakLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), - EditLineConstString("End editing or continue when incomplete"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), - EditLineConstString("Delete next character"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), - EditLineConstString("Delete previous character"), - (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), - EditLineConstString("Move to previous line"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->PreviousLineCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), EditLineConstString("Move to next line"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextLineCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), - EditLineConstString("Move to previous history"), - (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); - })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), EditLineConstString("Move to next history"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextHistoryCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), - EditLineConstString("Move to start of buffer"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferStartCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), EditLineConstString("Move to end of buffer"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferEndCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), - EditLineConstString("Fix line indentation"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { - return Editline::InstanceFor (editline)->FixIndentationCommand (ch); - })); - - // Register the complete callback under two names for compatibility with older clients using - // custom .editrc files (largely because libedit has a bad bug where if you have a bind command - // that tries to bind to a function name that doesn't exist, it can corrupt the heap and - // crash your process later.) - EditlineCommandCallbackType complete_callback = [] (EditLine * editline, int ch) { - return Editline::InstanceFor (editline)->TabCommand (ch); - }; - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"), EditLineConstString("Invoke completion"), - complete_callback); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"), EditLineConstString("Invoke completion"), - complete_callback); - - // General bindings we don't mind being overridden - if (!multiline) { - el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string - } - el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash in emacs mode - el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to auto complete - - // Allow user-specific customization prior to registering bindings we absolutely require - el_source (m_editline, NULL); - - // Register an internal binding that external developers shouldn't use - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), - EditLineConstString("Revert line to saved state"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->RevertLineCommand(ch); })); - - // Register keys that perform auto-indent correction - if (m_fix_indentation_callback && m_fix_indentation_callback_chars) - { - char bind_key[2] = { 0, 0 }; - const char * indent_chars = m_fix_indentation_callback_chars; - while (*indent_chars) - { - bind_key[0] = *indent_chars; - el_set (m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); - ++indent_chars; - } +void Editline::ConfigureEditor(bool multiline) { + if (m_editline && m_multiline_enabled == multiline) + return; + m_multiline_enabled = multiline; + + if (m_editline) { + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set(m_editline, EL_EDITMODE, 0); + el_end(m_editline); + } + + m_editline = + el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); + TerminalSizeChanged(); + + if (m_history_sp && m_history_sp->IsValid()) { + m_history_sp->Load(); + el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); + } + el_set(m_editline, EL_CLIENTDATA, this); + el_set(m_editline, EL_SIGNAL, 0); + el_set(m_editline, EL_EDITOR, "emacs"); + el_set(m_editline, EL_PROMPT, + (EditlinePromptCallbackType)([](EditLine *editline) { + return Editline::InstanceFor(editline)->Prompt(); + })); + + el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([]( + EditLine *editline, EditLineCharType *c) { + return Editline::InstanceFor(editline)->GetCharacter(c); + })); + + // Commands used for multiline support, registered whether or not they're used + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), + EditLineConstString("Insert a line break"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BreakLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), + EditLineConstString("End editing or continue when incomplete"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), + EditLineConstString("Delete next character"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); + })); + el_wset( + m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), + EditLineConstString("Delete previous character"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), + EditLineConstString("Move to previous line"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->PreviousLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), + EditLineConstString("Move to next line"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->NextLineCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), + EditLineConstString("Move to previous history"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), + EditLineConstString("Move to next history"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->NextHistoryCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), + EditLineConstString("Move to start of buffer"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferStartCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), + EditLineConstString("Move to end of buffer"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferEndCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), + EditLineConstString("Fix line indentation"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->FixIndentationCommand(ch); + })); + + // Register the complete callback under two names for compatibility with older + // clients using + // custom .editrc files (largely because libedit has a bad bug where if you + // have a bind command + // that tries to bind to a function name that doesn't exist, it can corrupt + // the heap and + // crash your process later.) + EditlineCommandCallbackType complete_callback = [](EditLine *editline, + int ch) { + return Editline::InstanceFor(editline)->TabCommand(ch); + }; + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"), + EditLineConstString("Invoke completion"), complete_callback); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"), + EditLineConstString("Invoke completion"), complete_callback); + + // General bindings we don't mind being overridden + if (!multiline) { + el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev", + NULL); // Cycle through backwards search, entering string + } + el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word", + NULL); // Delete previous word, behave like bash in emacs mode + el_set(m_editline, EL_BIND, "\t", "lldb-complete", + NULL); // Bind TAB to auto complete + + // Allow user-specific customization prior to registering bindings we + // absolutely require + el_source(m_editline, NULL); + + // Register an internal binding that external developers shouldn't use + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), + EditLineConstString("Revert line to saved state"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->RevertLineCommand(ch); + })); + + // Register keys that perform auto-indent correction + if (m_fix_indentation_callback && m_fix_indentation_callback_chars) { + char bind_key[2] = {0, 0}; + const char *indent_chars = m_fix_indentation_callback_chars; + while (*indent_chars) { + bind_key[0] = *indent_chars; + el_set(m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); + ++indent_chars; } - - // Multi-line editor bindings - if (multiline) - { - el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); - el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); - el_set (m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "^n", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); - el_set (m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); - - // Editor-specific bindings - if (IsEmacs()) - { - el_set (m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); - el_set (m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); - el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", NULL); - el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); - } - else - { - el_set (m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); - - el_set (m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); - el_set (m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", NULL); - el_set (m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", NULL); - - // Escape is absorbed exiting edit mode, so re-register important sequences - // without the prefix - el_set (m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); - el_set (m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); - el_set (m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); - } + } + + // Multi-line editor bindings + if (multiline) { + el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, "^n", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); + el_set(m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); + + // Editor-specific bindings + if (IsEmacs()) { + el_set(m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); + el_set(m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", + NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); + } else { + el_set(m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); + + el_set(m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", + NULL); + el_set(m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); + el_set(m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", + NULL); + el_set(m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", + NULL); + + // Escape is absorbed exiting edit mode, so re-register important + // sequences + // without the prefix + el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); + el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); } + } } //------------------------------------------------------------------ // Editline public methods //------------------------------------------------------------------ -Editline * -Editline::InstanceFor (EditLine * editline) -{ - Editline * editor; - el_get (editline, EL_CLIENTDATA, &editor); - return editor; +Editline *Editline::InstanceFor(EditLine *editline) { + Editline *editor; + el_get(editline, EL_CLIENTDATA, &editor); + return editor; } -Editline::Editline (const char * editline_name, FILE * input_file, FILE * output_file, FILE * error_file, bool color_prompts) : - m_editor_status (EditorStatus::Complete), - m_color_prompts(color_prompts), - m_input_file (input_file), - m_output_file (output_file), - m_error_file (error_file), - m_input_connection (fileno(input_file), false) -{ - // Get a shared history instance - m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; - m_history_sp = EditlineHistory::GetHistory (m_editor_name); +Editline::Editline(const char *editline_name, FILE *input_file, + FILE *output_file, FILE *error_file, bool color_prompts) + : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), + m_input_file(input_file), m_output_file(output_file), + m_error_file(error_file), m_input_connection(fileno(input_file), false) { + // Get a shared history instance + m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; + m_history_sp = EditlineHistory::GetHistory(m_editor_name); #ifdef USE_SETUPTERM_WORKAROUND - if (m_output_file) - { - const int term_fd = fileno(m_output_file); - if (term_fd != -1) - { - static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; - static std::set<int> *g_init_terminal_fds_ptr = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [&]() { - g_init_terminal_fds_mutex_ptr = new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues - g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid C++ destructor chain issues - }); - - // We must make sure to initialize the terminal a given file descriptor - // only once. If we do this multiple times, we start leaking memory. - std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr); - if (g_init_terminal_fds_ptr->find(term_fd) == g_init_terminal_fds_ptr->end()) - { - g_init_terminal_fds_ptr->insert(term_fd); - setupterm((char *)0, term_fd, (int *)0); - } - } + if (m_output_file) { + const int term_fd = fileno(m_output_file); + if (term_fd != -1) { + static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; + static std::set<int> *g_init_terminal_fds_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, [&]() { + g_init_terminal_fds_mutex_ptr = + new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues + g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid + // C++ destructor chain + // issues + }); + + // We must make sure to initialize the terminal a given file descriptor + // only once. If we do this multiple times, we start leaking memory. + std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr); + if (g_init_terminal_fds_ptr->find(term_fd) == + g_init_terminal_fds_ptr->end()) { + g_init_terminal_fds_ptr->insert(term_fd); + setupterm((char *)0, term_fd, (int *)0); + } } + } #endif } -Editline::~Editline() -{ - if (m_editline) - { - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. - el_set (m_editline, EL_EDITMODE, 0); - el_end (m_editline); - m_editline = nullptr; - } - - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. So just release - // our shared pointer and if we are the last owner, it will save the - // history to the history save file automatically. - m_history_sp.reset(); +Editline::~Editline() { + if (m_editline) { + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set(m_editline, EL_EDITMODE, 0); + el_end(m_editline); + m_editline = nullptr; + } + + // EditlineHistory objects are sometimes shared between multiple + // Editline instances with the same program name. So just release + // our shared pointer and if we are the last owner, it will save the + // history to the history save file automatically. + m_history_sp.reset(); } -void -Editline::SetPrompt (const char * prompt) -{ - m_set_prompt = prompt == nullptr ? "" : prompt; +void Editline::SetPrompt(const char *prompt) { + m_set_prompt = prompt == nullptr ? "" : prompt; } -void -Editline::SetContinuationPrompt (const char * continuation_prompt) -{ - m_set_continuation_prompt = continuation_prompt == nullptr ? "" : continuation_prompt; +void Editline::SetContinuationPrompt(const char *continuation_prompt) { + m_set_continuation_prompt = + continuation_prompt == nullptr ? "" : continuation_prompt; } -void -Editline::TerminalSizeChanged() -{ - if (m_editline != nullptr) - { - el_resize (m_editline); - int columns; - // Despite the man page claiming non-zero indicates success, it's actually zero - if (el_get (m_editline, EL_GETTC, "co", &columns) == 0) - { - m_terminal_width = columns; - if (m_current_line_rows != -1) - { - const LineInfoW * info = el_wline (m_editline); - int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); - m_current_line_rows = (lineLength / columns) + 1; - } - } - else - { - m_terminal_width = INT_MAX; - m_current_line_rows = 1; - } +void Editline::TerminalSizeChanged() { + if (m_editline != nullptr) { + el_resize(m_editline); + int columns; + // Despite the man page claiming non-zero indicates success, it's actually + // zero + if (el_get(m_editline, EL_GETTC, "co", &columns) == 0) { + m_terminal_width = columns; + if (m_current_line_rows != -1) { + const LineInfoW *info = el_wline(m_editline); + int lineLength = + (int)((info->lastchar - info->buffer) + GetPromptWidth()); + m_current_line_rows = (lineLength / columns) + 1; + } + } else { + m_terminal_width = INT_MAX; + m_current_line_rows = 1; } + } } -const char * -Editline::GetPrompt() -{ - return m_set_prompt.c_str(); -} +const char *Editline::GetPrompt() { return m_set_prompt.c_str(); } -uint32_t -Editline::GetCurrentLine() -{ - return m_current_line_index; -} +uint32_t Editline::GetCurrentLine() { return m_current_line_index; } -bool -Editline::Interrupt() -{ - bool result = true; - std::lock_guard<std::mutex> guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) { - fprintf(m_output_file, "^C\n"); - result = m_input_connection.InterruptRead(); - } - m_editor_status = EditorStatus::Interrupted; - return result; +bool Editline::Interrupt() { + bool result = true; + std::lock_guard<std::mutex> guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + fprintf(m_output_file, "^C\n"); + result = m_input_connection.InterruptRead(); + } + m_editor_status = EditorStatus::Interrupted; + return result; } -bool -Editline::Cancel() -{ - bool result = true; - std::lock_guard<std::mutex> guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) { - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); - fprintf(m_output_file, ANSI_CLEAR_BELOW); - result = m_input_connection.InterruptRead(); - } - m_editor_status = EditorStatus::Interrupted; - return result; +bool Editline::Cancel() { + bool result = true; + std::lock_guard<std::mutex> guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + result = m_input_connection.InterruptRead(); + } + m_editor_status = EditorStatus::Interrupted; + return result; } -void -Editline::SetAutoCompleteCallback (CompleteCallbackType callback, void * baton) -{ - m_completion_callback = callback; - m_completion_callback_baton = baton; +void Editline::SetAutoCompleteCallback(CompleteCallbackType callback, + void *baton) { + m_completion_callback = callback; + m_completion_callback_baton = baton; } -void -Editline::SetIsInputCompleteCallback (IsInputCompleteCallbackType callback, void * baton) -{ - m_is_input_complete_callback = callback; - m_is_input_complete_callback_baton = baton; +void Editline::SetIsInputCompleteCallback(IsInputCompleteCallbackType callback, + void *baton) { + m_is_input_complete_callback = callback; + m_is_input_complete_callback_baton = baton; } -bool -Editline::SetFixIndentationCallback (FixIndentationCallbackType callback, - void * baton, - const char * indent_chars) -{ - m_fix_indentation_callback = callback; - m_fix_indentation_callback_baton = baton; - m_fix_indentation_callback_chars = indent_chars; - return false; +bool Editline::SetFixIndentationCallback(FixIndentationCallbackType callback, + void *baton, + const char *indent_chars) { + m_fix_indentation_callback = callback; + m_fix_indentation_callback_baton = baton; + m_fix_indentation_callback_chars = indent_chars; + return false; } -bool -Editline::GetLine (std::string &line, bool &interrupted) -{ - ConfigureEditor (false); - m_input_lines = std::vector<EditLineStringType>(); - m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); +bool Editline::GetLine(std::string &line, bool &interrupted) { + ConfigureEditor(false); + m_input_lines = std::vector<EditLineStringType>(); + m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); - std::lock_guard<std::mutex> guard(m_output_mutex); + std::lock_guard<std::mutex> guard(m_output_mutex); - lldbassert(m_editor_status != EditorStatus::Editing); - if (m_editor_status == EditorStatus::Interrupted) - { - m_editor_status = EditorStatus::Complete; - interrupted = true; - return true; - } - - SetCurrentLine (0); - m_in_history = false; - m_editor_status = EditorStatus::Editing; - m_revert_cursor_index = -1; - - int count; - auto input = el_wgets (m_editline, &count); - - interrupted = m_editor_status == EditorStatus::Interrupted; - if (!interrupted) - { - if (input == nullptr) - { - fprintf (m_output_file, "\n"); - m_editor_status = EditorStatus::EndOfInput; - } - else - { - m_history_sp->Enter (input); + lldbassert(m_editor_status != EditorStatus::Editing); + if (m_editor_status == EditorStatus::Interrupted) { + m_editor_status = EditorStatus::Complete; + interrupted = true; + return true; + } + + SetCurrentLine(0); + m_in_history = false; + m_editor_status = EditorStatus::Editing; + m_revert_cursor_index = -1; + + int count; + auto input = el_wgets(m_editline, &count); + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) { + if (input == nullptr) { + fprintf(m_output_file, "\n"); + m_editor_status = EditorStatus::EndOfInput; + } else { + m_history_sp->Enter(input); #if LLDB_EDITLINE_USE_WCHAR - line = m_utf8conv.to_bytes (SplitLines (input)[0]); + line = m_utf8conv.to_bytes(SplitLines(input)[0]); #else - line = SplitLines (input)[0]; + line = SplitLines(input)[0]; #endif - m_editor_status = EditorStatus::Complete; - } + m_editor_status = EditorStatus::Complete; } - return m_editor_status != EditorStatus::EndOfInput; + } + return m_editor_status != EditorStatus::EndOfInput; } -bool -Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted) -{ - ConfigureEditor (true); - - // Print the initial input lines, then move the cursor back up to the start of input - SetBaseLineNumber (first_line_number); - m_input_lines = std::vector<EditLineStringType>(); - m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); - - std::lock_guard<std::mutex> guard(m_output_mutex); - // Begin the line editing loop - DisplayInput(); - SetCurrentLine (0); - MoveCursor (CursorLocation::BlockEnd, CursorLocation::BlockStart); - m_editor_status = EditorStatus::Editing; - m_in_history = false; - - m_revert_cursor_index = -1; - while (m_editor_status == EditorStatus::Editing) - { - int count; - m_current_line_rows = -1; - el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content - el_wgets (m_editline, &count); - } - - interrupted = m_editor_status == EditorStatus::Interrupted; - if (!interrupted) - { - // Save the completed entry in history before returning - m_history_sp->Enter (CombineLines (m_input_lines).c_str()); - - lines = GetInputAsStringList(); - } - return m_editor_status != EditorStatus::EndOfInput; +bool Editline::GetLines(int first_line_number, StringList &lines, + bool &interrupted) { + ConfigureEditor(true); + + // Print the initial input lines, then move the cursor back up to the start of + // input + SetBaseLineNumber(first_line_number); + m_input_lines = std::vector<EditLineStringType>(); + m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + + std::lock_guard<std::mutex> guard(m_output_mutex); + // Begin the line editing loop + DisplayInput(); + SetCurrentLine(0); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart); + m_editor_status = EditorStatus::Editing; + m_in_history = false; + + m_revert_cursor_index = -1; + while (m_editor_status == EditorStatus::Editing) { + int count; + m_current_line_rows = -1; + el_wpush(m_editline, EditLineConstString( + "\x1b[^")); // Revert to the existing line content + el_wgets(m_editline, &count); + } + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) { + // Save the completed entry in history before returning + m_history_sp->Enter(CombineLines(m_input_lines).c_str()); + + lines = GetInputAsStringList(); + } + return m_editor_status != EditorStatus::EndOfInput; } -void -Editline::PrintAsync (Stream *stream, const char *s, size_t len) -{ - std::lock_guard<std::mutex> guard(m_output_mutex); - if (m_editor_status == EditorStatus::Editing) - { - MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); - fprintf(m_output_file, ANSI_CLEAR_BELOW); - } - stream->Write (s, len); - stream->Flush(); - if (m_editor_status == EditorStatus::Editing) - { - DisplayInput(); - MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); - } +void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { + std::lock_guard<std::mutex> guard(m_output_mutex); + if (m_editor_status == EditorStatus::Editing) { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + } + stream->Write(s, len); + stream->Flush(); + if (m_editor_status == EditorStatus::Editing) { + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); + } } diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 89587a9..fcd1416 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -34,1028 +34,829 @@ using namespace lldb; using namespace lldb_private; -static const char * -GetStreamOpenModeFromOptions (uint32_t options) -{ - if (options & File::eOpenOptionAppend) - { - if (options & File::eOpenOptionRead) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "a+x"; - else - return "a+"; - } - else if (options & File::eOpenOptionWrite) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "ax"; - else - return "a"; - } - } - else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) - { - if (options & File::eOpenOptionCanCreate) - { - if (options & File::eOpenOptionCanCreateNewOnly) - return "w+x"; - else - return "w+"; - } - else - return "r+"; - } - else if (options & File::eOpenOptionRead) - { - return "r"; - } - else if (options & File::eOpenOptionWrite) - { - return "w"; - } - return NULL; +static const char *GetStreamOpenModeFromOptions(uint32_t options) { + if (options & File::eOpenOptionAppend) { + if (options & File::eOpenOptionRead) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "a+x"; + else + return "a+"; + } else if (options & File::eOpenOptionWrite) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "ax"; + else + return "a"; + } + } else if (options & File::eOpenOptionRead && + options & File::eOpenOptionWrite) { + if (options & File::eOpenOptionCanCreate) { + if (options & File::eOpenOptionCanCreateNewOnly) + return "w+x"; + else + return "w+"; + } else + return "r+"; + } else if (options & File::eOpenOptionRead) { + return "r"; + } else if (options & File::eOpenOptionWrite) { + return "w"; + } + return NULL; } int File::kInvalidDescriptor = -1; -FILE * File::kInvalidStream = NULL; - -File::File(const char *path, uint32_t options, uint32_t permissions) : - IOObject(eFDTypeFile, false), - m_descriptor (kInvalidDescriptor), - m_stream (kInvalidStream), - m_options (), - m_own_stream (false), - m_is_interactive (eLazyBoolCalculate), - m_is_real_terminal (eLazyBoolCalculate) -{ - Open (path, options, permissions); -} - -File::File (const FileSpec& filespec, - uint32_t options, - uint32_t permissions) : - IOObject(eFDTypeFile, false), - m_descriptor (kInvalidDescriptor), - m_stream (kInvalidStream), - m_options (0), - m_own_stream (false), - m_is_interactive (eLazyBoolCalculate), - m_is_real_terminal (eLazyBoolCalculate) +FILE *File::kInvalidStream = NULL; -{ - if (filespec) - { - Open (filespec.GetPath().c_str(), options, permissions); - } +File::File(const char *path, uint32_t options, uint32_t permissions) + : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), + m_stream(kInvalidStream), m_options(), m_own_stream(false), + m_is_interactive(eLazyBoolCalculate), + m_is_real_terminal(eLazyBoolCalculate) { + Open(path, options, permissions); } -File::~File() +File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions) + : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), + m_stream(kInvalidStream), m_options(0), m_own_stream(false), + m_is_interactive(eLazyBoolCalculate), + m_is_real_terminal(eLazyBoolCalculate) + { - Close (); + if (filespec) { + Open(filespec.GetPath().c_str(), options, permissions); + } } +File::~File() { Close(); } -int -File::GetDescriptor() const -{ - if (DescriptorIsValid()) - return m_descriptor; +int File::GetDescriptor() const { + if (DescriptorIsValid()) + return m_descriptor; - // Don't open the file descriptor if we don't need to, just get it from the - // stream if we have one. - if (StreamIsValid()) - { + // Don't open the file descriptor if we don't need to, just get it from the + // stream if we have one. + if (StreamIsValid()) { #if defined(LLVM_ON_WIN32) - return _fileno(m_stream); + return _fileno(m_stream); #else - return fileno(m_stream); + return fileno(m_stream); #endif - } + } - // Invalid descriptor and invalid stream, return invalid descriptor. - return kInvalidDescriptor; -} - -IOObject::WaitableHandle -File::GetWaitableHandle() -{ - return m_descriptor; + // Invalid descriptor and invalid stream, return invalid descriptor. + return kInvalidDescriptor; } +IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; } -void -File::SetDescriptor (int fd, bool transfer_ownership) -{ - if (IsValid()) - Close(); - m_descriptor = fd; - m_should_close_fd = transfer_ownership; +void File::SetDescriptor(int fd, bool transfer_ownership) { + if (IsValid()) + Close(); + m_descriptor = fd; + m_should_close_fd = transfer_ownership; } - -FILE * -File::GetStream () -{ - if (!StreamIsValid()) - { - if (DescriptorIsValid()) - { - const char *mode = GetStreamOpenModeFromOptions (m_options); - if (mode) - { - if (!m_should_close_fd) - { - // We must duplicate the file descriptor if we don't own it because - // when you call fdopen, the stream will own the fd +FILE *File::GetStream() { + if (!StreamIsValid()) { + if (DescriptorIsValid()) { + const char *mode = GetStreamOpenModeFromOptions(m_options); + if (mode) { + if (!m_should_close_fd) { +// We must duplicate the file descriptor if we don't own it because +// when you call fdopen, the stream will own the fd #ifdef _WIN32 - m_descriptor = ::_dup(GetDescriptor()); + m_descriptor = ::_dup(GetDescriptor()); #else - m_descriptor = dup(GetDescriptor()); + m_descriptor = dup(GetDescriptor()); #endif - m_should_close_fd = true; - } - - do - { - m_stream = ::fdopen (m_descriptor, mode); - } while (m_stream == NULL && errno == EINTR); - - // If we got a stream, then we own the stream and should no - // longer own the descriptor because fclose() will close it for us - - if (m_stream) - { - m_own_stream = true; - m_should_close_fd = false; - } - } + m_should_close_fd = true; + } + + do { + m_stream = ::fdopen(m_descriptor, mode); + } while (m_stream == NULL && errno == EINTR); + + // If we got a stream, then we own the stream and should no + // longer own the descriptor because fclose() will close it for us + + if (m_stream) { + m_own_stream = true; + m_should_close_fd = false; } + } } - return m_stream; + } + return m_stream; } -void -File::SetStream (FILE *fh, bool transfer_ownership) -{ - if (IsValid()) - Close(); - m_stream = fh; - m_own_stream = transfer_ownership; +void File::SetStream(FILE *fh, bool transfer_ownership) { + if (IsValid()) + Close(); + m_stream = fh; + m_own_stream = transfer_ownership; } -Error -File::Open (const char *path, uint32_t options, uint32_t permissions) -{ - Error error; - if (IsValid()) - Close (); - - int oflag = 0; - const bool read = options & eOpenOptionRead; - const bool write = options & eOpenOptionWrite; - if (write) - { - if (read) - oflag |= O_RDWR; - else - oflag |= O_WRONLY; - - if (options & eOpenOptionAppend) - oflag |= O_APPEND; - - if (options & eOpenOptionTruncate) - oflag |= O_TRUNC; - - if (options & eOpenOptionCanCreate) - oflag |= O_CREAT; - - if (options & eOpenOptionCanCreateNewOnly) - oflag |= O_CREAT | O_EXCL; - } - else if (read) - { - oflag |= O_RDONLY; +Error File::Open(const char *path, uint32_t options, uint32_t permissions) { + Error error; + if (IsValid()) + Close(); + + int oflag = 0; + const bool read = options & eOpenOptionRead; + const bool write = options & eOpenOptionWrite; + if (write) { + if (read) + oflag |= O_RDWR; + else + oflag |= O_WRONLY; + + if (options & eOpenOptionAppend) + oflag |= O_APPEND; + + if (options & eOpenOptionTruncate) + oflag |= O_TRUNC; + + if (options & eOpenOptionCanCreate) + oflag |= O_CREAT; + + if (options & eOpenOptionCanCreateNewOnly) + oflag |= O_CREAT | O_EXCL; + } else if (read) { + oflag |= O_RDONLY; #ifndef _WIN32 - if (options & eOpenOptionDontFollowSymlinks) - oflag |= O_NOFOLLOW; + if (options & eOpenOptionDontFollowSymlinks) + oflag |= O_NOFOLLOW; #endif - } - + } + #ifndef _WIN32 - if (options & eOpenOptionNonBlocking) - oflag |= O_NONBLOCK; - if (options & eOpenOptionCloseOnExec) - oflag |= O_CLOEXEC; + if (options & eOpenOptionNonBlocking) + oflag |= O_NONBLOCK; + if (options & eOpenOptionCloseOnExec) + oflag |= O_CLOEXEC; #else - oflag |= O_BINARY; + oflag |= O_BINARY; #endif - mode_t mode = 0; - if (oflag & O_CREAT) - { - if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; - if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; - if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; - if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; - if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; - if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; - if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; - if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; - if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; + mode_t mode = 0; + if (oflag & O_CREAT) { + if (permissions & lldb::eFilePermissionsUserRead) + mode |= S_IRUSR; + if (permissions & lldb::eFilePermissionsUserWrite) + mode |= S_IWUSR; + if (permissions & lldb::eFilePermissionsUserExecute) + mode |= S_IXUSR; + if (permissions & lldb::eFilePermissionsGroupRead) + mode |= S_IRGRP; + if (permissions & lldb::eFilePermissionsGroupWrite) + mode |= S_IWGRP; + if (permissions & lldb::eFilePermissionsGroupExecute) + mode |= S_IXGRP; + if (permissions & lldb::eFilePermissionsWorldRead) + mode |= S_IROTH; + if (permissions & lldb::eFilePermissionsWorldWrite) + mode |= S_IWOTH; + if (permissions & lldb::eFilePermissionsWorldExecute) + mode |= S_IXOTH; + } + + do { +#ifdef _WIN32 + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + m_descriptor = -1; + error.SetErrorString("Error converting path to UTF-16"); + return error; } + ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); +#else + m_descriptor = ::open(path, oflag, mode); +#endif + } while (m_descriptor < 0 && errno == EINTR); + + if (!DescriptorIsValid()) + error.SetErrorToErrno(); + else { + m_should_close_fd = true; + m_options = options; + } + + return error; +} + +uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) { + if (file_spec) { + struct stat file_stats; + int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); + if (stat_result == -1) + error.SetErrorToErrno(); + else { + error.Clear(); + return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + } else + error.SetErrorString("empty file spec"); + return 0; +} + +uint32_t File::GetPermissions(Error &error) const { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + struct stat file_stats; + if (::fstat(fd, &file_stats) == -1) + error.SetErrorToErrno(); + else { + error.Clear(); + return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + } else { + error.SetErrorString("invalid file descriptor"); + } + return 0; +} + +Error File::Close() { + Error error; + if (StreamIsValid() && m_own_stream) { + if (::fclose(m_stream) == EOF) + error.SetErrorToErrno(); + } + + if (DescriptorIsValid() && m_should_close_fd) { + if (::close(m_descriptor) != 0) + error.SetErrorToErrno(); + } + m_descriptor = kInvalidDescriptor; + m_stream = kInvalidStream; + m_options = 0; + m_own_stream = false; + m_should_close_fd = false; + m_is_interactive = eLazyBoolCalculate; + m_is_real_terminal = eLazyBoolCalculate; + return error; +} + +void File::Clear() { + m_stream = nullptr; + m_descriptor = -1; + m_options = 0; + m_own_stream = false; + m_is_interactive = m_supports_colors = m_is_real_terminal = + eLazyBoolCalculate; +} + +Error File::GetFileSpec(FileSpec &file_spec) const { + Error error; +#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED + if (IsValid()) { + char path[PATH_MAX]; + if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) + error.SetErrorToErrno(); + else + file_spec.SetFile(path, false); + } else { + error.SetErrorString("invalid file handle"); + } +#elif defined(__linux__) + char proc[64]; + char path[PATH_MAX]; + if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) + error.SetErrorString("cannot resolve file descriptor"); + else { + ssize_t len; + if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) + error.SetErrorToErrno(); + else { + path[len] = '\0'; + file_spec.SetFile(path, false); + } + } +#else + error.SetErrorString("File::GetFileSpec is not supported on this platform"); +#endif - do - { + if (error.Fail()) + file_spec.Clear(); + return error; +} + +off_t File::SeekFromStart(off_t offset, Error *error_ptr) { + off_t result = 0; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_SET); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_SET); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) { + off_t result = -1; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_CUR); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_CUR); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +off_t File::SeekFromEnd(off_t offset, Error *error_ptr) { + off_t result = -1; + if (DescriptorIsValid()) { + result = ::lseek(m_descriptor, offset, SEEK_END); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (StreamIsValid()) { + result = ::fseek(m_stream, offset, SEEK_END); + + if (error_ptr) { + if (result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->Clear(); + } + } else if (error_ptr) { + error_ptr->SetErrorString("invalid file handle"); + } + return result; +} + +Error File::Flush() { + Error error; + if (StreamIsValid()) { + int err = 0; + do { + err = ::fflush(m_stream); + } while (err == EOF && errno == EINTR); + + if (err == EOF) + error.SetErrorToErrno(); + } else if (!DescriptorIsValid()) { + error.SetErrorString("invalid file handle"); + } + return error; +} + +Error File::Sync() { + Error error; + if (DescriptorIsValid()) { #ifdef _WIN32 - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - m_descriptor = -1; - error.SetErrorString("Error converting path to UTF-16"); - return error; - } - ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); + int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); + if (err == 0) + error.SetErrorToGenericError(); #else - m_descriptor = ::open(path, oflag, mode); -#endif - } while (m_descriptor < 0 && errno == EINTR); + int err = 0; + do { + err = ::fsync(m_descriptor); + } while (err == -1 && errno == EINTR); - if (!DescriptorIsValid()) - error.SetErrorToErrno(); - else - { - m_should_close_fd = true; - m_options = options; - } - - return error; + if (err == -1) + error.SetErrorToErrno(); +#endif + } else { + error.SetErrorString("invalid file handle"); + } + return error; } -uint32_t -File::GetPermissions(const FileSpec &file_spec, Error &error) -{ - if (file_spec) - { - struct stat file_stats; - int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); - if (stat_result == -1) - error.SetErrorToErrno(); - else - { - error.Clear(); - return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - } - else - error.SetErrorString ("empty file spec"); - return 0; -} +#if defined(__APPLE__) +// Darwin kernels only can read/write <= INT_MAX bytes +#define MAX_READ_SIZE INT_MAX +#define MAX_WRITE_SIZE INT_MAX +#endif -uint32_t -File::GetPermissions(Error &error) const -{ - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == -1) - error.SetErrorToErrno(); - else - { - error.Clear(); - return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - } - else - { - error.SetErrorString ("invalid file descriptor"); - } - return 0; -} +Error File::Read(void *buf, size_t &num_bytes) { + Error error; +#if defined(MAX_READ_SIZE) + if (num_bytes > MAX_READ_SIZE) { + uint8_t *p = (uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes read to zero + num_bytes = 0; -Error -File::Close () -{ - Error error; - if (StreamIsValid() && m_own_stream) - { - if (::fclose (m_stream) == EOF) - error.SetErrorToErrno(); - } - - if (DescriptorIsValid() && m_should_close_fd) - { - if (::close (m_descriptor) != 0) - error.SetErrorToErrno(); - } - m_descriptor = kInvalidDescriptor; - m_stream = kInvalidStream; - m_options = 0; - m_own_stream = false; - m_should_close_fd = false; - m_is_interactive = eLazyBoolCalculate; - m_is_real_terminal = eLazyBoolCalculate; - return error; -} + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_READ_SIZE) + curr_num_bytes = MAX_READ_SIZE; + else + curr_num_bytes = bytes_left; -void -File::Clear () -{ - m_stream = nullptr; - m_descriptor = -1; - m_options = 0; - m_own_stream = false; - m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate; -} + error = Read(p + num_bytes, curr_num_bytes); -Error -File::GetFileSpec (FileSpec &file_spec) const -{ - Error error; -#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED - if (IsValid ()) - { - char path[PATH_MAX]; - if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) - error.SetErrorToErrno(); - else - file_spec.SetFile (path, false); - } - else - { - error.SetErrorString("invalid file handle"); - } -#elif defined(__linux__) - char proc[64]; - char path[PATH_MAX]; - if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) - error.SetErrorString ("cannot resolve file descriptor"); - else - { - ssize_t len; - if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) - error.SetErrorToErrno(); - else - { - path[len] = '\0'; - file_spec.SetFile (path, false); - } + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } -#else - error.SetErrorString ("File::GetFileSpec is not supported on this platform"); + return error; + } #endif - if (error.Fail()) - file_spec.Clear(); - return error; + ssize_t bytes_read = -1; + if (DescriptorIsValid()) { + do { + bytes_read = ::read(m_descriptor, buf, num_bytes); + } while (bytes_read < 0 && errno == EINTR); + + if (bytes_read == -1) { + error.SetErrorToErrno(); + num_bytes = 0; + } else + num_bytes = bytes_read; + } else if (StreamIsValid()) { + bytes_read = ::fread(buf, 1, num_bytes, m_stream); + + if (bytes_read == 0) { + if (::feof(m_stream)) + error.SetErrorString("feof"); + else if (::ferror(m_stream)) + error.SetErrorString("ferror"); + num_bytes = 0; + } else + num_bytes = bytes_read; + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } + return error; } -off_t -File::SeekFromStart (off_t offset, Error *error_ptr) -{ - off_t result = 0; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_SET); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_SET); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} +Error File::Write(const void *buf, size_t &num_bytes) { + Error error; -off_t -File::SeekFromCurrent (off_t offset, Error *error_ptr) -{ - off_t result = -1; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_CUR); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_CUR); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} +#if defined(MAX_WRITE_SIZE) + if (num_bytes > MAX_WRITE_SIZE) { + const uint8_t *p = (const uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes written to zero + num_bytes = 0; -off_t -File::SeekFromEnd (off_t offset, Error *error_ptr) -{ - off_t result = -1; - if (DescriptorIsValid()) - { - result = ::lseek (m_descriptor, offset, SEEK_END); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (StreamIsValid ()) - { - result = ::fseek(m_stream, offset, SEEK_END); - - if (error_ptr) - { - if (result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->Clear(); - } - } - else if (error_ptr) - { - error_ptr->SetErrorString("invalid file handle"); - } - return result; -} + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_WRITE_SIZE) + curr_num_bytes = MAX_WRITE_SIZE; + else + curr_num_bytes = bytes_left; -Error -File::Flush () -{ - Error error; - if (StreamIsValid()) - { - int err = 0; - do - { - err = ::fflush (m_stream); - } while (err == EOF && errno == EINTR); - - if (err == EOF) - error.SetErrorToErrno(); - } - else if (!DescriptorIsValid()) - { - error.SetErrorString("invalid file handle"); - } - return error; -} + error = Write(p + num_bytes, curr_num_bytes); + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; -Error -File::Sync () -{ - Error error; - if (DescriptorIsValid()) - { -#ifdef _WIN32 - int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); - if (err == 0) - error.SetErrorToGenericError(); -#else - int err = 0; - do - { - err = ::fsync (m_descriptor); - } while (err == -1 && errno == EINTR); - - if (err == -1) - error.SetErrorToErrno(); -#endif - } - else - { - error.SetErrorString("invalid file handle"); + if (error.Fail()) + break; } return error; -} - -#if defined (__APPLE__) -// Darwin kernels only can read/write <= INT_MAX bytes -#define MAX_READ_SIZE INT_MAX -#define MAX_WRITE_SIZE INT_MAX + } #endif -Error -File::Read (void *buf, size_t &num_bytes) -{ - Error error; - -#if defined (MAX_READ_SIZE) - if (num_bytes > MAX_READ_SIZE) - { - uint8_t *p = (uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes read to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_READ_SIZE) - curr_num_bytes = MAX_READ_SIZE; - else - curr_num_bytes = bytes_left; - - error = Read (p + num_bytes, curr_num_bytes); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; - } -#endif + ssize_t bytes_written = -1; + if (DescriptorIsValid()) { + do { + bytes_written = ::write(m_descriptor, buf, num_bytes); + } while (bytes_written < 0 && errno == EINTR); + + if (bytes_written == -1) { + error.SetErrorToErrno(); + num_bytes = 0; + } else + num_bytes = bytes_written; + } else if (StreamIsValid()) { + bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); + + if (bytes_written == 0) { + if (::feof(m_stream)) + error.SetErrorString("feof"); + else if (::ferror(m_stream)) + error.SetErrorString("ferror"); + num_bytes = 0; + } else + num_bytes = bytes_written; + + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } - ssize_t bytes_read = -1; - if (DescriptorIsValid()) - { - do - { - bytes_read = ::read (m_descriptor, buf, num_bytes); - } while (bytes_read < 0 && errno == EINTR); - - if (bytes_read == -1) - { - error.SetErrorToErrno(); - num_bytes = 0; - } - else - num_bytes = bytes_read; - } - else if (StreamIsValid()) - { - bytes_read = ::fread (buf, 1, num_bytes, m_stream); - - if (bytes_read == 0) - { - if (::feof(m_stream)) - error.SetErrorString ("feof"); - else if (::ferror (m_stream)) - error.SetErrorString ("ferror"); - num_bytes = 0; - } - else - num_bytes = bytes_read; - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } - return error; + return error; } - -Error -File::Write (const void *buf, size_t &num_bytes) -{ - Error error; - -#if defined (MAX_WRITE_SIZE) - if (num_bytes > MAX_WRITE_SIZE) - { - const uint8_t *p = (const uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes written to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_WRITE_SIZE) - curr_num_bytes = MAX_WRITE_SIZE; - else - curr_num_bytes = bytes_left; - - error = Write (p + num_bytes, curr_num_bytes); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; - } -#endif - ssize_t bytes_written = -1; - if (DescriptorIsValid()) - { - do - { - bytes_written = ::write (m_descriptor, buf, num_bytes); - } while (bytes_written < 0 && errno == EINTR); - - if (bytes_written == -1) - { - error.SetErrorToErrno(); - num_bytes = 0; - } - else - num_bytes = bytes_written; - } - else if (StreamIsValid()) - { - bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); - - if (bytes_written == 0) - { - if (::feof(m_stream)) - error.SetErrorString ("feof"); - else if (::ferror (m_stream)) - error.SetErrorString ("ferror"); - num_bytes = 0; - } - else - num_bytes = bytes_written; - - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } +Error File::Read(void *buf, size_t &num_bytes, off_t &offset) { + Error error; - return error; -} +#if defined(MAX_READ_SIZE) + if (num_bytes > MAX_READ_SIZE) { + uint8_t *p = (uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes read to zero + num_bytes = 0; + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_READ_SIZE) + curr_num_bytes = MAX_READ_SIZE; + else + curr_num_bytes = bytes_left; -Error -File::Read (void *buf, size_t &num_bytes, off_t &offset) -{ - Error error; - -#if defined (MAX_READ_SIZE) - if (num_bytes > MAX_READ_SIZE) - { - uint8_t *p = (uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes read to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_READ_SIZE) - curr_num_bytes = MAX_READ_SIZE; - else - curr_num_bytes = bytes_left; - - error = Read (p + num_bytes, curr_num_bytes, offset); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; + error = Read(p + num_bytes, curr_num_bytes, offset); + + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } + return error; + } #endif #ifndef _WIN32 - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - ssize_t bytes_read = -1; - do - { - bytes_read = ::pread (fd, buf, num_bytes, offset); - } while (bytes_read < 0 && errno == EINTR); - - if (bytes_read < 0) - { - num_bytes = 0; - error.SetErrorToErrno(); - } - else - { - offset += bytes_read; - num_bytes = bytes_read; - } - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + ssize_t bytes_read = -1; + do { + bytes_read = ::pread(fd, buf, num_bytes, offset); + } while (bytes_read < 0 && errno == EINTR); + + if (bytes_read < 0) { + num_bytes = 0; + error.SetErrorToErrno(); + } else { + offset += bytes_read; + num_bytes = bytes_read; + } + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } #else - long cur = ::lseek(m_descriptor, 0, SEEK_CUR); - SeekFromStart(offset); - error = Read(buf, num_bytes); - if (!error.Fail()) - SeekFromStart(cur); + long cur = ::lseek(m_descriptor, 0, SEEK_CUR); + SeekFromStart(offset); + error = Read(buf, num_bytes); + if (!error.Fail()) + SeekFromStart(cur); #endif - return error; + return error; } -Error -File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) -{ - Error error; - - if (num_bytes > 0) - { - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == 0) - { - if (file_stats.st_size > offset) - { - const size_t bytes_left = file_stats.st_size - offset; - if (num_bytes > bytes_left) - num_bytes = bytes_left; - - size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); - std::unique_ptr<DataBufferHeap> data_heap_ap; - data_heap_ap.reset(new DataBufferHeap()); - data_heap_ap->SetByteSize(num_bytes_plus_nul_char); - - if (data_heap_ap.get()) - { - error = Read (data_heap_ap->GetBytes(), num_bytes, offset); - if (error.Success()) - { - // Make sure we read exactly what we asked for and if we got - // less, adjust the array - if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) - data_heap_ap->SetByteSize(num_bytes_plus_nul_char); - data_buffer_sp.reset(data_heap_ap.release()); - return error; - } - } - } - else - error.SetErrorString("file is empty"); +Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, + DataBufferSP &data_buffer_sp) { + Error error; + + if (num_bytes > 0) { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { + struct stat file_stats; + if (::fstat(fd, &file_stats) == 0) { + if (file_stats.st_size > offset) { + const size_t bytes_left = file_stats.st_size - offset; + if (num_bytes > bytes_left) + num_bytes = bytes_left; + + size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); + std::unique_ptr<DataBufferHeap> data_heap_ap; + data_heap_ap.reset(new DataBufferHeap()); + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); + + if (data_heap_ap.get()) { + error = Read(data_heap_ap->GetBytes(), num_bytes, offset); + if (error.Success()) { + // Make sure we read exactly what we asked for and if we got + // less, adjust the array + if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); + data_buffer_sp.reset(data_heap_ap.release()); + return error; } - else - error.SetErrorToErrno(); - } - else - error.SetErrorString("invalid file handle"); - } - else - error.SetErrorString("invalid file handle"); + } + } else + error.SetErrorString("file is empty"); + } else + error.SetErrorToErrno(); + } else + error.SetErrorString("invalid file handle"); + } else + error.SetErrorString("invalid file handle"); - num_bytes = 0; - data_buffer_sp.reset(); - return error; + num_bytes = 0; + data_buffer_sp.reset(); + return error; } -Error -File::Write (const void *buf, size_t &num_bytes, off_t &offset) -{ - Error error; - -#if defined (MAX_WRITE_SIZE) - if (num_bytes > MAX_WRITE_SIZE) - { - const uint8_t *p = (const uint8_t *)buf; - size_t bytes_left = num_bytes; - // Init the num_bytes written to zero - num_bytes = 0; - - while (bytes_left > 0) - { - size_t curr_num_bytes; - if (bytes_left > MAX_WRITE_SIZE) - curr_num_bytes = MAX_WRITE_SIZE; - else - curr_num_bytes = bytes_left; - - error = Write (p + num_bytes, curr_num_bytes, offset); - - // Update how many bytes were read - num_bytes += curr_num_bytes; - if (bytes_left < curr_num_bytes) - bytes_left = 0; - else - bytes_left -= curr_num_bytes; - - if (error.Fail()) - break; - } - return error; +Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) { + Error error; + +#if defined(MAX_WRITE_SIZE) + if (num_bytes > MAX_WRITE_SIZE) { + const uint8_t *p = (const uint8_t *)buf; + size_t bytes_left = num_bytes; + // Init the num_bytes written to zero + num_bytes = 0; + + while (bytes_left > 0) { + size_t curr_num_bytes; + if (bytes_left > MAX_WRITE_SIZE) + curr_num_bytes = MAX_WRITE_SIZE; + else + curr_num_bytes = bytes_left; + + error = Write(p + num_bytes, curr_num_bytes, offset); + + // Update how many bytes were read + num_bytes += curr_num_bytes; + if (bytes_left < curr_num_bytes) + bytes_left = 0; + else + bytes_left -= curr_num_bytes; + + if (error.Fail()) + break; } + return error; + } #endif - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) - { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { #ifndef _WIN32 - ssize_t bytes_written = -1; - do - { - bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); - } while (bytes_written < 0 && errno == EINTR); - - if (bytes_written < 0) - { - num_bytes = 0; - error.SetErrorToErrno(); - } - else - { - offset += bytes_written; - num_bytes = bytes_written; - } + ssize_t bytes_written = -1; + do { + bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); + } while (bytes_written < 0 && errno == EINTR); + + if (bytes_written < 0) { + num_bytes = 0; + error.SetErrorToErrno(); + } else { + offset += bytes_written; + num_bytes = bytes_written; + } #else - long cur = ::lseek(m_descriptor, 0, SEEK_CUR); - error = Write(buf, num_bytes); - long after = ::lseek(m_descriptor, 0, SEEK_CUR); + long cur = ::lseek(m_descriptor, 0, SEEK_CUR); + error = Write(buf, num_bytes); + long after = ::lseek(m_descriptor, 0, SEEK_CUR); - if (!error.Fail()) - SeekFromStart(cur); + if (!error.Fail()) + SeekFromStart(cur); - offset = after; + offset = after; #endif - } - else - { - num_bytes = 0; - error.SetErrorString("invalid file handle"); - } - return error; + } else { + num_bytes = 0; + error.SetErrorString("invalid file handle"); + } + return error; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -File::Printf (const char *format, ...) -{ - va_list args; - va_start (args, format); - size_t result = PrintfVarArg (format, args); - va_end (args); - return result; +size_t File::Printf(const char *format, ...) { + va_list args; + va_start(args, format); + size_t result = PrintfVarArg(format, args); + va_end(args); + return result; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -File::PrintfVarArg (const char *format, va_list args) -{ - size_t result = 0; - if (DescriptorIsValid()) - { - char *s = NULL; - result = vasprintf(&s, format, args); - if (s != NULL) - { - if (result > 0) - { - size_t s_len = result; - Write (s, s_len); - result = s_len; - } - free (s); - } - } - else if (StreamIsValid()) - { - result = ::vfprintf (m_stream, format, args); - } - return result; -} - -mode_t -File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) -{ - mode_t mode = 0; - if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) - mode |= O_RDWR; - else if (open_options & eOpenOptionWrite) - mode |= O_WRONLY; - - if (open_options & eOpenOptionAppend) - mode |= O_APPEND; - - if (open_options & eOpenOptionTruncate) - mode |= O_TRUNC; - - if (open_options & eOpenOptionNonBlocking) - mode |= O_NONBLOCK; - - if (open_options & eOpenOptionCanCreateNewOnly) - mode |= O_CREAT | O_EXCL; - else if (open_options & eOpenOptionCanCreate) - mode |= O_CREAT; - - return mode; -} - -void -File::CalculateInteractiveAndTerminal () -{ - const int fd = GetDescriptor(); - if (fd >= 0) - { - m_is_interactive = eLazyBoolNo; - m_is_real_terminal = eLazyBoolNo; +size_t File::PrintfVarArg(const char *format, va_list args) { + size_t result = 0; + if (DescriptorIsValid()) { + char *s = NULL; + result = vasprintf(&s, format, args); + if (s != NULL) { + if (result > 0) { + size_t s_len = result; + Write(s, s_len); + result = s_len; + } + free(s); + } + } else if (StreamIsValid()) { + result = ::vfprintf(m_stream, format, args); + } + return result; +} + +mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { + mode_t mode = 0; + if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) + mode |= O_RDWR; + else if (open_options & eOpenOptionWrite) + mode |= O_WRONLY; + + if (open_options & eOpenOptionAppend) + mode |= O_APPEND; + + if (open_options & eOpenOptionTruncate) + mode |= O_TRUNC; + + if (open_options & eOpenOptionNonBlocking) + mode |= O_NONBLOCK; + + if (open_options & eOpenOptionCanCreateNewOnly) + mode |= O_CREAT | O_EXCL; + else if (open_options & eOpenOptionCanCreate) + mode |= O_CREAT; + + return mode; +} + +void File::CalculateInteractiveAndTerminal() { + const int fd = GetDescriptor(); + if (fd >= 0) { + m_is_interactive = eLazyBoolNo; + m_is_real_terminal = eLazyBoolNo; #if defined(_WIN32) - if (_isatty(fd)) - { - m_is_interactive = eLazyBoolYes; - m_is_real_terminal = eLazyBoolYes; - } + if (_isatty(fd)) { + m_is_interactive = eLazyBoolYes; + m_is_real_terminal = eLazyBoolYes; + } #else - if (isatty(fd)) - { - m_is_interactive = eLazyBoolYes; - struct winsize window_size; - if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) - { - if (window_size.ws_col > 0) - { - m_is_real_terminal = eLazyBoolYes; - if (llvm::sys::Process::FileDescriptorHasColors(fd)) - m_supports_colors = eLazyBoolYes; - } - } + if (isatty(fd)) { + m_is_interactive = eLazyBoolYes; + struct winsize window_size; + if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { + if (window_size.ws_col > 0) { + m_is_real_terminal = eLazyBoolYes; + if (llvm::sys::Process::FileDescriptorHasColors(fd)) + m_supports_colors = eLazyBoolYes; } -#endif + } } +#endif + } } -bool -File::GetIsInteractive () -{ - if (m_is_interactive == eLazyBoolCalculate) - CalculateInteractiveAndTerminal (); - return m_is_interactive == eLazyBoolYes; +bool File::GetIsInteractive() { + if (m_is_interactive == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_interactive == eLazyBoolYes; } -bool -File::GetIsRealTerminal () -{ - if (m_is_real_terminal == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_is_real_terminal == eLazyBoolYes; +bool File::GetIsRealTerminal() { + if (m_is_real_terminal == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_real_terminal == eLazyBoolYes; } -bool -File::GetIsTerminalWithColors () -{ - if (m_supports_colors == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_supports_colors == eLazyBoolYes; +bool File::GetIsTerminalWithColors() { + if (m_supports_colors == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_supports_colors == eLazyBoolYes; } - diff --git a/lldb/source/Host/common/FileCache.cpp b/lldb/source/Host/common/FileCache.cpp index 96b2a2e..db71813 100644 --- a/lldb/source/Host/common/FileCache.cpp +++ b/lldb/source/Host/common/FileCache.cpp @@ -16,112 +16,97 @@ using namespace lldb_private; FileCache *FileCache::m_instance = nullptr; -FileCache & -FileCache::GetInstance() -{ - if (m_instance == nullptr) - m_instance = new FileCache(); +FileCache &FileCache::GetInstance() { + if (m_instance == nullptr) + m_instance = new FileCache(); - return *m_instance; + return *m_instance; } -lldb::user_id_t -FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, uint32_t mode, Error &error) -{ - std::string path(file_spec.GetPath()); - if (path.empty()) - { - error.SetErrorString("empty path"); - return UINT64_MAX; - } - FileSP file_sp(new File()); - error = file_sp->Open(path.c_str(), flags, mode); - if (file_sp->IsValid() == false) - return UINT64_MAX; - lldb::user_id_t fd = file_sp->GetDescriptor(); - m_cache[fd] = file_sp; - return fd; +lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, + uint32_t mode, Error &error) { + std::string path(file_spec.GetPath()); + if (path.empty()) { + error.SetErrorString("empty path"); + return UINT64_MAX; + } + FileSP file_sp(new File()); + error = file_sp->Open(path.c_str(), flags, mode); + if (file_sp->IsValid() == false) + return UINT64_MAX; + lldb::user_id_t fd = file_sp->GetDescriptor(); + m_cache[fd] = file_sp; + return fd; } -bool -FileCache::CloseFile(lldb::user_id_t fd, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return false; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return false; - } - error = file_sp->Close(); - m_cache.erase(pos); - return error.Success(); +bool FileCache::CloseFile(lldb::user_id_t fd, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return false; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return false; + } + error = file_sp->Close(); + m_cache.erase(pos); + return error.Success(); } -uint64_t -FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return UINT64_MAX; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return UINT64_MAX; - } - if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail()) - return UINT64_MAX; - size_t bytes_written = src_len; - error = file_sp->Write(src, bytes_written); - if (error.Fail()) - return UINT64_MAX; - return bytes_written; +uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, + const void *src, uint64_t src_len, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return UINT64_MAX; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return UINT64_MAX; + } + if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || + error.Fail()) + return UINT64_MAX; + size_t bytes_written = src_len; + error = file_sp->Write(src, bytes_written); + if (error.Fail()) + return UINT64_MAX; + return bytes_written; } -uint64_t -FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Error &error) -{ - if (fd == UINT64_MAX) - { - error.SetErrorString("invalid file descriptor"); - return UINT64_MAX; - } - FDToFileMap::iterator pos = m_cache.find(fd); - if (pos == m_cache.end()) - { - error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); - return false; - } - FileSP file_sp = pos->second; - if (!file_sp) - { - error.SetErrorString("invalid host backing file"); - return UINT64_MAX; - } - if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail()) - return UINT64_MAX; - size_t bytes_read = dst_len; - error = file_sp->Read(dst, bytes_read); - if (error.Fail()) - return UINT64_MAX; - return bytes_read; +uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, + uint64_t dst_len, Error &error) { + if (fd == UINT64_MAX) { + error.SetErrorString("invalid file descriptor"); + return UINT64_MAX; + } + FDToFileMap::iterator pos = m_cache.find(fd); + if (pos == m_cache.end()) { + error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); + return false; + } + FileSP file_sp = pos->second; + if (!file_sp) { + error.SetErrorString("invalid host backing file"); + return UINT64_MAX; + } + if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || + error.Fail()) + return UINT64_MAX; + size_t bytes_read = dst_len; + error = file_sp->Read(dst, bytes_read); + if (error.Fail()) + return UINT64_MAX; + return bytes_read; } diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 62117b78..0f2a664 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef _WIN32 #include <dirent.h> #else @@ -17,9 +16,9 @@ #ifndef _MSC_VER #include <libgen.h> #endif +#include <fstream> #include <set> #include <string.h> -#include <fstream> #include "lldb/Host/Config.h" // Have to include this before we test the define... #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER @@ -30,8 +29,8 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataBufferMemoryMap.h" #include "lldb/Core/RegularExpression.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" @@ -49,339 +48,291 @@ using namespace lldb_private; namespace { -bool -PathSyntaxIsPosix(FileSpec::PathSyntax syntax) -{ - return (syntax == FileSpec::ePathSyntaxPosix || - (syntax == FileSpec::ePathSyntaxHostNative && - FileSystem::GetNativePathSyntax() == FileSpec::ePathSyntaxPosix)); +bool PathSyntaxIsPosix(FileSpec::PathSyntax syntax) { + return (syntax == FileSpec::ePathSyntaxPosix || + (syntax == FileSpec::ePathSyntaxHostNative && + FileSystem::GetNativePathSyntax() == FileSpec::ePathSyntaxPosix)); } -const char * -GetPathSeparators(FileSpec::PathSyntax syntax) -{ - return PathSyntaxIsPosix(syntax) ? "/" : "\\/"; +const char *GetPathSeparators(FileSpec::PathSyntax syntax) { + return PathSyntaxIsPosix(syntax) ? "/" : "\\/"; } -char -GetPrefferedPathSeparator(FileSpec::PathSyntax syntax) -{ - return GetPathSeparators(syntax)[0]; +char GetPrefferedPathSeparator(FileSpec::PathSyntax syntax) { + return GetPathSeparators(syntax)[0]; } -bool -IsPathSeparator(char value, FileSpec::PathSyntax syntax) -{ - return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\'); +bool IsPathSeparator(char value, FileSpec::PathSyntax syntax) { + return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\'); } -void -Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) -{ - if (PathSyntaxIsPosix(syntax)) return; +void Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) { + if (PathSyntaxIsPosix(syntax)) + return; - std::replace(path.begin(), path.end(), '\\', '/'); - // Windows path can have \\ slashes which can be changed by replace - // call above to //. Here we remove the duplicate. - auto iter = std::unique ( path.begin(), path.end(), - []( char &c1, char &c2 ){ - return (c1 == '/' && c2 == '/');}); - path.erase(iter, path.end()); + std::replace(path.begin(), path.end(), '\\', '/'); + // Windows path can have \\ slashes which can be changed by replace + // call above to //. Here we remove the duplicate. + auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) { + return (c1 == '/' && c2 == '/'); + }); + path.erase(iter, path.end()); } -void -Denormalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) -{ - if (PathSyntaxIsPosix(syntax)) return; +void Denormalize(llvm::SmallVectorImpl<char> &path, + FileSpec::PathSyntax syntax) { + if (PathSyntaxIsPosix(syntax)) + return; - std::replace(path.begin(), path.end(), '/', '\\'); + std::replace(path.begin(), path.end(), '/', '\\'); } -bool -GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr) -{ - char resolved_path[PATH_MAX]; - if (file_spec->GetPath (resolved_path, sizeof(resolved_path))) - return FileSystem::Stat(resolved_path, stats_ptr) == 0; - return false; +bool GetFileStats(const FileSpec *file_spec, struct stat *stats_ptr) { + char resolved_path[PATH_MAX]; + if (file_spec->GetPath(resolved_path, sizeof(resolved_path))) + return FileSystem::Stat(resolved_path, stats_ptr) == 0; + return false; } -size_t -FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) -{ - if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) - return 0; +size_t FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) { + if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) + return 0; - if (str.size() > 0 && IsPathSeparator(str.back(), syntax)) - return str.size() - 1; + if (str.size() > 0 && IsPathSeparator(str.back(), syntax)) + return str.size() - 1; - size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1); + size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1); - if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos) - pos = str.find_last_of(':', str.size() - 2); + if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos) + pos = str.find_last_of(':', str.size() - 2); - if (pos == llvm::StringRef::npos || (pos == 1 && IsPathSeparator(str[0], syntax))) - return 0; + if (pos == llvm::StringRef::npos || + (pos == 1 && IsPathSeparator(str[0], syntax))) + return 0; - return pos + 1; + return pos + 1; } -size_t -RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) -{ - // case "c:/" - if (!PathSyntaxIsPosix(syntax) && (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax))) - return 2; +size_t RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) { + // case "c:/" + if (!PathSyntaxIsPosix(syntax) && + (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax))) + return 2; - // case "//" - if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) - return llvm::StringRef::npos; + // case "//" + if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1]) + return llvm::StringRef::npos; - // case "//net" - if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] && !IsPathSeparator(str[2], syntax)) - return str.find_first_of(GetPathSeparators(syntax), 2); + // case "//net" + if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] && + !IsPathSeparator(str[2], syntax)) + return str.find_first_of(GetPathSeparators(syntax), 2); - // case "/" - if (str.size() > 0 && IsPathSeparator(str[0], syntax)) - return 0; + // case "/" + if (str.size() > 0 && IsPathSeparator(str[0], syntax)) + return 0; - return llvm::StringRef::npos; + return llvm::StringRef::npos; } -size_t -ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) -{ - size_t end_pos = FilenamePos(path, syntax); +size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) { + size_t end_pos = FilenamePos(path, syntax); - bool filename_was_sep = path.size() > 0 && IsPathSeparator(path[end_pos], syntax); + bool filename_was_sep = + path.size() > 0 && IsPathSeparator(path[end_pos], syntax); - // Skip separators except for root dir. - size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax); + // Skip separators except for root dir. + size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax); - while (end_pos > 0 && (end_pos - 1) != root_dir_pos && IsPathSeparator(path[end_pos - 1], syntax)) - --end_pos; + while (end_pos > 0 && (end_pos - 1) != root_dir_pos && + IsPathSeparator(path[end_pos - 1], syntax)) + --end_pos; - if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) - return llvm::StringRef::npos; + if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) + return llvm::StringRef::npos; - return end_pos; + return end_pos; } } // end anonymous namespace // Resolves the username part of a path of the form ~user/other/directories, and -// writes the result into dst_path. This will also resolve "~" to the current user. -// If you want to complete "~" to the list of users, pass it to ResolvePartialUsername. -void -FileSpec::ResolveUsername (llvm::SmallVectorImpl<char> &path) -{ +// writes the result into dst_path. This will also resolve "~" to the current +// user. +// If you want to complete "~" to the list of users, pass it to +// ResolvePartialUsername. +void FileSpec::ResolveUsername(llvm::SmallVectorImpl<char> &path) { #if LLDB_CONFIG_TILDE_RESOLVES_TO_USER - if (path.empty() || path[0] != '~') - return; - - llvm::StringRef path_str(path.data(), path.size()); - size_t slash_pos = path_str.find('/', 1); - if (slash_pos == 1 || path.size() == 1) - { - // A path of ~/ resolves to the current user's home dir - llvm::SmallString<64> home_dir; - // llvm::sys::path::home_directory() only checks if "HOME" is set in the - // environment and does nothing else to locate the user home directory - if (!llvm::sys::path::home_directory(home_dir)) - { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir && pw->pw_dir[0]) - { - // Update our environemnt so llvm::sys::path::home_directory() works next time - setenv("HOME", pw->pw_dir, 0); - home_dir.assign(llvm::StringRef(pw->pw_dir)); - } - else - { - return; - } - } - - // Overwrite the ~ with the first character of the homedir, and insert - // the rest. This way we only trigger one move, whereas an insert - // followed by a delete (or vice versa) would trigger two. - path[0] = home_dir[0]; - path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end()); + if (path.empty() || path[0] != '~') + return; + + llvm::StringRef path_str(path.data(), path.size()); + size_t slash_pos = path_str.find('/', 1); + if (slash_pos == 1 || path.size() == 1) { + // A path of ~/ resolves to the current user's home dir + llvm::SmallString<64> home_dir; + // llvm::sys::path::home_directory() only checks if "HOME" is set in the + // environment and does nothing else to locate the user home directory + if (!llvm::sys::path::home_directory(home_dir)) { + struct passwd *pw = getpwuid(getuid()); + if (pw && pw->pw_dir && pw->pw_dir[0]) { + // Update our environemnt so llvm::sys::path::home_directory() works + // next time + setenv("HOME", pw->pw_dir, 0); + home_dir.assign(llvm::StringRef(pw->pw_dir)); + } else { return; + } } - - auto username_begin = path.begin()+1; - auto username_end = (slash_pos == llvm::StringRef::npos) - ? path.end() - : (path.begin() + slash_pos); - size_t replacement_length = std::distance(path.begin(), username_end); - - llvm::SmallString<20> username(username_begin, username_end); - struct passwd *user_entry = ::getpwnam(username.c_str()); - if (user_entry != nullptr) - { - // Copy over the first n characters of the path, where n is the smaller of the length - // of the home directory and the slash pos. - llvm::StringRef homedir(user_entry->pw_dir); - size_t initial_copy_length = std::min(homedir.size(), replacement_length); - auto src_begin = homedir.begin(); - auto src_end = src_begin + initial_copy_length; - std::copy(src_begin, src_end, path.begin()); - if (replacement_length > homedir.size()) - { - // We copied the entire home directory, but the ~username portion of the path was - // longer, so there's characters that need to be removed. - path.erase(path.begin() + initial_copy_length, username_end); - } - else if (replacement_length < homedir.size()) - { - // We copied all the way up to the slash in the destination, but there's still more - // characters that need to be inserted. - path.insert(username_end, src_end, homedir.end()); - } - } - else - { - // Unable to resolve username (user doesn't exist?) - path.clear(); + + // Overwrite the ~ with the first character of the homedir, and insert + // the rest. This way we only trigger one move, whereas an insert + // followed by a delete (or vice versa) would trigger two. + path[0] = home_dir[0]; + path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end()); + return; + } + + auto username_begin = path.begin() + 1; + auto username_end = (slash_pos == llvm::StringRef::npos) + ? path.end() + : (path.begin() + slash_pos); + size_t replacement_length = std::distance(path.begin(), username_end); + + llvm::SmallString<20> username(username_begin, username_end); + struct passwd *user_entry = ::getpwnam(username.c_str()); + if (user_entry != nullptr) { + // Copy over the first n characters of the path, where n is the smaller of + // the length + // of the home directory and the slash pos. + llvm::StringRef homedir(user_entry->pw_dir); + size_t initial_copy_length = std::min(homedir.size(), replacement_length); + auto src_begin = homedir.begin(); + auto src_end = src_begin + initial_copy_length; + std::copy(src_begin, src_end, path.begin()); + if (replacement_length > homedir.size()) { + // We copied the entire home directory, but the ~username portion of the + // path was + // longer, so there's characters that need to be removed. + path.erase(path.begin() + initial_copy_length, username_end); + } else if (replacement_length < homedir.size()) { + // We copied all the way up to the slash in the destination, but there's + // still more + // characters that need to be inserted. + path.insert(username_end, src_end, homedir.end()); } + } else { + // Unable to resolve username (user doesn't exist?) + path.clear(); + } #endif } -size_t -FileSpec::ResolvePartialUsername (const char *partial_name, StringList &matches) -{ +size_t FileSpec::ResolvePartialUsername(const char *partial_name, + StringList &matches) { #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - size_t extant_entries = matches.GetSize(); - - setpwent(); - struct passwd *user_entry; - const char *name_start = partial_name + 1; - std::set<std::string> name_list; - - while ((user_entry = getpwent()) != NULL) - { - if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) - { - std::string tmp_buf("~"); - tmp_buf.append(user_entry->pw_name); - tmp_buf.push_back('/'); - name_list.insert(tmp_buf); - } + size_t extant_entries = matches.GetSize(); + + setpwent(); + struct passwd *user_entry; + const char *name_start = partial_name + 1; + std::set<std::string> name_list; + + while ((user_entry = getpwent()) != NULL) { + if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) { + std::string tmp_buf("~"); + tmp_buf.append(user_entry->pw_name); + tmp_buf.push_back('/'); + name_list.insert(tmp_buf); } - std::set<std::string>::iterator pos, end = name_list.end(); - for (pos = name_list.begin(); pos != end; pos++) - { - matches.AppendString((*pos).c_str()); - } - return matches.GetSize() - extant_entries; + } + std::set<std::string>::iterator pos, end = name_list.end(); + for (pos = name_list.begin(); pos != end; pos++) { + matches.AppendString((*pos).c_str()); + } + return matches.GetSize() - extant_entries; #else - // Resolving home directories is not supported, just copy the path... - return 0; -#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER + // Resolving home directories is not supported, just copy the path... + return 0; +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER } -void -FileSpec::Resolve (llvm::SmallVectorImpl<char> &path) -{ - if (path.empty()) - return; +void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) { + if (path.empty()) + return; #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - if (path[0] == '~') - ResolveUsername(path); + if (path[0] == '~') + ResolveUsername(path); #endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER - // Save a copy of the original path that's passed in - llvm::SmallString<128> original_path(path.begin(), path.end()); + // Save a copy of the original path that's passed in + llvm::SmallString<128> original_path(path.begin(), path.end()); - llvm::sys::fs::make_absolute(path); - if (!llvm::sys::fs::exists(path)) - { - path.clear(); - path.append(original_path.begin(), original_path.end()); - } + llvm::sys::fs::make_absolute(path); + if (!llvm::sys::fs::exists(path)) { + path.clear(); + path.append(original_path.begin(), original_path.end()); + } } -FileSpec::FileSpec() : - m_directory(), - m_filename(), - m_syntax(FileSystem::GetNativePathSyntax()) -{ +FileSpec::FileSpec() + : m_directory(), m_filename(), m_syntax(FileSystem::GetNativePathSyntax()) { } //------------------------------------------------------------------ // Default constructor that can take an optional full path to a // file on disk. //------------------------------------------------------------------ -FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) : - m_directory(), - m_filename(), - m_is_resolved(false), - m_syntax(syntax) -{ - if (pathname && pathname[0]) - SetFile(pathname, resolve_path, syntax); +FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) + : m_directory(), m_filename(), m_is_resolved(false), m_syntax(syntax) { + if (pathname && pathname[0]) + SetFile(pathname, resolve_path, syntax); } -FileSpec::FileSpec(const char *pathname, bool resolve_path, ArchSpec arch) : - FileSpec{pathname, resolve_path, arch.GetTriple().isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix} -{ -} +FileSpec::FileSpec(const char *pathname, bool resolve_path, ArchSpec arch) + : FileSpec{pathname, resolve_path, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix} {} -FileSpec::FileSpec(const std::string &path, bool resolve_path, PathSyntax syntax) : - FileSpec{path.c_str(), resolve_path, syntax} -{ -} +FileSpec::FileSpec(const std::string &path, bool resolve_path, + PathSyntax syntax) + : FileSpec{path.c_str(), resolve_path, syntax} {} -FileSpec::FileSpec(const std::string &path, bool resolve_path, ArchSpec arch) : - FileSpec{path.c_str(), resolve_path, arch} -{ -} +FileSpec::FileSpec(const std::string &path, bool resolve_path, ArchSpec arch) + : FileSpec{path.c_str(), resolve_path, arch} {} //------------------------------------------------------------------ // Copy constructor //------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec& rhs) : - m_directory (rhs.m_directory), - m_filename (rhs.m_filename), - m_is_resolved (rhs.m_is_resolved), - m_syntax (rhs.m_syntax) -{ -} +FileSpec::FileSpec(const FileSpec &rhs) + : m_directory(rhs.m_directory), m_filename(rhs.m_filename), + m_is_resolved(rhs.m_is_resolved), m_syntax(rhs.m_syntax) {} //------------------------------------------------------------------ // Copy constructor //------------------------------------------------------------------ -FileSpec::FileSpec(const FileSpec* rhs) : - m_directory(), - m_filename() -{ - if (rhs) - *this = *rhs; +FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() { + if (rhs) + *this = *rhs; } //------------------------------------------------------------------ // Virtual destructor in case anyone inherits from this class. //------------------------------------------------------------------ -FileSpec::~FileSpec() -{ -} +FileSpec::~FileSpec() {} //------------------------------------------------------------------ // Assignment operator. //------------------------------------------------------------------ -const FileSpec& -FileSpec::operator= (const FileSpec& rhs) -{ - if (this != &rhs) - { - m_directory = rhs.m_directory; - m_filename = rhs.m_filename; - m_is_resolved = rhs.m_is_resolved; - m_syntax = rhs.m_syntax; - } - return *this; +const FileSpec &FileSpec::operator=(const FileSpec &rhs) { + if (this != &rhs) { + m_directory = rhs.m_directory; + m_filename = rhs.m_filename; + m_is_resolved = rhs.m_is_resolved; + m_syntax = rhs.m_syntax; + } + return *this; } //------------------------------------------------------------------ @@ -389,66 +340,62 @@ FileSpec::operator= (const FileSpec& rhs) // be split up into a directory and filename and stored as uniqued // string values for quick comparison and efficient memory usage. //------------------------------------------------------------------ -void -FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax) -{ - m_filename.Clear(); - m_directory.Clear(); - m_is_resolved = false; - m_syntax = (syntax == ePathSyntaxHostNative) ? FileSystem::GetNativePathSyntax() : syntax; - - if (pathname == NULL || pathname[0] == '\0') - return; +void FileSpec::SetFile(const char *pathname, bool resolve, PathSyntax syntax) { + m_filename.Clear(); + m_directory.Clear(); + m_is_resolved = false; + m_syntax = (syntax == ePathSyntaxHostNative) + ? FileSystem::GetNativePathSyntax() + : syntax; + + if (pathname == NULL || pathname[0] == '\0') + return; - llvm::SmallString<64> resolved(pathname); + llvm::SmallString<64> resolved(pathname); - if (resolve) - { - FileSpec::Resolve (resolved); - m_is_resolved = true; - } + if (resolve) { + FileSpec::Resolve(resolved); + m_is_resolved = true; + } - Normalize(resolved, syntax); + Normalize(resolved, syntax); - llvm::StringRef resolve_path_ref(resolved.c_str()); - size_t dir_end = ParentPathEnd(resolve_path_ref, syntax); - if (dir_end == 0) - { - m_filename.SetString(resolve_path_ref); - return; - } + llvm::StringRef resolve_path_ref(resolved.c_str()); + size_t dir_end = ParentPathEnd(resolve_path_ref, syntax); + if (dir_end == 0) { + m_filename.SetString(resolve_path_ref); + return; + } - m_directory.SetString(resolve_path_ref.substr(0, dir_end)); + m_directory.SetString(resolve_path_ref.substr(0, dir_end)); - size_t filename_begin = dir_end; - size_t root_dir_start = RootDirStart(resolve_path_ref, syntax); - while (filename_begin != llvm::StringRef::npos && filename_begin < resolve_path_ref.size() && - filename_begin != root_dir_start && IsPathSeparator(resolve_path_ref[filename_begin], syntax)) - ++filename_begin; - m_filename.SetString((filename_begin == llvm::StringRef::npos || filename_begin >= resolve_path_ref.size()) - ? "." - : resolve_path_ref.substr(filename_begin)); + size_t filename_begin = dir_end; + size_t root_dir_start = RootDirStart(resolve_path_ref, syntax); + while (filename_begin != llvm::StringRef::npos && + filename_begin < resolve_path_ref.size() && + filename_begin != root_dir_start && + IsPathSeparator(resolve_path_ref[filename_begin], syntax)) + ++filename_begin; + m_filename.SetString((filename_begin == llvm::StringRef::npos || + filename_begin >= resolve_path_ref.size()) + ? "." + : resolve_path_ref.substr(filename_begin)); } -void -FileSpec::SetFile(const char *pathname, bool resolve, ArchSpec arch) -{ - return SetFile(pathname, resolve, - arch.GetTriple().isOSWindows() - ? ePathSyntaxWindows - : ePathSyntaxPosix); +void FileSpec::SetFile(const char *pathname, bool resolve, ArchSpec arch) { + return SetFile(pathname, resolve, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix); } -void -FileSpec::SetFile(const std::string &pathname, bool resolve, PathSyntax syntax) -{ - return SetFile(pathname.c_str(), resolve, syntax); +void FileSpec::SetFile(const std::string &pathname, bool resolve, + PathSyntax syntax) { + return SetFile(pathname.c_str(), resolve, syntax); } -void -FileSpec::SetFile(const std::string &pathname, bool resolve, ArchSpec arch) -{ - return SetFile(pathname.c_str(), resolve, arch); +void FileSpec::SetFile(const std::string &pathname, bool resolve, + ArchSpec arch) { + return SetFile(pathname.c_str(), resolve, arch); } //---------------------------------------------------------------------- @@ -458,10 +405,7 @@ FileSpec::SetFile(const std::string &pathname, bool resolve, ArchSpec arch) // if (file_spec) // {} //---------------------------------------------------------------------- -FileSpec::operator bool() const -{ - return m_filename || m_directory; -} +FileSpec::operator bool() const { return m_filename || m_directory; } //---------------------------------------------------------------------- // Logical NOT operator. This allows code to check any FileSpec @@ -470,123 +414,96 @@ FileSpec::operator bool() const // if (!file_spec) // {} //---------------------------------------------------------------------- -bool -FileSpec::operator!() const -{ - return !m_directory && !m_filename; -} +bool FileSpec::operator!() const { return !m_directory && !m_filename; } -bool -FileSpec::DirectoryEquals(const FileSpec &rhs) const -{ - const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); - return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive); +bool FileSpec::DirectoryEquals(const FileSpec &rhs) const { + const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); + return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive); } -bool -FileSpec::FileEquals(const FileSpec &rhs) const -{ - const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); - return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive); +bool FileSpec::FileEquals(const FileSpec &rhs) const { + const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive(); + return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive); } //------------------------------------------------------------------ // Equal to operator //------------------------------------------------------------------ -bool -FileSpec::operator== (const FileSpec& rhs) const -{ - if (!FileEquals(rhs)) - return false; - if (DirectoryEquals(rhs)) - return true; - - // TODO: determine if we want to keep this code in here. - // The code below was added to handle a case where we were - // trying to set a file and line breakpoint and one path - // was resolved, and the other not and the directory was - // in a mount point that resolved to a more complete path: - // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling - // this out... - if (IsResolved() && rhs.IsResolved()) - { - // Both paths are resolved, no need to look further... - return false; - } - - FileSpec resolved_lhs(*this); - - // If "this" isn't resolved, resolve it - if (!IsResolved()) - { - if (resolved_lhs.ResolvePath()) - { - // This path wasn't resolved but now it is. Check if the resolved - // directory is the same as our unresolved directory, and if so, - // we can mark this object as resolved to avoid more future resolves - m_is_resolved = (m_directory == resolved_lhs.m_directory); - } - else - return false; - } - - FileSpec resolved_rhs(rhs); - if (!rhs.IsResolved()) - { - if (resolved_rhs.ResolvePath()) - { - // rhs's path wasn't resolved but now it is. Check if the resolved - // directory is the same as rhs's unresolved directory, and if so, - // we can mark this object as resolved to avoid more future resolves - rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory); - } - else - return false; - } - - // If we reach this point in the code we were able to resolve both paths - // and since we only resolve the paths if the basenames are equal, then - // we can just check if both directories are equal... - return DirectoryEquals(rhs); +bool FileSpec::operator==(const FileSpec &rhs) const { + if (!FileEquals(rhs)) + return false; + if (DirectoryEquals(rhs)) + return true; + + // TODO: determine if we want to keep this code in here. + // The code below was added to handle a case where we were + // trying to set a file and line breakpoint and one path + // was resolved, and the other not and the directory was + // in a mount point that resolved to a more complete path: + // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling + // this out... + if (IsResolved() && rhs.IsResolved()) { + // Both paths are resolved, no need to look further... + return false; + } + + FileSpec resolved_lhs(*this); + + // If "this" isn't resolved, resolve it + if (!IsResolved()) { + if (resolved_lhs.ResolvePath()) { + // This path wasn't resolved but now it is. Check if the resolved + // directory is the same as our unresolved directory, and if so, + // we can mark this object as resolved to avoid more future resolves + m_is_resolved = (m_directory == resolved_lhs.m_directory); + } else + return false; + } + + FileSpec resolved_rhs(rhs); + if (!rhs.IsResolved()) { + if (resolved_rhs.ResolvePath()) { + // rhs's path wasn't resolved but now it is. Check if the resolved + // directory is the same as rhs's unresolved directory, and if so, + // we can mark this object as resolved to avoid more future resolves + rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory); + } else + return false; + } + + // If we reach this point in the code we were able to resolve both paths + // and since we only resolve the paths if the basenames are equal, then + // we can just check if both directories are equal... + return DirectoryEquals(rhs); } //------------------------------------------------------------------ // Not equal to operator //------------------------------------------------------------------ -bool -FileSpec::operator!= (const FileSpec& rhs) const -{ - return !(*this == rhs); -} +bool FileSpec::operator!=(const FileSpec &rhs) const { return !(*this == rhs); } //------------------------------------------------------------------ // Less than operator //------------------------------------------------------------------ -bool -FileSpec::operator< (const FileSpec& rhs) const -{ - return FileSpec::Compare(*this, rhs, true) < 0; +bool FileSpec::operator<(const FileSpec &rhs) const { + return FileSpec::Compare(*this, rhs, true) < 0; } //------------------------------------------------------------------ // Dump a FileSpec object to a stream //------------------------------------------------------------------ -Stream& -lldb_private::operator << (Stream &s, const FileSpec& f) -{ - f.Dump(&s); - return s; +Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) { + f.Dump(&s); + return s; } //------------------------------------------------------------------ // Clear this object by releasing both the directory and filename // string values and making them both the empty string. //------------------------------------------------------------------ -void -FileSpec::Clear() -{ - m_directory.Clear(); - m_filename.Clear(); +void FileSpec::Clear() { + m_directory.Clear(); + m_filename.Clear(); } //------------------------------------------------------------------ @@ -600,166 +517,148 @@ FileSpec::Clear() // Return -1 if the "a" is less than "b", 0 if "a" is equal to "b" // and "1" if "a" is greater than "b". //------------------------------------------------------------------ -int -FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full) -{ - int result = 0; - - // case sensitivity of compare - const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - - // If full is true, then we must compare both the directory and filename. - - // If full is false, then if either directory is empty, then we match on - // the basename only, and if both directories have valid values, we still - // do a full compare. This allows for matching when we just have a filename - // in one of the FileSpec objects. - - if (full || (a.m_directory && b.m_directory)) - { - result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive); - if (result) - return result; - } - return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive); -} - -bool -FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full, bool remove_backups) -{ - // case sensitivity of equality test - const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); - - if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) - return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive); - else if (remove_backups == false) - return a == b; - else - { - if (!ConstString::Equals(a.m_filename, b.m_filename, case_sensitive)) - return false; - if (ConstString::Equals(a.m_directory, b.m_directory, case_sensitive)) - return true; - ConstString a_without_dots; - ConstString b_without_dots; +int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) { + int result = 0; + + // case sensitivity of compare + const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); + + // If full is true, then we must compare both the directory and filename. + + // If full is false, then if either directory is empty, then we match on + // the basename only, and if both directories have valid values, we still + // do a full compare. This allows for matching when we just have a filename + // in one of the FileSpec objects. + + if (full || (a.m_directory && b.m_directory)) { + result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive); + if (result) + return result; + } + return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive); +} + +bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full, + bool remove_backups) { + // case sensitivity of equality test + const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive(); + + if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) + return ConstString::Equals(a.m_filename, b.m_filename, case_sensitive); + else if (remove_backups == false) + return a == b; + else { + if (!ConstString::Equals(a.m_filename, b.m_filename, case_sensitive)) + return false; + if (ConstString::Equals(a.m_directory, b.m_directory, case_sensitive)) + return true; + ConstString a_without_dots; + ConstString b_without_dots; + + RemoveBackupDots(a.m_directory, a_without_dots); + RemoveBackupDots(b.m_directory, b_without_dots); + return ConstString::Equals(a_without_dots, b_without_dots, case_sensitive); + } +} + +void FileSpec::NormalizePath() { + ConstString normalized_directory; + FileSpec::RemoveBackupDots(m_directory, normalized_directory); + m_directory = normalized_directory; +} + +void FileSpec::RemoveBackupDots(const ConstString &input_const_str, + ConstString &result_const_str) { + const char *input = input_const_str.GetCString(); + result_const_str.Clear(); + if (!input || input[0] == '\0') + return; - RemoveBackupDots (a.m_directory, a_without_dots); - RemoveBackupDots (b.m_directory, b_without_dots); - return ConstString::Equals(a_without_dots, b_without_dots, case_sensitive); + const char win_sep = '\\'; + const char unix_sep = '/'; + char found_sep; + const char *win_backup = "\\.."; + const char *unix_backup = "/.."; + + bool is_win = false; + + // Determine the platform for the path (win or unix): + + if (input[0] == win_sep) + is_win = true; + else if (input[0] == unix_sep) + is_win = false; + else if (input[1] == ':') + is_win = true; + else if (strchr(input, unix_sep) != nullptr) + is_win = false; + else if (strchr(input, win_sep) != nullptr) + is_win = true; + else { + // No separators at all, no reason to do any work here. + result_const_str = input_const_str; + return; + } + + llvm::StringRef backup_sep; + if (is_win) { + found_sep = win_sep; + backup_sep = win_backup; + } else { + found_sep = unix_sep; + backup_sep = unix_backup; + } + + llvm::StringRef input_ref(input); + llvm::StringRef curpos(input); + + bool had_dots = false; + std::string result; + + while (1) { + // Start of loop + llvm::StringRef before_sep; + std::pair<llvm::StringRef, llvm::StringRef> around_sep = + curpos.split(backup_sep); + + before_sep = around_sep.first; + curpos = around_sep.second; + + if (curpos.empty()) { + if (had_dots) { + while (before_sep.startswith("//")) + before_sep = before_sep.substr(1); + if (!before_sep.empty()) { + result.append(before_sep.data(), before_sep.size()); + } + } + break; } -} - -void -FileSpec::NormalizePath () -{ - ConstString normalized_directory; - FileSpec::RemoveBackupDots(m_directory, normalized_directory); - m_directory = normalized_directory; -} + had_dots = true; -void -FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str) -{ - const char *input = input_const_str.GetCString(); - result_const_str.Clear(); - if (!input || input[0] == '\0') - return; + unsigned num_backups = 1; + while (curpos.startswith(backup_sep)) { + num_backups++; + curpos = curpos.slice(backup_sep.size(), curpos.size()); + } - const char win_sep = '\\'; - const char unix_sep = '/'; - char found_sep; - const char *win_backup = "\\.."; - const char *unix_backup = "/.."; - - bool is_win = false; - - // Determine the platform for the path (win or unix): - - if (input[0] == win_sep) - is_win = true; - else if (input[0] == unix_sep) - is_win = false; - else if (input[1] == ':') - is_win = true; - else if (strchr(input, unix_sep) != nullptr) - is_win = false; - else if (strchr(input, win_sep) != nullptr) - is_win = true; - else - { - // No separators at all, no reason to do any work here. + size_t end_pos = before_sep.size(); + while (num_backups-- > 0) { + end_pos = before_sep.rfind(found_sep, end_pos); + if (end_pos == llvm::StringRef::npos) { result_const_str = input_const_str; return; + } } + result.append(before_sep.data(), end_pos); + } - llvm::StringRef backup_sep; - if (is_win) - { - found_sep = win_sep; - backup_sep = win_backup; - } - else - { - found_sep = unix_sep; - backup_sep = unix_backup; - } - - llvm::StringRef input_ref(input); - llvm::StringRef curpos(input); - - bool had_dots = false; - std::string result; - - while (1) - { - // Start of loop - llvm::StringRef before_sep; - std::pair<llvm::StringRef, llvm::StringRef> around_sep = curpos.split(backup_sep); - - before_sep = around_sep.first; - curpos = around_sep.second; - - if (curpos.empty()) - { - if (had_dots) - { - while (before_sep.startswith("//")) - before_sep = before_sep.substr(1); - if (!before_sep.empty()) - { - result.append(before_sep.data(), before_sep.size()); - } - } - break; - } - had_dots = true; - - unsigned num_backups = 1; - while (curpos.startswith(backup_sep)) - { - num_backups++; - curpos = curpos.slice(backup_sep.size(), curpos.size()); - } - - size_t end_pos = before_sep.size(); - while (num_backups-- > 0) - { - end_pos = before_sep.rfind(found_sep, end_pos); - if (end_pos == llvm::StringRef::npos) - { - result_const_str = input_const_str; - return; - } - } - result.append(before_sep.data(), end_pos); - } + if (had_dots) + result_const_str.SetCString(result.c_str()); + else + result_const_str = input_const_str; - if (had_dots) - result_const_str.SetCString(result.c_str()); - else - result_const_str = input_const_str; - - return; + return; } //------------------------------------------------------------------ @@ -767,279 +666,230 @@ FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &res // a valid directory name, it will be displayed followed by a // directory delimiter, and the filename. //------------------------------------------------------------------ -void -FileSpec::Dump(Stream *s) const -{ - if (s) - { - std::string path{GetPath(true)}; - s->PutCString(path.c_str()); - char path_separator = GetPrefferedPathSeparator(m_syntax); - if (!m_filename && !path.empty() && path.back() != path_separator) - s->PutChar(path_separator); - } +void FileSpec::Dump(Stream *s) const { + if (s) { + std::string path{GetPath(true)}; + s->PutCString(path.c_str()); + char path_separator = GetPrefferedPathSeparator(m_syntax); + if (!m_filename && !path.empty() && path.back() != path_separator) + s->PutChar(path_separator); + } } //------------------------------------------------------------------ // Returns true if the file exists. //------------------------------------------------------------------ -bool -FileSpec::Exists () const -{ - struct stat file_stats; - return GetFileStats (this, &file_stats); -} - -bool -FileSpec::Readable () const -{ - const uint32_t permissions = GetPermissions(); - if (permissions & eFilePermissionsEveryoneR) - return true; - return false; -} - -bool -FileSpec::ResolveExecutableLocation () -{ - if (!m_directory) - { - const char *file_cstr = m_filename.GetCString(); - if (file_cstr) - { - const std::string file_str (file_cstr); - llvm::ErrorOr<std::string> error_or_path = llvm::sys::findProgramByName (file_str); - if (!error_or_path) - return false; - std::string path = error_or_path.get(); - llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); - if (!dir_ref.empty()) - { - // FindProgramByName returns "." if it can't find the file. - if (strcmp (".", dir_ref.data()) == 0) - return false; - - m_directory.SetCString (dir_ref.data()); - if (Exists()) - return true; - else - { - // If FindProgramByName found the file, it returns the directory + filename in its return results. - // We need to separate them. - FileSpec tmp_file (dir_ref.data(), false); - if (tmp_file.Exists()) - { - m_directory = tmp_file.m_directory; - return true; - } - } - } +bool FileSpec::Exists() const { + struct stat file_stats; + return GetFileStats(this, &file_stats); +} + +bool FileSpec::Readable() const { + const uint32_t permissions = GetPermissions(); + if (permissions & eFilePermissionsEveryoneR) + return true; + return false; +} + +bool FileSpec::ResolveExecutableLocation() { + if (!m_directory) { + const char *file_cstr = m_filename.GetCString(); + if (file_cstr) { + const std::string file_str(file_cstr); + llvm::ErrorOr<std::string> error_or_path = + llvm::sys::findProgramByName(file_str); + if (!error_or_path) + return false; + std::string path = error_or_path.get(); + llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); + if (!dir_ref.empty()) { + // FindProgramByName returns "." if it can't find the file. + if (strcmp(".", dir_ref.data()) == 0) + return false; + + m_directory.SetCString(dir_ref.data()); + if (Exists()) + return true; + else { + // If FindProgramByName found the file, it returns the directory + + // filename in its return results. + // We need to separate them. + FileSpec tmp_file(dir_ref.data(), false); + if (tmp_file.Exists()) { + m_directory = tmp_file.m_directory; + return true; + } } + } } - - return false; + } + + return false; } -bool -FileSpec::ResolvePath () -{ - if (m_is_resolved) - return true; // We have already resolved this path +bool FileSpec::ResolvePath() { + if (m_is_resolved) + return true; // We have already resolved this path - char path_buf[PATH_MAX]; - if (!GetPath (path_buf, PATH_MAX, false)) - return false; - // SetFile(...) will set m_is_resolved correctly if it can resolve the path - SetFile (path_buf, true); - return m_is_resolved; + char path_buf[PATH_MAX]; + if (!GetPath(path_buf, PATH_MAX, false)) + return false; + // SetFile(...) will set m_is_resolved correctly if it can resolve the path + SetFile(path_buf, true); + return m_is_resolved; } -uint64_t -FileSpec::GetByteSize() const -{ - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - return file_stats.st_size; - return 0; +uint64_t FileSpec::GetByteSize() const { + struct stat file_stats; + if (GetFileStats(this, &file_stats)) + return file_stats.st_size; + return 0; } -FileSpec::PathSyntax -FileSpec::GetPathSyntax() const -{ - return m_syntax; -} +FileSpec::PathSyntax FileSpec::GetPathSyntax() const { return m_syntax; } -FileSpec::FileType -FileSpec::GetFileType () const -{ - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - { - mode_t file_type = file_stats.st_mode & S_IFMT; - switch (file_type) - { - case S_IFDIR: return eFileTypeDirectory; - case S_IFREG: return eFileTypeRegular; +FileSpec::FileType FileSpec::GetFileType() const { + struct stat file_stats; + if (GetFileStats(this, &file_stats)) { + mode_t file_type = file_stats.st_mode & S_IFMT; + switch (file_type) { + case S_IFDIR: + return eFileTypeDirectory; + case S_IFREG: + return eFileTypeRegular; #ifndef _WIN32 - case S_IFIFO: return eFileTypePipe; - case S_IFSOCK: return eFileTypeSocket; - case S_IFLNK: return eFileTypeSymbolicLink; + case S_IFIFO: + return eFileTypePipe; + case S_IFSOCK: + return eFileTypeSocket; + case S_IFLNK: + return eFileTypeSymbolicLink; #endif - default: - break; - } - return eFileTypeUnknown; + default: + break; } - return eFileTypeInvalid; + return eFileTypeUnknown; + } + return eFileTypeInvalid; } -bool -FileSpec::IsSymbolicLink () const -{ - char resolved_path[PATH_MAX]; - if (!GetPath (resolved_path, sizeof (resolved_path))) - return false; +bool FileSpec::IsSymbolicLink() const { + char resolved_path[PATH_MAX]; + if (!GetPath(resolved_path, sizeof(resolved_path))) + return false; #ifdef _WIN32 - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(resolved_path, wpath)) - return false; - auto attrs = ::GetFileAttributesW(wpath.c_str()); - if (attrs == INVALID_FILE_ATTRIBUTES) - return false; + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(resolved_path, wpath)) + return false; + auto attrs = ::GetFileAttributesW(wpath.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) + return false; - return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); + return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); #else - struct stat file_stats; - if (::lstat (resolved_path, &file_stats) != 0) - return false; + struct stat file_stats; + if (::lstat(resolved_path, &file_stats) != 0) + return false; - return (file_stats.st_mode & S_IFMT) == S_IFLNK; + return (file_stats.st_mode & S_IFMT) == S_IFLNK; #endif } -uint32_t -FileSpec::GetPermissions () const -{ - uint32_t file_permissions = 0; - if (*this) - FileSystem::GetFilePermissions(*this, file_permissions); - return file_permissions; +uint32_t FileSpec::GetPermissions() const { + uint32_t file_permissions = 0; + if (*this) + FileSystem::GetFilePermissions(*this, file_permissions); + return file_permissions; } -TimeValue -FileSpec::GetModificationTime () const -{ - TimeValue mod_time; - struct stat file_stats; - if (GetFileStats (this, &file_stats)) - mod_time.OffsetWithSeconds(file_stats.st_mtime); - return mod_time; +TimeValue FileSpec::GetModificationTime() const { + TimeValue mod_time; + struct stat file_stats; + if (GetFileStats(this, &file_stats)) + mod_time.OffsetWithSeconds(file_stats.st_mtime); + return mod_time; } //------------------------------------------------------------------ // Directory string get accessor. //------------------------------------------------------------------ -ConstString & -FileSpec::GetDirectory() -{ - return m_directory; -} +ConstString &FileSpec::GetDirectory() { return m_directory; } //------------------------------------------------------------------ // Directory string const get accessor. //------------------------------------------------------------------ -const ConstString & -FileSpec::GetDirectory() const -{ - return m_directory; -} +const ConstString &FileSpec::GetDirectory() const { return m_directory; } //------------------------------------------------------------------ // Filename string get accessor. //------------------------------------------------------------------ -ConstString & -FileSpec::GetFilename() -{ - return m_filename; -} +ConstString &FileSpec::GetFilename() { return m_filename; } //------------------------------------------------------------------ // Filename string const get accessor. //------------------------------------------------------------------ -const ConstString & -FileSpec::GetFilename() const -{ - return m_filename; -} +const ConstString &FileSpec::GetFilename() const { return m_filename; } //------------------------------------------------------------------ // Extract the directory and path into a fixed buffer. This is // needed as the directory and path are stored in separate string // values. //------------------------------------------------------------------ -size_t -FileSpec::GetPath(char *path, size_t path_max_len, bool denormalize) const -{ - if (!path) - return 0; - - std::string result = GetPath(denormalize); - ::snprintf(path, path_max_len, "%s", result.c_str()); - return std::min(path_max_len-1, result.length()); -} - -std::string -FileSpec::GetPath(bool denormalize) const -{ - llvm::SmallString<64> result; - GetPath(result, denormalize); - return std::string(result.begin(), result.end()); -} - -const char * -FileSpec::GetCString(bool denormalize) const -{ - return ConstString{GetPath(denormalize)}.AsCString(NULL); -} - -void -FileSpec::GetPath(llvm::SmallVectorImpl<char> &path, bool denormalize) const -{ - path.append(m_directory.GetStringRef().begin(), m_directory.GetStringRef().end()); - if (m_directory && m_filename && !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) - path.insert(path.end(), GetPrefferedPathSeparator(m_syntax)); - path.append(m_filename.GetStringRef().begin(), m_filename.GetStringRef().end()); - Normalize(path, m_syntax); - if (denormalize && !path.empty()) - Denormalize(path, m_syntax); -} - -ConstString -FileSpec::GetFileNameExtension () const -{ - if (m_filename) - { - const char *filename = m_filename.GetCString(); - const char* dot_pos = strrchr(filename, '.'); - if (dot_pos && dot_pos[1] != '\0') - return ConstString(dot_pos+1); - } - return ConstString(); +size_t FileSpec::GetPath(char *path, size_t path_max_len, + bool denormalize) const { + if (!path) + return 0; + + std::string result = GetPath(denormalize); + ::snprintf(path, path_max_len, "%s", result.c_str()); + return std::min(path_max_len - 1, result.length()); } -ConstString -FileSpec::GetFileNameStrippingExtension () const -{ +std::string FileSpec::GetPath(bool denormalize) const { + llvm::SmallString<64> result; + GetPath(result, denormalize); + return std::string(result.begin(), result.end()); +} + +const char *FileSpec::GetCString(bool denormalize) const { + return ConstString{GetPath(denormalize)}.AsCString(NULL); +} + +void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path, + bool denormalize) const { + path.append(m_directory.GetStringRef().begin(), + m_directory.GetStringRef().end()); + if (m_directory && m_filename && + !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) + path.insert(path.end(), GetPrefferedPathSeparator(m_syntax)); + path.append(m_filename.GetStringRef().begin(), + m_filename.GetStringRef().end()); + Normalize(path, m_syntax); + if (denormalize && !path.empty()) + Denormalize(path, m_syntax); +} + +ConstString FileSpec::GetFileNameExtension() const { + if (m_filename) { const char *filename = m_filename.GetCString(); - if (filename == NULL) - return ConstString(); - - const char* dot_pos = strrchr(filename, '.'); - if (dot_pos == NULL) - return m_filename; - - return ConstString(filename, dot_pos-filename); + const char *dot_pos = strrchr(filename, '.'); + if (dot_pos && dot_pos[1] != '\0') + return ConstString(dot_pos + 1); + } + return ConstString(); +} + +ConstString FileSpec::GetFileNameStrippingExtension() const { + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + const char *dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return m_filename; + + return ConstString(filename, dot_pos - filename); } //------------------------------------------------------------------ @@ -1053,66 +903,56 @@ FileSpec::GetFileNameStrippingExtension () const // truncated. The final number of bytes that get mapped can be // verified using the DataBuffer::GetByteSize() function. //------------------------------------------------------------------ -DataBufferSP -FileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const -{ - DataBufferSP data_sp; - std::unique_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap()); - if (mmap_data.get()) - { - const size_t mapped_length = mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size); - if (((file_size == SIZE_MAX) && (mapped_length > 0)) || (mapped_length >= file_size)) - data_sp.reset(mmap_data.release()); - } - return data_sp; -} - -DataBufferSP -FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, size_t file_size) const -{ - if (FileSystem::IsLocal(*this)) - return MemoryMapFileContents(file_offset, file_size); - else - return ReadFileContents(file_offset, file_size, NULL); +DataBufferSP FileSpec::MemoryMapFileContents(off_t file_offset, + size_t file_size) const { + DataBufferSP data_sp; + std::unique_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap()); + if (mmap_data.get()) { + const size_t mapped_length = + mmap_data->MemoryMapFromFileSpec(this, file_offset, file_size); + if (((file_size == SIZE_MAX) && (mapped_length > 0)) || + (mapped_length >= file_size)) + data_sp.reset(mmap_data.release()); + } + return data_sp; +} + +DataBufferSP FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, + size_t file_size) const { + if (FileSystem::IsLocal(*this)) + return MemoryMapFileContents(file_offset, file_size); + else + return ReadFileContents(file_offset, file_size, NULL); } - //------------------------------------------------------------------ // Return the size in bytes that this object takes in memory. This // returns the size in bytes of this object, not any shared string // values it may refer to. //------------------------------------------------------------------ -size_t -FileSpec::MemorySize() const -{ - return m_filename.MemorySize() + m_directory.MemorySize(); -} - - -size_t -FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const -{ - Error error; - size_t bytes_read = 0; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - off_t file_offset_after_seek = file_offset; - bytes_read = dst_len; - error = file.Read(dst, bytes_read, file_offset_after_seek); - } - } - else - { - error.SetErrorString("invalid file specification"); +size_t FileSpec::MemorySize() const { + return m_filename.MemorySize() + m_directory.MemorySize(); +} + +size_t FileSpec::ReadFileContents(off_t file_offset, void *dst, size_t dst_len, + Error *error_ptr) const { + Error error; + size_t bytes_read = 0; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + off_t file_offset_after_seek = file_offset; + bytes_read = dst_len; + error = file.Read(dst, bytes_read, file_offset_after_seek); } - if (error_ptr) - *error_ptr = error; - return bytes_read; + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return bytes_read; } //------------------------------------------------------------------ @@ -1126,489 +966,450 @@ FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error // truncated. The final number of bytes that get mapped can be // verified using the DataBuffer::GetByteSize() function. //------------------------------------------------------------------ -DataBufferSP -FileSpec::ReadFileContents (off_t file_offset, size_t file_size, Error *error_ptr) const -{ - Error error; - DataBufferSP data_sp; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - const bool null_terminate = false; - error = file.Read (file_size, file_offset, null_terminate, data_sp); - } - } - else - { - error.SetErrorString("invalid file specification"); - } - if (error_ptr) - *error_ptr = error; - return data_sp; -} - -DataBufferSP -FileSpec::ReadFileContentsAsCString(Error *error_ptr) -{ - Error error; - DataBufferSP data_sp; - char resolved_path[PATH_MAX]; - if (GetPath(resolved_path, sizeof(resolved_path))) - { - File file; - error = file.Open(resolved_path, File::eOpenOptionRead); - if (error.Success()) - { - off_t offset = 0; - size_t length = SIZE_MAX; - const bool null_terminate = true; - error = file.Read (length, offset, null_terminate, data_sp); - } +DataBufferSP FileSpec::ReadFileContents(off_t file_offset, size_t file_size, + Error *error_ptr) const { + Error error; + DataBufferSP data_sp; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + const bool null_terminate = false; + error = file.Read(file_size, file_offset, null_terminate, data_sp); } - else - { - error.SetErrorString("invalid file specification"); + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return data_sp; +} + +DataBufferSP FileSpec::ReadFileContentsAsCString(Error *error_ptr) { + Error error; + DataBufferSP data_sp; + char resolved_path[PATH_MAX]; + if (GetPath(resolved_path, sizeof(resolved_path))) { + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { + off_t offset = 0; + size_t length = SIZE_MAX; + const bool null_terminate = true; + error = file.Read(length, offset, null_terminate, data_sp); } - if (error_ptr) - *error_ptr = error; - return data_sp; -} - -size_t -FileSpec::ReadFileLines (STLStringArray &lines) -{ - lines.clear(); - char path[PATH_MAX]; - if (GetPath(path, sizeof(path))) - { - std::ifstream file_stream (path); - - if (file_stream) - { - std::string line; - while (getline (file_stream, line)) - lines.push_back (line); - } + } else { + error.SetErrorString("invalid file specification"); + } + if (error_ptr) + *error_ptr = error; + return data_sp; +} + +size_t FileSpec::ReadFileLines(STLStringArray &lines) { + lines.clear(); + char path[PATH_MAX]; + if (GetPath(path, sizeof(path))) { + std::ifstream file_stream(path); + + if (file_stream) { + std::string line; + while (getline(file_stream, line)) + lines.push_back(line); } - return lines.size(); + } + return lines.size(); } FileSpec::EnumerateDirectoryResult -FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const &callback) -{ - if (dir_path && dir_path[0]) - { +FileSpec::ForEachItemInDirectory(const char *dir_path, + DirectoryCallback const &callback) { + if (dir_path && dir_path[0]) { #ifdef _WIN32 - std::string szDir(dir_path); - szDir += "\\*"; + std::string szDir(dir_path); + szDir += "\\*"; - std::wstring wszDir; - if (!llvm::ConvertUTF8toWide(szDir, wszDir)) - { - return eEnumerateDirectoryResultNext; - } + std::wstring wszDir; + if (!llvm::ConvertUTF8toWide(szDir, wszDir)) { + return eEnumerateDirectoryResultNext; + } - WIN32_FIND_DATAW ffd; - HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd); + WIN32_FIND_DATAW ffd; + HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd); - if (hFind == INVALID_HANDLE_VALUE) - { - return eEnumerateDirectoryResultNext; - } + if (hFind == INVALID_HANDLE_VALUE) { + return eEnumerateDirectoryResultNext; + } - do - { - FileSpec::FileType file_type = eFileTypeUnknown; - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - size_t len = wcslen(ffd.cFileName); + do { + FileSpec::FileType file_type = eFileTypeUnknown; + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + size_t len = wcslen(ffd.cFileName); + + if (len == 1 && ffd.cFileName[0] == L'.') + continue; + + if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.') + continue; + + file_type = eFileTypeDirectory; + } else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { + file_type = eFileTypeOther; + } else { + file_type = eFileTypeRegular; + } + + std::string fileName; + if (!llvm::convertWideToUTF8(ffd.cFileName, fileName)) { + continue; + } + + std::vector<char> child_path(PATH_MAX); + const int child_path_len = + ::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, + fileName.c_str()); + if (child_path_len < (int)(child_path.size() - 1)) { + // Don't resolve the file type or path + FileSpec child_path_spec(child_path.data(), false); + + EnumerateDirectoryResult result = callback(file_type, child_path_spec); + + switch (result) { + case eEnumerateDirectoryResultNext: + // Enumerate next entry in the current directory. We just + // exit this switch and will continue enumerating the + // current directory as we currently are... + break; + + case eEnumerateDirectoryResultEnter: // Recurse into the current entry + // if it is a directory or symlink, + // or next if not + if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == + eEnumerateDirectoryResultQuit) { + // The subdirectory returned Quit, which means to + // stop all directory enumerations at all levels. + return eEnumerateDirectoryResultQuit; + } + break; + + case eEnumerateDirectoryResultExit: // Exit from the current directory + // at the current level. + // Exit from this directory level and tell parent to + // keep enumerating. + return eEnumerateDirectoryResultNext; + + case eEnumerateDirectoryResultQuit: // Stop directory enumerations at + // any level + return eEnumerateDirectoryResultQuit; + } + } + } while (FindNextFileW(hFind, &ffd) != 0); - if (len == 1 && ffd.cFileName[0] == L'.') - continue; + FindClose(hFind); +#else + lldb_utility::CleanUp<DIR *, int> dir_path_dir(opendir(dir_path), NULL, + closedir); + if (dir_path_dir.is_valid()) { + char dir_path_last_char = dir_path[strlen(dir_path) - 1]; + + long path_max = fpathconf(dirfd(dir_path_dir.get()), _PC_NAME_MAX); +#if defined(__APPLE_) && defined(__DARWIN_MAXPATHLEN) + if (path_max < __DARWIN_MAXPATHLEN) + path_max = __DARWIN_MAXPATHLEN; +#endif + struct dirent *buf, *dp; + buf = (struct dirent *)malloc(offsetof(struct dirent, d_name) + path_max + + 1); - if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.') - continue; + while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp) { + // Only search directories + if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) { + size_t len = strlen(dp->d_name); - file_type = eFileTypeDirectory; - } - else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) - { - file_type = eFileTypeOther; - } - else - { - file_type = eFileTypeRegular; - } + if (len == 1 && dp->d_name[0] == '.') + continue; - std::string fileName; - if (!llvm::convertWideToUTF8(ffd.cFileName, fileName)) - { - continue; - } + if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') + continue; + } - std::vector<char> child_path(PATH_MAX); - const int child_path_len = - ::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, fileName.c_str()); - if (child_path_len < (int)(child_path.size() - 1)) - { - // Don't resolve the file type or path - FileSpec child_path_spec(child_path.data(), false); - - EnumerateDirectoryResult result = callback (file_type, child_path_spec); - - switch (result) - { - case eEnumerateDirectoryResultNext: - // Enumerate next entry in the current directory. We just - // exit this switch and will continue enumerating the - // current directory as we currently are... - break; - - case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not - if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == - eEnumerateDirectoryResultQuit) - { - // The subdirectory returned Quit, which means to - // stop all directory enumerations at all levels. - return eEnumerateDirectoryResultQuit; - } - break; - - case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level. - // Exit from this directory level and tell parent to - // keep enumerating. - return eEnumerateDirectoryResultNext; - - case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level - return eEnumerateDirectoryResultQuit; - } - } - } while (FindNextFileW(hFind, &ffd) != 0); + FileSpec::FileType file_type = eFileTypeUnknown; - FindClose(hFind); -#else - lldb_utility::CleanUp <DIR *, int> dir_path_dir(opendir(dir_path), NULL, closedir); - if (dir_path_dir.is_valid()) - { - char dir_path_last_char = dir_path[strlen(dir_path) - 1]; - - long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX); -#if defined (__APPLE_) && defined (__DARWIN_MAXPATHLEN) - if (path_max < __DARWIN_MAXPATHLEN) - path_max = __DARWIN_MAXPATHLEN; -#endif - struct dirent *buf, *dp; - buf = (struct dirent *) malloc (offsetof (struct dirent, d_name) + path_max + 1); - - while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp) - { - // Only search directories - if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) - { - size_t len = strlen(dp->d_name); - - if (len == 1 && dp->d_name[0] == '.') - continue; - - if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') - continue; - } - - FileSpec::FileType file_type = eFileTypeUnknown; - - switch (dp->d_type) - { - default: - case DT_UNKNOWN: file_type = eFileTypeUnknown; break; - case DT_FIFO: file_type = eFileTypePipe; break; - case DT_CHR: file_type = eFileTypeOther; break; - case DT_DIR: file_type = eFileTypeDirectory; break; - case DT_BLK: file_type = eFileTypeOther; break; - case DT_REG: file_type = eFileTypeRegular; break; - case DT_LNK: file_type = eFileTypeSymbolicLink; break; - case DT_SOCK: file_type = eFileTypeSocket; break; + switch (dp->d_type) { + default: + case DT_UNKNOWN: + file_type = eFileTypeUnknown; + break; + case DT_FIFO: + file_type = eFileTypePipe; + break; + case DT_CHR: + file_type = eFileTypeOther; + break; + case DT_DIR: + file_type = eFileTypeDirectory; + break; + case DT_BLK: + file_type = eFileTypeOther; + break; + case DT_REG: + file_type = eFileTypeRegular; + break; + case DT_LNK: + file_type = eFileTypeSymbolicLink; + break; + case DT_SOCK: + file_type = eFileTypeSocket; + break; #if !defined(__OpenBSD__) - case DT_WHT: file_type = eFileTypeOther; break; + case DT_WHT: + file_type = eFileTypeOther; + break; #endif - } - - char child_path[PATH_MAX]; - - // Don't make paths with "/foo//bar", that just confuses everybody. - int child_path_len; - if (dir_path_last_char == '/') - child_path_len = ::snprintf (child_path, sizeof(child_path), "%s%s", dir_path, dp->d_name); - else - child_path_len = ::snprintf (child_path, sizeof(child_path), "%s/%s", dir_path, dp->d_name); - - if (child_path_len < (int)(sizeof(child_path) - 1)) - { - // Don't resolve the file type or path - FileSpec child_path_spec (child_path, false); - - EnumerateDirectoryResult result = callback (file_type, child_path_spec); - - switch (result) - { - case eEnumerateDirectoryResultNext: - // Enumerate next entry in the current directory. We just - // exit this switch and will continue enumerating the - // current directory as we currently are... - break; - - case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not - if (FileSpec::ForEachItemInDirectory (child_path, callback) == eEnumerateDirectoryResultQuit) - { - // The subdirectory returned Quit, which means to - // stop all directory enumerations at all levels. - if (buf) - free (buf); - return eEnumerateDirectoryResultQuit; - } - break; - - case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level. - // Exit from this directory level and tell parent to - // keep enumerating. - if (buf) - free (buf); - return eEnumerateDirectoryResultNext; - - case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level - if (buf) - free (buf); - return eEnumerateDirectoryResultQuit; - } - } + } + + char child_path[PATH_MAX]; + + // Don't make paths with "/foo//bar", that just confuses everybody. + int child_path_len; + if (dir_path_last_char == '/') + child_path_len = ::snprintf(child_path, sizeof(child_path), "%s%s", + dir_path, dp->d_name); + else + child_path_len = ::snprintf(child_path, sizeof(child_path), "%s/%s", + dir_path, dp->d_name); + + if (child_path_len < (int)(sizeof(child_path) - 1)) { + // Don't resolve the file type or path + FileSpec child_path_spec(child_path, false); + + EnumerateDirectoryResult result = + callback(file_type, child_path_spec); + + switch (result) { + case eEnumerateDirectoryResultNext: + // Enumerate next entry in the current directory. We just + // exit this switch and will continue enumerating the + // current directory as we currently are... + break; + + case eEnumerateDirectoryResultEnter: // Recurse into the current entry + // if it is a directory or + // symlink, or next if not + if (FileSpec::ForEachItemInDirectory(child_path, callback) == + eEnumerateDirectoryResultQuit) { + // The subdirectory returned Quit, which means to + // stop all directory enumerations at all levels. + if (buf) + free(buf); + return eEnumerateDirectoryResultQuit; } + break; + + case eEnumerateDirectoryResultExit: // Exit from the current directory + // at the current level. + // Exit from this directory level and tell parent to + // keep enumerating. if (buf) - { - free (buf); - } + free(buf); + return eEnumerateDirectoryResultNext; + + case eEnumerateDirectoryResultQuit: // Stop directory enumerations at + // any level + if (buf) + free(buf); + return eEnumerateDirectoryResultQuit; + } } -#endif + } + if (buf) { + free(buf); + } } - // By default when exiting a directory, we tell the parent enumeration - // to continue enumerating. - return eEnumerateDirectoryResultNext; +#endif + } + // By default when exiting a directory, we tell the parent enumeration + // to continue enumerating. + return eEnumerateDirectoryResultNext; } FileSpec::EnumerateDirectoryResult -FileSpec::EnumerateDirectory -( - const char *dir_path, - bool find_directories, - bool find_files, - bool find_other, - EnumerateDirectoryCallbackType callback, - void *callback_baton -) -{ - return ForEachItemInDirectory(dir_path, - [&find_directories, &find_files, &find_other, &callback, &callback_baton] - (FileType file_type, const FileSpec &file_spec) { - switch (file_type) - { - case FileType::eFileTypeDirectory: - if (find_directories) - return callback(callback_baton, file_type, file_spec); - break; - case FileType::eFileTypeRegular: - if (find_files) - return callback(callback_baton, file_type, file_spec); - break; - default: - if (find_other) - return callback(callback_baton, file_type, file_spec); - break; - } - return eEnumerateDirectoryResultNext; - }); -} - -FileSpec -FileSpec::CopyByAppendingPathComponent (const char *new_path) const -{ - FileSpec ret = *this; - ret.AppendPathComponent(new_path); - return ret; -} - -FileSpec -FileSpec::CopyByRemovingLastPathComponent () const -{ - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - return FileSpec("",resolve); - if (m_directory.IsEmpty()) - return FileSpec("",resolve); - if (m_filename.IsEmpty()) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - - // check for obvious cases before doing the full thing - if (!last_slash_ptr) - return FileSpec("",resolve); - if (last_slash_ptr == dir_cstr) - return FileSpec("/",resolve); - - size_t last_slash_pos = last_slash_ptr - dir_cstr+1; - ConstString new_path(dir_cstr,last_slash_pos); - return FileSpec(new_path.GetCString(),resolve); - } - else - return FileSpec(m_directory.GetCString(),resolve); -} - -ConstString -FileSpec::GetLastPathComponent () const -{ - if (m_filename) - return m_filename; - if (m_directory) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - if (last_slash_ptr == NULL) - return m_directory; - if (last_slash_ptr == dir_cstr) - { - if (last_slash_ptr[1] == 0) - return ConstString(last_slash_ptr); - else - return ConstString(last_slash_ptr+1); - } - if (last_slash_ptr[1] != 0) - return ConstString(last_slash_ptr+1); - const char* penultimate_slash_ptr = last_slash_ptr; - while (*penultimate_slash_ptr) - { - --penultimate_slash_ptr; - if (penultimate_slash_ptr == dir_cstr) - break; - if (*penultimate_slash_ptr == '/') - break; +FileSpec::EnumerateDirectory(const char *dir_path, bool find_directories, + bool find_files, bool find_other, + EnumerateDirectoryCallbackType callback, + void *callback_baton) { + return ForEachItemInDirectory( + dir_path, + [&find_directories, &find_files, &find_other, &callback, + &callback_baton](FileType file_type, const FileSpec &file_spec) { + switch (file_type) { + case FileType::eFileTypeDirectory: + if (find_directories) + return callback(callback_baton, file_type, file_spec); + break; + case FileType::eFileTypeRegular: + if (find_files) + return callback(callback_baton, file_type, file_spec); + break; + default: + if (find_other) + return callback(callback_baton, file_type, file_spec); + break; } - ConstString result(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr); - return result; - } - return ConstString(); + return eEnumerateDirectoryResultNext; + }); } -void -FileSpec::PrependPathComponent(const char *new_path) -{ - if (!new_path) return; - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - { - SetFile(new_path, resolve); - return; +FileSpec FileSpec::CopyByAppendingPathComponent(const char *new_path) const { + FileSpec ret = *this; + ret.AppendPathComponent(new_path); + return ret; +} + +FileSpec FileSpec::CopyByRemovingLastPathComponent() const { + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) + return FileSpec("", resolve); + if (m_directory.IsEmpty()) + return FileSpec("", resolve); + if (m_filename.IsEmpty()) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + + // check for obvious cases before doing the full thing + if (!last_slash_ptr) + return FileSpec("", resolve); + if (last_slash_ptr == dir_cstr) + return FileSpec("/", resolve); + + size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; + ConstString new_path(dir_cstr, last_slash_pos); + return FileSpec(new_path.GetCString(), resolve); + } else + return FileSpec(m_directory.GetCString(), resolve); +} + +ConstString FileSpec::GetLastPathComponent() const { + if (m_filename) + return m_filename; + if (m_directory) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + if (last_slash_ptr == NULL) + return m_directory; + if (last_slash_ptr == dir_cstr) { + if (last_slash_ptr[1] == 0) + return ConstString(last_slash_ptr); + else + return ConstString(last_slash_ptr + 1); } - StreamString stream; - if (m_filename.IsEmpty()) - stream.Printf("%s/%s", new_path, m_directory.GetCString()); - else if (m_directory.IsEmpty()) - stream.Printf("%s/%s", new_path, m_filename.GetCString()); - else - stream.Printf("%s/%s/%s", new_path, m_directory.GetCString(), m_filename.GetCString()); - SetFile(stream.GetData(), resolve); -} - -void -FileSpec::PrependPathComponent(const std::string &new_path) -{ - return PrependPathComponent(new_path.c_str()); -} - -void -FileSpec::PrependPathComponent(const FileSpec &new_path) -{ - return PrependPathComponent(new_path.GetPath(false)); -} - -void -FileSpec::AppendPathComponent(const char *new_path) -{ - if (!new_path) return; - - StreamString stream; - if (!m_directory.IsEmpty()) - { - stream.PutCString(m_directory.GetCString()); - if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + if (last_slash_ptr[1] != 0) + return ConstString(last_slash_ptr + 1); + const char *penultimate_slash_ptr = last_slash_ptr; + while (*penultimate_slash_ptr) { + --penultimate_slash_ptr; + if (penultimate_slash_ptr == dir_cstr) + break; + if (*penultimate_slash_ptr == '/') + break; } + ConstString result(penultimate_slash_ptr + 1, + last_slash_ptr - penultimate_slash_ptr); + return result; + } + return ConstString(); +} - if (!m_filename.IsEmpty()) - { - stream.PutCString(m_filename.GetCString()); - if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); - } +void FileSpec::PrependPathComponent(const char *new_path) { + if (!new_path) + return; + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) { + SetFile(new_path, resolve); + return; + } + StreamString stream; + if (m_filename.IsEmpty()) + stream.Printf("%s/%s", new_path, m_directory.GetCString()); + else if (m_directory.IsEmpty()) + stream.Printf("%s/%s", new_path, m_filename.GetCString()); + else + stream.Printf("%s/%s/%s", new_path, m_directory.GetCString(), + m_filename.GetCString()); + SetFile(stream.GetData(), resolve); +} + +void FileSpec::PrependPathComponent(const std::string &new_path) { + return PrependPathComponent(new_path.c_str()); +} + +void FileSpec::PrependPathComponent(const FileSpec &new_path) { + return PrependPathComponent(new_path.GetPath(false)); +} + +void FileSpec::AppendPathComponent(const char *new_path) { + if (!new_path) + return; + + StreamString stream; + if (!m_directory.IsEmpty()) { + stream.PutCString(m_directory.GetCString()); + if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) + stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + } + + if (!m_filename.IsEmpty()) { + stream.PutCString(m_filename.GetCString()); + if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) + stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + } - while (IsPathSeparator(new_path[0], m_syntax)) - new_path++; + while (IsPathSeparator(new_path[0], m_syntax)) + new_path++; - stream.PutCString(new_path); + stream.PutCString(new_path); - const bool resolve = false; - SetFile(stream.GetData(), resolve, m_syntax); + const bool resolve = false; + SetFile(stream.GetData(), resolve, m_syntax); } -void -FileSpec::AppendPathComponent(const std::string &new_path) -{ - return AppendPathComponent(new_path.c_str()); +void FileSpec::AppendPathComponent(const std::string &new_path) { + return AppendPathComponent(new_path.c_str()); } -void -FileSpec::AppendPathComponent(const FileSpec &new_path) -{ - return AppendPathComponent(new_path.GetPath(false)); +void FileSpec::AppendPathComponent(const FileSpec &new_path) { + return AppendPathComponent(new_path.GetPath(false)); } -void -FileSpec::RemoveLastPathComponent () -{ - const bool resolve = false; - if (m_filename.IsEmpty() && m_directory.IsEmpty()) - { - SetFile("",resolve); - return; - } - if (m_directory.IsEmpty()) - { - SetFile("",resolve); - return; +void FileSpec::RemoveLastPathComponent() { + const bool resolve = false; + if (m_filename.IsEmpty() && m_directory.IsEmpty()) { + SetFile("", resolve); + return; + } + if (m_directory.IsEmpty()) { + SetFile("", resolve); + return; + } + if (m_filename.IsEmpty()) { + const char *dir_cstr = m_directory.GetCString(); + const char *last_slash_ptr = ::strrchr(dir_cstr, '/'); + + // check for obvious cases before doing the full thing + if (!last_slash_ptr) { + SetFile("", resolve); + return; } - if (m_filename.IsEmpty()) - { - const char* dir_cstr = m_directory.GetCString(); - const char* last_slash_ptr = ::strrchr(dir_cstr, '/'); - - // check for obvious cases before doing the full thing - if (!last_slash_ptr) - { - SetFile("",resolve); - return; - } - if (last_slash_ptr == dir_cstr) - { - SetFile("/",resolve); - return; - } - size_t last_slash_pos = last_slash_ptr - dir_cstr+1; - ConstString new_path(dir_cstr,last_slash_pos); - SetFile(new_path.GetCString(),resolve); + if (last_slash_ptr == dir_cstr) { + SetFile("/", resolve); + return; } - else - SetFile(m_directory.GetCString(),resolve); + size_t last_slash_pos = last_slash_ptr - dir_cstr + 1; + ConstString new_path(dir_cstr, last_slash_pos); + SetFile(new_path.GetCString(), resolve); + } else + SetFile(m_directory.GetCString(), resolve); } //------------------------------------------------------------------ /// Returns true if the filespec represents an implementation source @@ -1619,57 +1420,45 @@ FileSpec::RemoveLastPathComponent () /// \b true if the filespec represents an implementation source /// file, \b false otherwise. //------------------------------------------------------------------ -bool -FileSpec::IsSourceImplementationFile () const -{ - ConstString extension (GetFileNameExtension()); - if (extension) - { - static RegularExpression g_source_file_regex ("^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])$"); - return g_source_file_regex.Execute (extension.GetCString()); - } - return false; -} - -bool -FileSpec::IsRelative() const -{ - const char *dir = m_directory.GetCString(); - llvm::StringRef directory(dir ? dir : ""); - - if (directory.size() > 0) - { - if (PathSyntaxIsPosix(m_syntax)) - { - // If the path doesn't start with '/' or '~', return true - switch (directory[0]) - { - case '/': - case '~': - return false; - default: - return true; - } - } - else - { - if (directory.size() >= 2 && directory[1] == ':') - return false; - if (directory[0] == '/') - return false; - return true; - } - } - else if (m_filename) - { - // No directory, just a basename, return true +bool FileSpec::IsSourceImplementationFile() const { + ConstString extension(GetFileNameExtension()); + if (extension) { + static RegularExpression g_source_file_regex( + "^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[" + "cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][" + "rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])" + "$"); + return g_source_file_regex.Execute(extension.GetCString()); + } + return false; +} + +bool FileSpec::IsRelative() const { + const char *dir = m_directory.GetCString(); + llvm::StringRef directory(dir ? dir : ""); + + if (directory.size() > 0) { + if (PathSyntaxIsPosix(m_syntax)) { + // If the path doesn't start with '/' or '~', return true + switch (directory[0]) { + case '/': + case '~': + return false; + default: return true; + } + } else { + if (directory.size() >= 2 && directory[1] == ':') + return false; + if (directory[0] == '/') + return false; + return true; } - return false; + } else if (m_filename) { + // No directory, just a basename, return true + return true; + } + return false; } -bool -FileSpec::IsAbsolute() const -{ - return !FileSpec::IsRelative(); -} +bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); } diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp index 5a5dbc7..c865bf3 100644 --- a/lldb/source/Host/common/FileSystem.cpp +++ b/lldb/source/Host/common/FileSystem.cpp @@ -20,84 +20,73 @@ using namespace lldb_private; namespace { -bool -CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, llvm::MD5::MD5Result &md5_result) -{ - llvm::MD5 md5_hash; - std::ifstream file(file_spec.GetPath(), std::ios::binary); - if (!file.is_open()) - return false; - - if (offset > 0) - file.seekg(offset, file.beg); - - std::vector<char> read_buf(4096); - uint64_t total_read_bytes = 0; - while (!file.eof()) - { - const uint64_t to_read = (length > 0) ? - std::min(static_cast<uint64_t>(read_buf.size()), length - total_read_bytes) : - read_buf.size(); - if (to_read == 0) - break; - - file.read(&read_buf[0], to_read); - const auto read_bytes = file.gcount(); - if (read_bytes == 0) - break; - - md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes)); - total_read_bytes += read_bytes; - } - - md5_hash.final(md5_result); - return true; +bool CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, + llvm::MD5::MD5Result &md5_result) { + llvm::MD5 md5_hash; + std::ifstream file(file_spec.GetPath(), std::ios::binary); + if (!file.is_open()) + return false; + + if (offset > 0) + file.seekg(offset, file.beg); + + std::vector<char> read_buf(4096); + uint64_t total_read_bytes = 0; + while (!file.eof()) { + const uint64_t to_read = + (length > 0) ? std::min(static_cast<uint64_t>(read_buf.size()), + length - total_read_bytes) + : read_buf.size(); + if (to_read == 0) + break; + + file.read(&read_buf[0], to_read); + const auto read_bytes = file.gcount(); + if (read_bytes == 0) + break; + + md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes)); + total_read_bytes += read_bytes; + } + + md5_hash.final(md5_result); + return true; } -} // namespace +} // namespace -bool -FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high) -{ - return CalculateMD5(file_spec, 0, 0, low, high); +bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, + uint64_t &high) { + return CalculateMD5(file_spec, 0, 0, low, high); } -bool -FileSystem::CalculateMD5(const FileSpec &file_spec, - uint64_t offset, - uint64_t length, - uint64_t &low, - uint64_t &high) -{ - llvm::MD5::MD5Result md5_result; - if (!CalcMD5(file_spec, offset, length, md5_result)) - return false; - - const auto uint64_res = reinterpret_cast<const uint64_t*>(md5_result); - high = uint64_res[0]; - low = uint64_res[1]; - - return true; +bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset, + uint64_t length, uint64_t &low, uint64_t &high) { + llvm::MD5::MD5Result md5_result; + if (!CalcMD5(file_spec, offset, length, md5_result)) + return false; + + const auto uint64_res = reinterpret_cast<const uint64_t *>(md5_result); + high = uint64_res[0]; + low = uint64_res[1]; + + return true; } -bool -FileSystem::CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str) -{ - return CalculateMD5AsString(file_spec, 0, 0, digest_str); +bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, + std::string &digest_str) { + return CalculateMD5AsString(file_spec, 0, 0, digest_str); } -bool -FileSystem::CalculateMD5AsString(const FileSpec &file_spec, - uint64_t offset, - uint64_t length, - std::string& digest_str) -{ - llvm::MD5::MD5Result md5_result; - if (!CalcMD5(file_spec, offset, length, md5_result)) - return false; - - llvm::SmallString<32> result_str; - llvm::MD5::stringifyResult(md5_result, result_str); - digest_str = result_str.c_str(); - return true; +bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec, + uint64_t offset, uint64_t length, + std::string &digest_str) { + llvm::MD5::MD5Result md5_result; + if (!CalcMD5(file_spec, offset, length, md5_result)) + return false; + + llvm::SmallString<32> result_str; + llvm::MD5::stringifyResult(md5_result, result_str); + digest_str = result_str.c_str(); + return true; } diff --git a/lldb/source/Host/common/GetOptInc.cpp b/lldb/source/Host/common/GetOptInc.cpp index 7689f36..231e991 100644 --- a/lldb/source/Host/common/GetOptInc.cpp +++ b/lldb/source/Host/common/GetOptInc.cpp @@ -1,6 +1,7 @@ #include "lldb/Host/common/GetOptInc.h" -#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || defined(REPLACE_GETOPT_LONG_ONLY) +#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || \ + defined(REPLACE_GETOPT_LONG_ONLY) // getopt.cpp #include <errno.h> @@ -8,32 +9,32 @@ #include <string.h> #if defined(REPLACE_GETOPT) -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ #endif #define PRINT_ERROR ((opterr) && (*options != ':')) -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 -#define EMSG "" +#define EMSG "" -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); +static int getopt_internal(int, char *const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char *const *, const char *, + const struct option *, int *, int); static int gcd(int, int); -static void permute_args(int, int, int, char * const *); +static void permute_args(int, int, int, char *const *); static const char *place = EMSG; /* option letter processing */ @@ -44,19 +45,17 @@ static int nonopt_end = -1; /* first option after non options (for permute) */ /* * Compute the greatest common divisor of a and b. */ -static int -gcd(int a, int b) -{ - int c; +static int gcd(int a, int b) { + int c; + c = a % b; + while (c != 0) { + a = b; + b = c; c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } + } - return (b); + return (b); } static void pass() {} @@ -67,36 +66,34 @@ static void pass() {} * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */ -static void -permute_args(int panonopt_start, int panonopt_end, int opt_end, -char * const *nargv) -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end + i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **)nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } +static void permute_args(int panonopt_start, int panonopt_end, int opt_end, + char *const *nargv) { + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end + i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **)nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; } + } } /* @@ -104,318 +101,297 @@ char * const *nargv) * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ -static int -parse_long_options(char * const *nargv, const char *options, -const struct option *long_options, int *idx, int short_too) -{ - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; - - current_argv = const_cast<char*>(place); - match = -1; - - optind++; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; +static int parse_long_options(char *const *nargv, const char *options, + const struct option *long_options, int *idx, + int short_too) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = const_cast<char *>(place); + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; } - else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - break; - } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == required_argument) { /* - * If this is a known short option, don't allow - * a partial match of a single character. + * optional argument doesn't use next nargv */ - if (short_too && current_argv_len == 1) - continue; - - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } + optarg = nargv[optind++]; + } } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } - else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); + if ((long_options[match].has_arg == required_argument) && + (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else optopt = 0; - return (BADCH); + --optind; + return (BADARG); } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); } - else - return (long_options[match].val); + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); } /* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx, int flags) -{ - const char *oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; - - if (options == NULL) - return (-1); - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ - if (posixly_correct == -1 || optreset) - posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); - if (*options == '-') - flags |= FLAG_ALLARGS; - else if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - if (*options == '+' || *options == '-') - options++; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; +static int getopt_internal(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx, + int flags) { + const char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1 || optreset) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { /* - * If we have "-" do nothing, if "--" we are done. + * If no permutation wanted, stop parsing + * at first non-option. */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + nonopt_start = optind - (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() + * If we have "-" do nothing, if "--" we are done. */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); } + } - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = const_cast<char *>(place); + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; if (PRINT_ERROR) - warnx(illoptchar, optchar); + warnx(recargchar, optchar); optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } - else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; + return (BADARG); + } else + optarg = nargv[optind]; } - else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = const_cast<char*>(place); - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } - else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); } /* @@ -425,19 +401,17 @@ start: * [eventually this will replace the BSD getopt] */ #if defined(REPLACE_GETOPT) -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +int getopt(int nargc, char *const *nargv, const char *options) { + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } #endif @@ -446,12 +420,10 @@ getopt(int nargc, char * const *nargv, const char *options) * Parse argc/argv argument vector. */ #if defined(REPLACE_GETOPT_LONG) -int -getopt_long(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx) -{ - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); +int getopt_long(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx) { + return ( + getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE)); } #endif @@ -460,13 +432,11 @@ const struct option *long_options, int *idx) * Parse argc/argv argument vector. */ #if defined(REPLACE_GETOPT_LONG_ONLY) -int -getopt_long_only(int nargc, char * const *nargv, const char *options, -const struct option *long_options, int *idx) -{ +int getopt_long_only(int nargc, char *const *nargv, const char *options, + const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE | FLAG_LONGONLY)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE | FLAG_LONGONLY)); } #endif diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index c5dd105..bd85c98 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -13,29 +13,30 @@ #include <stdlib.h> #include <sys/types.h> #ifndef _WIN32 -#include <unistd.h> #include <dlfcn.h> #include <grp.h> #include <netdb.h> #include <pwd.h> #include <sys/stat.h> +#include <unistd.h> #endif -#if defined (__APPLE__) -#include <mach/mach_port.h> -#include <mach/mach_init.h> +#if defined(__APPLE__) #include <mach-o/dyld.h> +#include <mach/mach_init.h> +#include <mach/mach_port.h> #endif -#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) #include <spawn.h> #endif -#include <sys/wait.h> #include <sys/syscall.h> +#include <sys/wait.h> #endif -#if defined (__FreeBSD__) +#if defined(__FreeBSD__) #include <pthread_np.h> #endif @@ -44,25 +45,25 @@ // Other libraries and framework includes // Project includes -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/lldb-private-forward.h" -#include "llvm/Support/FileSystem.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/CleanUp.h" +#include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" #if defined(_WIN32) #include "lldb/Host/windows/ProcessLauncherWindows.h" @@ -72,15 +73,14 @@ #include "lldb/Host/posix/ProcessLauncherPosix.h" #endif -#if defined (__APPLE__) +#if defined(__APPLE__) #ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif -extern "C" -{ - int __pthread_chdir(const char *path); - int __pthread_fchdir (int fildes); +extern "C" { +int __pthread_chdir(const char *path); +int __pthread_fchdir(int fildes); } #endif @@ -88,30 +88,30 @@ extern "C" using namespace lldb; using namespace lldb_private; -#if !defined (__APPLE__) && !defined (_WIN32) -struct MonitorInfo -{ - lldb::pid_t pid; // The process ID to monitor - Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals - bool monitor_signals; // If true, call the callback when "pid" gets signaled. +#if !defined(__APPLE__) && !defined(_WIN32) +struct MonitorInfo { + lldb::pid_t pid; // The process ID to monitor + Host::MonitorChildProcessCallback + callback; // The callback function to call when "pid" exits or signals + bool monitor_signals; // If true, call the callback when "pid" gets signaled. }; -static thread_result_t -MonitorChildProcessThreadFunction (void *arg); +static thread_result_t MonitorChildProcessThreadFunction(void *arg); -HostThread -Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, - bool monitor_signals) -{ - MonitorInfo * info_ptr = new MonitorInfo(); - - info_ptr->pid = pid; - info_ptr->callback = callback; - info_ptr->monitor_signals = monitor_signals; - - char thread_name[256]; - ::snprintf(thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); - return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); +HostThread Host::StartMonitoringChildProcess( + const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, + bool monitor_signals) { + MonitorInfo *info_ptr = new MonitorInfo(); + + info_ptr->pid = pid; + info_ptr->callback = callback; + info_ptr->monitor_signals = monitor_signals; + + char thread_name[256]; + ::snprintf(thread_name, sizeof(thread_name), + "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); + return ThreadLauncher::LaunchThread( + thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); } #ifndef __linux__ @@ -120,26 +120,24 @@ Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callb // constructed, and exception safely restore the previous value it // when it goes out of scope. //------------------------------------------------------------------ -class ScopedPThreadCancelDisabler -{ +class ScopedPThreadCancelDisabler { public: - ScopedPThreadCancelDisabler() - { - // Disable the ability for this thread to be cancelled - int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); - if (err != 0) - m_old_state = -1; - } + ScopedPThreadCancelDisabler() { + // Disable the ability for this thread to be cancelled + int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m_old_state); + if (err != 0) + m_old_state = -1; + } + + ~ScopedPThreadCancelDisabler() { + // Restore the ability for this thread to be cancelled to what it + // previously was. + if (m_old_state != -1) + ::pthread_setcancelstate(m_old_state, 0); + } - ~ScopedPThreadCancelDisabler() - { - // Restore the ability for this thread to be cancelled to what it - // previously was. - if (m_old_state != -1) - ::pthread_setcancelstate (m_old_state, 0); - } private: - int m_old_state; // Save the old cancelability state. + int m_old_state; // Save the old cancelability state. }; #endif // __linux__ @@ -150,279 +148,275 @@ static __thread volatile sig_atomic_t g_usr1_called; static thread_local volatile sig_atomic_t g_usr1_called; #endif -static void -SigUsr1Handler (int) -{ - g_usr1_called = 1; -} +static void SigUsr1Handler(int) { g_usr1_called = 1; } #endif // __linux__ -static bool -CheckForMonitorCancellation() -{ +static bool CheckForMonitorCancellation() { #ifdef __linux__ - if (g_usr1_called) - { - g_usr1_called = 0; - return true; - } + if (g_usr1_called) { + g_usr1_called = 0; + return true; + } #else - ::pthread_testcancel (); + ::pthread_testcancel(); #endif - return false; + return false; } -static thread_result_t -MonitorChildProcessThreadFunction (void *arg) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - const char *function = __FUNCTION__; - if (log) - log->Printf ("%s (arg = %p) thread starting...", function, arg); +static thread_result_t MonitorChildProcessThreadFunction(void *arg) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + const char *function = __FUNCTION__; + if (log) + log->Printf("%s (arg = %p) thread starting...", function, arg); - MonitorInfo *info = (MonitorInfo *)arg; + MonitorInfo *info = (MonitorInfo *)arg; - const Host::MonitorChildProcessCallback callback = info->callback; - const bool monitor_signals = info->monitor_signals; + const Host::MonitorChildProcessCallback callback = info->callback; + const bool monitor_signals = info->monitor_signals; - assert (info->pid <= UINT32_MAX); - const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; + assert(info->pid <= UINT32_MAX); + const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; - delete info; + delete info; - int status = -1; -#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) - #define __WALL 0 + int status = -1; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#define __WALL 0 #endif - const int options = __WALL; + const int options = __WALL; #ifdef __linux__ - // This signal is only used to interrupt the thread from waitpid - struct sigaction sigUsr1Action; - memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); - sigUsr1Action.sa_handler = SigUsr1Handler; - ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); -#endif // __linux__ - - while (1) - { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); + // This signal is only used to interrupt the thread from waitpid + struct sigaction sigUsr1Action; + memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); + sigUsr1Action.sa_handler = SigUsr1Handler; + ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); +#endif // __linux__ - if (CheckForMonitorCancellation ()) - break; + while (1) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", + function, pid, options); - // Get signals from all children with same process group of pid - const ::pid_t wait_pid = ::waitpid (pid, &status, options); + if (CheckForMonitorCancellation()) + break; - if (CheckForMonitorCancellation ()) - break; + // Get signals from all children with same process group of pid + const ::pid_t wait_pid = ::waitpid(pid, &status, options); - if (wait_pid == -1) - { - if (errno == EINTR) - continue; - else - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno)); - break; - } + if (CheckForMonitorCancellation()) + break; + + if (wait_pid == -1) { + if (errno == EINTR) + continue; + else { + if (log) + log->Printf( + "%s (arg = %p) thread exiting because waitpid failed (%s)...", + __FUNCTION__, arg, strerror(errno)); + break; + } + } else if (wait_pid > 0) { + bool exited = false; + int signal = 0; + int exit_status = 0; + const char *status_cstr = NULL; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + status_cstr = "STOPPED"; + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + status_cstr = "EXITED"; + exited = true; + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + status_cstr = "SIGNALED"; + if (wait_pid == abs(pid)) { + exited = true; + exit_status = -1; } - else if (wait_pid > 0) - { - bool exited = false; - int signal = 0; - int exit_status = 0; - const char *status_cstr = NULL; - if (WIFSTOPPED(status)) - { - signal = WSTOPSIG(status); - status_cstr = "STOPPED"; - } - else if (WIFEXITED(status)) - { - exit_status = WEXITSTATUS(status); - status_cstr = "EXITED"; - exited = true; - } - else if (WIFSIGNALED(status)) - { - signal = WTERMSIG(status); - status_cstr = "SIGNALED"; - if (wait_pid == abs(pid)) { - exited = true; - exit_status = -1; - } - } - else - { - status_cstr = "(\?\?\?)"; - } - - // Scope for pthread_cancel_disabler - { + } else { + status_cstr = "(\?\?\?)"; + } + + // Scope for pthread_cancel_disabler + { #ifndef __linux__ - ScopedPThreadCancelDisabler pthread_cancel_disabler; + ScopedPThreadCancelDisabler pthread_cancel_disabler; #endif - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", - function, - pid, - options, - wait_pid, - status, - status_cstr, - signal, - exit_status); - - if (exited || (signal != 0 && monitor_signals)) - { - bool callback_return = false; - if (callback) - callback_return = callback(wait_pid, exited, signal, exit_status); - - // If our process exited, then this thread should exit - if (exited && wait_pid == abs(pid)) - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg); - break; - } - // If the callback returns true, it means this process should - // exit - if (callback_return) - { - if (log) - log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg); - break; - } - } - } + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s ::waitpid (pid = %" PRIi32 + ", &status, options = %i) => pid = %" PRIi32 + ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", + function, pid, options, wait_pid, status, status_cstr, + signal, exit_status); + + if (exited || (signal != 0 && monitor_signals)) { + bool callback_return = false; + if (callback) + callback_return = callback(wait_pid, exited, signal, exit_status); + + // If our process exited, then this thread should exit + if (exited && wait_pid == abs(pid)) { + if (log) + log->Printf("%s (arg = %p) thread exiting because pid received " + "exit signal...", + __FUNCTION__, arg); + break; + } + // If the callback returns true, it means this process should + // exit + if (callback_return) { + if (log) + log->Printf("%s (arg = %p) thread exiting because callback " + "returned true...", + __FUNCTION__, arg); + break; + } } + } } + } - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg); - return NULL; + return NULL; } #endif // #if !defined (__APPLE__) && !defined (_WIN32) -#if !defined (__APPLE__) +#if !defined(__APPLE__) -void -Host::SystemLog (SystemLogType type, const char *format, va_list args) -{ - vfprintf (stderr, format, args); +void Host::SystemLog(SystemLogType type, const char *format, va_list args) { + vfprintf(stderr, format, args); } #endif -void -Host::SystemLog (SystemLogType type, const char *format, ...) -{ - va_list args; - va_start (args, format); - SystemLog (type, format, args); - va_end (args); +void Host::SystemLog(SystemLogType type, const char *format, ...) { + va_list args; + va_start(args, format); + SystemLog(type, format, args); + va_end(args); } -lldb::pid_t -Host::GetCurrentProcessID() -{ - return ::getpid(); -} +lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); } #ifndef _WIN32 -lldb::tid_t -Host::GetCurrentThreadID() -{ -#if defined (__APPLE__) - // Calling "mach_thread_self()" bumps the reference count on the thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the ref - // count. - thread_port_t thread_self = mach_thread_self(); - mach_port_deallocate(mach_task_self(), thread_self); - return thread_self; +lldb::tid_t Host::GetCurrentThreadID() { +#if defined(__APPLE__) + // Calling "mach_thread_self()" bumps the reference count on the thread + // port, so we need to deallocate it. mach_task_self() doesn't bump the ref + // count. + thread_port_t thread_self = mach_thread_self(); + mach_port_deallocate(mach_task_self(), thread_self); + return thread_self; #elif defined(__FreeBSD__) - return lldb::tid_t(pthread_getthreadid_np()); + return lldb::tid_t(pthread_getthreadid_np()); #elif defined(__ANDROID_NDK__) - return lldb::tid_t(gettid()); + return lldb::tid_t(gettid()); #elif defined(__linux__) - return lldb::tid_t(syscall(SYS_gettid)); + return lldb::tid_t(syscall(SYS_gettid)); #else - return lldb::tid_t(pthread_self()); + return lldb::tid_t(pthread_self()); #endif } -lldb::thread_t -Host::GetCurrentThread () -{ - return lldb::thread_t(pthread_self()); +lldb::thread_t Host::GetCurrentThread() { + return lldb::thread_t(pthread_self()); } -const char * -Host::GetSignalAsCString (int signo) -{ - switch (signo) - { - case SIGHUP: return "SIGHUP"; // 1 hangup - case SIGINT: return "SIGINT"; // 2 interrupt - case SIGQUIT: return "SIGQUIT"; // 3 quit - case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) - case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) - case SIGABRT: return "SIGABRT"; // 6 abort() -#if defined(SIGPOLL) +const char *Host::GetSignalAsCString(int signo) { + switch (signo) { + case SIGHUP: + return "SIGHUP"; // 1 hangup + case SIGINT: + return "SIGINT"; // 2 interrupt + case SIGQUIT: + return "SIGQUIT"; // 3 quit + case SIGILL: + return "SIGILL"; // 4 illegal instruction (not reset when caught) + case SIGTRAP: + return "SIGTRAP"; // 5 trace trap (not reset when caught) + case SIGABRT: + return "SIGABRT"; // 6 abort() +#if defined(SIGPOLL) #if !defined(SIGIO) || (SIGPOLL != SIGIO) -// Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to -// fail with 'multiple define cases with same value' - case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) -#endif -#endif -#if defined(SIGEMT) - case SIGEMT: return "SIGEMT"; // 7 EMT instruction -#endif - case SIGFPE: return "SIGFPE"; // 8 floating point exception - case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) - case SIGBUS: return "SIGBUS"; // 10 bus error - case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation - case SIGSYS: return "SIGSYS"; // 12 bad argument to system call - case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it - case SIGALRM: return "SIGALRM"; // 14 alarm clock - case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill - case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel - case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty - case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty - case SIGCONT: return "SIGCONT"; // 19 continue a stopped process - case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit - case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read - case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) -#if defined(SIGIO) - case SIGIO: return "SIGIO"; // 23 input/output possible signal -#endif - case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit - case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit - case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm - case SIGPROF: return "SIGPROF"; // 27 profiling time alarm -#if defined(SIGWINCH) - case SIGWINCH: return "SIGWINCH"; // 28 window size changes -#endif -#if defined(SIGINFO) - case SIGINFO: return "SIGINFO"; // 29 information request -#endif - case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 - case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 - default: - break; - } - return NULL; + // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to + // fail with 'multiple define cases with same value' + case SIGPOLL: + return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) +#endif +#endif +#if defined(SIGEMT) + case SIGEMT: + return "SIGEMT"; // 7 EMT instruction +#endif + case SIGFPE: + return "SIGFPE"; // 8 floating point exception + case SIGKILL: + return "SIGKILL"; // 9 kill (cannot be caught or ignored) + case SIGBUS: + return "SIGBUS"; // 10 bus error + case SIGSEGV: + return "SIGSEGV"; // 11 segmentation violation + case SIGSYS: + return "SIGSYS"; // 12 bad argument to system call + case SIGPIPE: + return "SIGPIPE"; // 13 write on a pipe with no one to read it + case SIGALRM: + return "SIGALRM"; // 14 alarm clock + case SIGTERM: + return "SIGTERM"; // 15 software termination signal from kill + case SIGURG: + return "SIGURG"; // 16 urgent condition on IO channel + case SIGSTOP: + return "SIGSTOP"; // 17 sendable stop signal not from tty + case SIGTSTP: + return "SIGTSTP"; // 18 stop signal from tty + case SIGCONT: + return "SIGCONT"; // 19 continue a stopped process + case SIGCHLD: + return "SIGCHLD"; // 20 to parent on child stop or exit + case SIGTTIN: + return "SIGTTIN"; // 21 to readers pgrp upon background tty read + case SIGTTOU: + return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) +#if defined(SIGIO) + case SIGIO: + return "SIGIO"; // 23 input/output possible signal +#endif + case SIGXCPU: + return "SIGXCPU"; // 24 exceeded CPU time limit + case SIGXFSZ: + return "SIGXFSZ"; // 25 exceeded file size limit + case SIGVTALRM: + return "SIGVTALRM"; // 26 virtual time alarm + case SIGPROF: + return "SIGPROF"; // 27 profiling time alarm +#if defined(SIGWINCH) + case SIGWINCH: + return "SIGWINCH"; // 28 window size changes +#endif +#if defined(SIGINFO) + case SIGINFO: + return "SIGINFO"; // 29 information request +#endif + case SIGUSR1: + return "SIGUSR1"; // 30 user defined signal 1 + case SIGUSR2: + return "SIGUSR2"; // 31 user defined signal 2 + default: + break; + } + return NULL; } #endif @@ -430,84 +424,63 @@ Host::GetSignalAsCString (int signo) #ifndef _WIN32 lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) -{ - pthread_key_t key; - ::pthread_key_create (&key, callback); - return key; +Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { + pthread_key_t key; + ::pthread_key_create(&key, callback); + return key; } -void* -Host::ThreadLocalStorageGet(lldb::thread_key_t key) -{ - return ::pthread_getspecific (key); +void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { + return ::pthread_getspecific(key); } -void -Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) -{ - ::pthread_setspecific (key, value); +void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { + ::pthread_setspecific(key, value); } #endif -#if !defined (__APPLE__) // see Host.mm +#if !defined(__APPLE__) // see Host.mm -bool -Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) -{ - bundle.Clear(); - return false; +bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) { + bundle.Clear(); + return false; } -bool -Host::ResolveExecutableInBundle (FileSpec &file) -{ - return false; -} +bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; } #endif #ifndef _WIN32 -FileSpec -Host::GetModuleFileSpecForHostAddress (const void *host_addr) -{ - FileSpec module_filespec; +FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { + FileSpec module_filespec; #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) - Dl_info info; - if (::dladdr (host_addr, &info)) - { - if (info.dli_fname) - module_filespec.SetFile(info.dli_fname, true); - } + Dl_info info; + if (::dladdr(host_addr, &info)) { + if (info.dli_fname) + module_filespec.SetFile(info.dli_fname, true); + } #endif - return module_filespec; + return module_filespec; } #endif #if !defined(__linux__) -bool -Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) -{ - return false; +bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { + return false; } #endif -struct ShellInfo -{ - ShellInfo () : - process_reaped (false), - pid (LLDB_INVALID_PROCESS_ID), - signo(-1), - status(-1) - { - } +struct ShellInfo { + ShellInfo() + : process_reaped(false), pid(LLDB_INVALID_PROCESS_ID), signo(-1), + status(-1) {} - lldb_private::Predicate<bool> process_reaped; - lldb::pid_t pid; - int signo; - int status; + lldb_private::Predicate<bool> process_reaped; + lldb::pid_t pid; + int signo; + int status; }; static bool @@ -516,540 +489,524 @@ MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid, int signo, // Zero for no signal int status) // Exit value of process if signal is zero { - shell_info->pid = pid; - shell_info->signo = signo; - shell_info->status = status; - // Let the thread running Host::RunShellCommand() know that the process - // exited and that ShellInfo has been filled in by broadcasting to it - shell_info->process_reaped.SetValue(true, eBroadcastAlways); - return true; + shell_info->pid = pid; + shell_info->signo = signo; + shell_info->status = status; + // Let the thread running Host::RunShellCommand() know that the process + // exited and that ShellInfo has been filled in by broadcasting to it + shell_info->process_reaped.SetValue(true, eBroadcastAlways); + return true; } -Error -Host::RunShellCommand(const char *command, - const FileSpec &working_dir, - int *status_ptr, - int *signo_ptr, - std::string *command_output_ptr, - uint32_t timeout_sec, - bool run_in_default_shell) -{ - return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, command_output_ptr, timeout_sec, run_in_default_shell); +Error Host::RunShellCommand(const char *command, const FileSpec &working_dir, + int *status_ptr, int *signo_ptr, + std::string *command_output_ptr, + uint32_t timeout_sec, bool run_in_default_shell) { + return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, + command_output_ptr, timeout_sec, run_in_default_shell); } -Error -Host::RunShellCommand(const Args &args, - const FileSpec &working_dir, - int *status_ptr, - int *signo_ptr, - std::string *command_output_ptr, - uint32_t timeout_sec, - bool run_in_default_shell) -{ - Error error; - ProcessLaunchInfo launch_info; - launch_info.SetArchitecture(HostInfo::GetArchitecture()); - if (run_in_default_shell) - { - // Run the command in a shell - launch_info.SetShell(HostInfo::GetDefaultShell()); - launch_info.GetArguments().AppendArguments(args); - const bool localhost = true; - const bool will_debug = false; - const bool first_arg_is_full_shell_command = false; - launch_info.ConvertArgumentsForLaunchingInShell (error, - localhost, - will_debug, - first_arg_is_full_shell_command, - 0); - } - else - { - // No shell, just run it - const bool first_arg_is_executable = true; - launch_info.SetArguments(args, first_arg_is_executable); +Error Host::RunShellCommand(const Args &args, const FileSpec &working_dir, + int *status_ptr, int *signo_ptr, + std::string *command_output_ptr, + uint32_t timeout_sec, bool run_in_default_shell) { + Error error; + ProcessLaunchInfo launch_info; + launch_info.SetArchitecture(HostInfo::GetArchitecture()); + if (run_in_default_shell) { + // Run the command in a shell + launch_info.SetShell(HostInfo::GetDefaultShell()); + launch_info.GetArguments().AppendArguments(args); + const bool localhost = true; + const bool will_debug = false; + const bool first_arg_is_full_shell_command = false; + launch_info.ConvertArgumentsForLaunchingInShell( + error, localhost, will_debug, first_arg_is_full_shell_command, 0); + } else { + // No shell, just run it + const bool first_arg_is_executable = true; + launch_info.SetArguments(args, first_arg_is_executable); + } + + if (working_dir) + launch_info.SetWorkingDirectory(working_dir); + llvm::SmallString<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)) { + tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), + output_file_path); + } else { + llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", + output_file_path); } - - if (working_dir) - launch_info.SetWorkingDirectory(working_dir); - llvm::SmallString<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)) - { - tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); - llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path); - } - else - { - llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path); + } + + FileSpec output_file_spec{output_file_path.c_str(), false}; + + launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); + if (output_file_spec) { + launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, + true); + launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); + } else { + launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); + launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); + } + + std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); + const bool monitor_signals = false; + launch_info.SetMonitorProcessCallback( + std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4), + monitor_signals); + + error = LaunchProcess(launch_info); + const lldb::pid_t pid = launch_info.GetProcessID(); + + if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) + error.SetErrorString("failed to get process ID"); + + if (error.Success()) { + bool timed_out = false; + shell_info_sp->process_reaped.WaitForValueEqualTo( + true, std::chrono::seconds(timeout_sec), &timed_out); + if (timed_out) { + error.SetErrorString("timed out waiting for shell command to complete"); + + // Kill the process since it didn't complete within the timeout specified + Kill(pid, SIGKILL); + // Wait for the monitor callback to get the message + timed_out = false; + shell_info_sp->process_reaped.WaitForValueEqualTo( + true, std::chrono::seconds(1), &timed_out); + } else { + if (status_ptr) + *status_ptr = shell_info_sp->status; + + if (signo_ptr) + *signo_ptr = shell_info_sp->signo; + + if (command_output_ptr) { + command_output_ptr->clear(); + uint64_t file_size = output_file_spec.GetByteSize(); + if (file_size > 0) { + if (file_size > command_output_ptr->max_size()) { + error.SetErrorStringWithFormat( + "shell command output is too large to fit into a std::string"); + } else { + std::vector<char> command_output(file_size); + output_file_spec.ReadFileContents(0, command_output.data(), + file_size, &error); + if (error.Success()) + command_output_ptr->assign(command_output.data(), file_size); + } } + } } + } - FileSpec output_file_spec{output_file_path.c_str(), false}; - - launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); - if (output_file_spec) - { - launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true); - launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); - } - else - { - launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); - launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); - } - - std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); - const bool monitor_signals = false; - launch_info.SetMonitorProcessCallback(std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4), - monitor_signals); - - error = LaunchProcess (launch_info); - const lldb::pid_t pid = launch_info.GetProcessID(); - - if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) - error.SetErrorString("failed to get process ID"); - - if (error.Success()) - { - bool timed_out = false; - shell_info_sp->process_reaped.WaitForValueEqualTo(true, std::chrono::seconds(timeout_sec), &timed_out); - if (timed_out) - { - error.SetErrorString("timed out waiting for shell command to complete"); - - // Kill the process since it didn't complete within the timeout specified - Kill (pid, SIGKILL); - // Wait for the monitor callback to get the message - timed_out = false; - shell_info_sp->process_reaped.WaitForValueEqualTo(true, std::chrono::seconds(1), &timed_out); - } - else - { - if (status_ptr) - *status_ptr = shell_info_sp->status; - - if (signo_ptr) - *signo_ptr = shell_info_sp->signo; - - if (command_output_ptr) - { - command_output_ptr->clear(); - uint64_t file_size = output_file_spec.GetByteSize(); - if (file_size > 0) - { - if (file_size > command_output_ptr->max_size()) - { - error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); - } - else - { - std::vector<char> command_output(file_size); - output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error); - if (error.Success()) - command_output_ptr->assign(command_output.data(), file_size); - } - } - } - } - } - - if (FileSystem::GetFileExists(output_file_spec)) - FileSystem::Unlink(output_file_spec); - return error; + if (FileSystem::GetFileExists(output_file_spec)) + FileSystem::Unlink(output_file_spec); + return error; } // LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC // systems -#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || \ + defined(__GLIBC__) || defined(__NetBSD__) #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) // this method needs to be visible to macosx/Host.cpp and // common/Host.cpp. -short -Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) -{ - short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - -#if defined (__APPLE__) - if (launch_info.GetFlags().Test (eLaunchFlagExec)) - flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test (eLaunchFlagDebug)) - flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) - flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag - - if (launch_info.GetLaunchInSeparateProcessGroup()) - flags |= POSIX_SPAWN_SETPGROUP; - +short Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { + short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + +#if defined(__APPLE__) + if (launch_info.GetFlags().Test(eLaunchFlagExec)) + flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) + flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag + + if (launch_info.GetLaunchInSeparateProcessGroup()) + flags |= POSIX_SPAWN_SETPGROUP; + #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT -#if defined (__APPLE__) && (defined (__x86_64__) || defined (__i386__)) - static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; - if (g_use_close_on_exec_flag == eLazyBoolCalculate) - { - g_use_close_on_exec_flag = eLazyBoolNo; - - uint32_t major, minor, update; - if (HostInfo::GetOSVersion(major, minor, update)) - { - // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier - if (major > 10 || (major == 10 && minor > 7)) - { - // Only enable for 10.8 and later OS versions - g_use_close_on_exec_flag = eLazyBoolYes; - } - } +#if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) + static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; + if (g_use_close_on_exec_flag == eLazyBoolCalculate) { + g_use_close_on_exec_flag = eLazyBoolNo; + + uint32_t major, minor, update; + if (HostInfo::GetOSVersion(major, minor, update)) { + // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or + // earlier + if (major > 10 || (major == 10 && minor > 7)) { + // Only enable for 10.8 and later OS versions + g_use_close_on_exec_flag = eLazyBoolYes; + } } + } #else - static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; + static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; #endif - // Close all files exception those with file actions if this is supported. - if (g_use_close_on_exec_flag == eLazyBoolYes) - flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; + // Close all files exception those with file actions if this is supported. + if (g_use_close_on_exec_flag == eLazyBoolYes) + flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; #endif #endif // #if defined (__APPLE__) - return flags; + return flags; } -Error -Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) -{ - Error error; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); +Error Host::LaunchProcessPosixSpawn(const char *exe_path, + const ProcessLaunchInfo &launch_info, + lldb::pid_t &pid) { + Error error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); - posix_spawnattr_t attr; - error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); + posix_spawnattr_t attr; + error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); - if (error.Fail()) - return error; + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); + if (error.Fail()) + return error; - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset (&no_signals); - sigfillset (&all_signals); - ::posix_spawnattr_setsigmask(&attr, &no_signals); -#if defined (__linux__) || defined (__FreeBSD__) - ::posix_spawnattr_setsigdefault(&attr, &no_signals); + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup( + &attr, posix_spawnattr_destroy); + + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + ::posix_spawnattr_setsigmask(&attr, &no_signals); +#if defined(__linux__) || defined(__FreeBSD__) + ::posix_spawnattr_setsigdefault(&attr, &no_signals); #else - ::posix_spawnattr_setsigdefault(&attr, &all_signals); + ::posix_spawnattr_setsigdefault(&attr, &all_signals); #endif - short flags = GetPosixspawnFlags(launch_info); + short flags = GetPosixspawnFlags(launch_info); - error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); - if (error.Fail()) - return error; + error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", + flags); + if (error.Fail()) + return error; - // posix_spawnattr_setbinpref_np appears to be an Apple extension per: - // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ -#if defined (__APPLE__) && !defined (__arm__) - - // Don't set the binpref if a shell was provided. After all, that's only going to affect what version of the shell - // is launched, not what fork of the binary is launched. We insert "arch --arch <ARCH> as part of the shell invocation - // to do that job on OSX. - - if (launch_info.GetShell() == nullptr) +// posix_spawnattr_setbinpref_np appears to be an Apple extension per: +// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ +#if defined(__APPLE__) && !defined(__arm__) + + // Don't set the binpref if a shell was provided. After all, that's only + // going to affect what version of the shell + // is launched, not what fork of the binary is launched. We insert "arch + // --arch <ARCH> as part of the shell invocation + // to do that job on OSX. + + if (launch_info.GetShell() == nullptr) { + // We don't need to do this for ARM, and we really shouldn't now that we + // have multiple CPU subtypes and no posix_spawnattr call that allows us + // to set which CPU subtype to launch... + const ArchSpec &arch_spec = launch_info.GetArchitecture(); + cpu_type_t cpu = arch_spec.GetMachOCPUType(); + cpu_type_t sub = arch_spec.GetMachOCPUSubType(); + if (cpu != 0 && cpu != static_cast<cpu_type_t>(UINT32_MAX) && + cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) && + !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try + // to set the CPU type or we will fail { - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - cpu_type_t cpu = arch_spec.GetMachOCPUType(); - cpu_type_t sub = arch_spec.GetMachOCPUSubType(); - if (cpu != 0 && - cpu != static_cast<cpu_type_t>(UINT32_MAX) && - cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) && - !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail - { - size_t ocount = 0; - error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); - - if (error.Fail() || ocount != 1) - return error; - } + size_t ocount = 0; + error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, " + "cpu_type = 0x%8.8x, count => %llu )", + cpu, (uint64_t)ocount); + + if (error.Fail() || ocount != 1) + return error; } - -#endif - - const char *tmp_argv[2]; - char * const *argv = const_cast<char * const*>(launch_info.GetArguments().GetConstArgumentVector()); - char * const *envp = const_cast<char * const*>(launch_info.GetEnvironmentEntries().GetConstArgumentVector()); - if (argv == NULL) - { - // posix_spawn gets very unhappy if it doesn't have at least the program - // name in argv[0]. One of the side affects I have noticed is the environment - // variables don't make it into the child process if "argv == NULL"!!! - tmp_argv[0] = exe_path; - tmp_argv[1] = NULL; - argv = const_cast<char * const*>(tmp_argv); + } + +#endif + + 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()); + if (argv == NULL) { + // posix_spawn gets very unhappy if it doesn't have at least the program + // name in argv[0]. One of the side affects I have noticed is the + // environment + // variables don't make it into the child process if "argv == NULL"!!! + tmp_argv[0] = exe_path; + tmp_argv[1] = NULL; + argv = const_cast<char *const *>(tmp_argv); + } + +#if !defined(__APPLE__) + // manage the working directory + char current_dir[PATH_MAX]; + current_dir[0] = '\0'; +#endif + + FileSpec working_dir{launch_info.GetWorkingDirectory()}; + if (working_dir) { +#if defined(__APPLE__) + // Set the working directory on this thread only + if (__pthread_chdir(working_dir.GetCString()) < 0) { + if (errno == ENOENT) { + error.SetErrorStringWithFormat("No such file or directory: %s", + working_dir.GetCString()); + } else if (errno == ENOTDIR) { + error.SetErrorStringWithFormat("Path doesn't name a directory: %s", + working_dir.GetCString()); + } else { + error.SetErrorStringWithFormat("An unknown error occurred when " + "changing directory for process " + "execution."); + } + return error; } - -#if !defined (__APPLE__) - // manage the working directory - char current_dir[PATH_MAX]; - current_dir[0] = '\0'; -#endif - - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir) - { -#if defined (__APPLE__) - // Set the working directory on this thread only - if (__pthread_chdir(working_dir.GetCString()) < 0) { - if (errno == ENOENT) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - } else if (errno == ENOTDIR) { - error.SetErrorStringWithFormat("Path doesn't name a directory: %s", - working_dir.GetCString()); - } else { - error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution."); - } - return error; - } #else - if (::getcwd(current_dir, sizeof(current_dir)) == NULL) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to save the current directory"); - return error; - } - - if (::chdir(working_dir.GetCString()) == -1) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to change working directory to %s", - working_dir.GetCString()); - return error; - } -#endif + if (::getcwd(current_dir, sizeof(current_dir)) == NULL) { + error.SetError(errno, eErrorTypePOSIX); + error.LogIfError(log, "unable to save the current directory"); + return error; } - ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; - const size_t num_file_actions = launch_info.GetNumFileActions (); - if (num_file_actions > 0) - { - posix_spawn_file_actions_t file_actions; - error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); - if (error.Fail()) - return error; - - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy); - - for (size_t i=0; i<num_file_actions; ++i) - { - const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); - if (launch_file_action) - { - if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error)) - return error; - } - } + if (::chdir(working_dir.GetCString()) == -1) { + error.SetError(errno, eErrorTypePOSIX); + error.LogIfError(log, "unable to change working directory to %s", + working_dir.GetCString()); + return error; + } +#endif + } - error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX); + ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; + const size_t num_file_actions = launch_info.GetNumFileActions(); + if (num_file_actions > 0) { + posix_spawn_file_actions_t file_actions; + error.SetError(::posix_spawn_file_actions_init(&file_actions), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); + if (error.Fail()) + return error; - if (error.Fail() || log) - { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid, - exe_path, static_cast<void *>(&file_actions), static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), - reinterpret_cast<const void *>(envp)); - if (log) - { - for (int ii=0; argv[ii]; ++ii) - log->Printf("argv[%i] = '%s'", ii, argv[ii]); - } - } + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp<posix_spawn_file_actions_t *, int> + posix_spawn_file_actions_cleanup(&file_actions, + posix_spawn_file_actions_destroy); + + for (size_t i = 0; i < num_file_actions; ++i) { + const FileAction *launch_file_action = + launch_info.GetFileActionAtIndex(i); + if (launch_file_action) { + if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, + error)) + return error; + } + } + error.SetError( + ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail() || log) { + error.PutToLog( + log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, " + "attr = %p, argv = %p, envp = %p )", + result_pid, exe_path, static_cast<void *>(&file_actions), + static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), + reinterpret_cast<const void *>(envp)); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + log->Printf("argv[%i] = '%s'", ii, argv[ii]); + } } - else - { - error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX); - if (error.Fail() || log) - { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", - result_pid, exe_path, static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), - reinterpret_cast<const void *>(envp)); - if (log) - { - for (int ii=0; argv[ii]; ++ii) - log->Printf("argv[%i] = '%s'", ii, argv[ii]); - } - } + } else { + error.SetError( + ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail() || log) { + error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', " + "file_actions = NULL, attr = %p, argv = %p, envp = " + "%p )", + result_pid, exe_path, static_cast<void *>(&attr), + reinterpret_cast<const void *>(argv), + reinterpret_cast<const void *>(envp)); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + log->Printf("argv[%i] = '%s'", ii, argv[ii]); + } } - pid = result_pid; + } + pid = result_pid; - if (working_dir) - { -#if defined (__APPLE__) - // No more thread specific current working directory - __pthread_fchdir (-1); + if (working_dir) { +#if defined(__APPLE__) + // No more thread specific current working directory + __pthread_fchdir(-1); #else - if (::chdir(current_dir) == -1 && error.Success()) - { - error.SetError(errno, eErrorTypePOSIX); - error.LogIfError(log, "unable to change current directory back to %s", - current_dir); - } -#endif + if (::chdir(current_dir) == -1 && error.Success()) { + error.SetError(errno, eErrorTypePOSIX); + error.LogIfError(log, "unable to change current directory back to %s", + current_dir); } +#endif + } - return error; + return error; } -bool -Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) -{ - if (info == NULL) - return false; - - posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); - - switch (info->GetAction()) - { - case FileAction::eFileActionNone: - error.Clear(); - break; - - case FileAction::eFileActionClose: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)"); - else - { - error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); - if (log && (error.Fail() || log)) - error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)", - static_cast<void *>(file_actions), info->GetFD()); - } - break; - - case FileAction::eFileActionDuplicate: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)"); - else if (info->GetActionArgument() == -1) - error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); - else - { - error.SetError( - ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), - eErrorTypePOSIX); - if (log && (error.Fail() || log)) - error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", - static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument()); - } - break; +bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, + Log *log, Error &error) { + if (info == NULL) + return false; - case FileAction::eFileActionOpen: - if (info->GetFD() == -1) - error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)"); - else - { - int oflag = info->GetActionArgument(); - - mode_t mode = 0; - - if (oflag & O_CREAT) - mode = 0640; - - error.SetError( - ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode), - eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, - "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)", - static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode); - } - break; + posix_spawn_file_actions_t *file_actions = + reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); + + switch (info->GetAction()) { + case FileAction::eFileActionNone: + error.Clear(); + break; + + case FileAction::eFileActionClose: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_addclose(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), + eErrorTypePOSIX); + if (log && (error.Fail() || log)) + error.PutToLog(log, + "posix_spawn_file_actions_addclose (action=%p, fd=%i)", + static_cast<void *>(file_actions), info->GetFD()); + } + break; + + case FileAction::eFileActionDuplicate: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_adddup2(...)"); + else if (info->GetActionArgument() == -1) + error.SetErrorString( + "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), + info->GetActionArgument()), + eErrorTypePOSIX); + if (log && (error.Fail() || log)) + error.PutToLog( + log, + "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", + static_cast<void *>(file_actions), info->GetFD(), + info->GetActionArgument()); + } + break; + + case FileAction::eFileActionOpen: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd in posix_spawn_file_actions_addopen(...)"); + else { + int oflag = info->GetActionArgument(); + + mode_t mode = 0; + + if (oflag & O_CREAT) + mode = 0640; + + error.SetError( + ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), + info->GetPath(), oflag, mode), + eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "posix_spawn_file_actions_addopen (action=%p, " + "fd=%i, path='%s', oflag=%i, mode=%i)", + static_cast<void *>(file_actions), info->GetFD(), + info->GetPath(), oflag, mode); } - return error.Success(); + break; + } + return error.Success(); } #endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__) -#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) +#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || + // defined (__GLIBC__) || defined(__NetBSD__) -#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || \ + defined(__NetBSD__) || defined(_WIN32) // The functions below implement process launching via posix_spawn() for Linux, // FreeBSD and NetBSD. -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - std::unique_ptr<ProcessLauncher> delegate_launcher; +Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) { + std::unique_ptr<ProcessLauncher> delegate_launcher; #if defined(_WIN32) - delegate_launcher.reset(new ProcessLauncherWindows()); + delegate_launcher.reset(new ProcessLauncherWindows()); #elif defined(__linux__) - delegate_launcher.reset(new ProcessLauncherLinux()); + delegate_launcher.reset(new ProcessLauncherLinux()); #else - delegate_launcher.reset(new ProcessLauncherPosix()); + delegate_launcher.reset(new ProcessLauncherPosix()); #endif - MonitoringProcessLauncher launcher(std::move(delegate_launcher)); + MonitoringProcessLauncher launcher(std::move(delegate_launcher)); - Error error; - HostProcess process = launcher.LaunchProcess(launch_info, error); + Error error; + HostProcess process = launcher.LaunchProcess(launch_info, error); - // TODO(zturner): It would be better if the entire HostProcess were returned instead of writing - // it into this structure. - launch_info.SetProcessID(process.GetProcessId()); + // TODO(zturner): It would be better if the entire HostProcess were returned + // instead of writing + // it into this structure. + launch_info.SetProcessID(process.GetProcessId()); - return error; + return error; } #endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) #ifndef _WIN32 -void -Host::Kill(lldb::pid_t pid, int signo) -{ - ::kill(pid, signo); -} +void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); } #endif -#if !defined (__APPLE__) -bool -Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) -{ - return false; +#if !defined(__APPLE__) +bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, + uint32_t line_no) { + return false; } -void -Host::SetCrashDescriptionWithFormat (const char *format, ...) -{ -} +void Host::SetCrashDescriptionWithFormat(const char *format, ...) {} -void -Host::SetCrashDescription (const char *description) -{ -} +void Host::SetCrashDescription(const char *description) {} #endif -const UnixSignalsSP & -Host::GetUnixSignals() -{ - static const auto s_unix_signals_sp = UnixSignals::Create(HostInfo::GetArchitecture()); - return s_unix_signals_sp; +const UnixSignalsSP &Host::GetUnixSignals() { + static const auto s_unix_signals_sp = + UnixSignals::Create(HostInfo::GetArchitecture()); + return s_unix_signals_sp; } diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index 3fcd31e..01ac870 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -24,405 +24,372 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" -#include <thread> #include <mutex> // std::once +#include <thread> using namespace lldb; using namespace lldb_private; -namespace -{ - //---------------------------------------------------------------------- - // The HostInfoBaseFields is a work around for windows not supporting - // static variables correctly in a thread safe way. Really each of the - // variables in HostInfoBaseFields should live in the functions in which - // they are used and each one should be static, but the work around is - // in place to avoid this restriction. Ick. - //---------------------------------------------------------------------- - - struct HostInfoBaseFields - { - ~HostInfoBaseFields() - { - if (m_lldb_process_tmp_dir.Exists()) - { - // Remove the LLDB temporary directory if we have one. Set "recurse" to - // true to all files that were created for the LLDB process can be cleaned up. - FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true); - } - } - - uint32_t m_number_cpus; - std::string m_vendor_string; - std::string m_os_string; - std::string m_host_triple; - - ArchSpec m_host_arch_32; - ArchSpec m_host_arch_64; - - FileSpec m_lldb_so_dir; - FileSpec m_lldb_support_exe_dir; - FileSpec m_lldb_headers_dir; - FileSpec m_lldb_python_dir; - FileSpec m_lldb_clang_resource_dir; - FileSpec m_lldb_system_plugin_dir; - FileSpec m_lldb_user_plugin_dir; - FileSpec m_lldb_process_tmp_dir; - FileSpec m_lldb_global_tmp_dir; - }; - - HostInfoBaseFields *g_fields = nullptr; +namespace { +//---------------------------------------------------------------------- +// The HostInfoBaseFields is a work around for windows not supporting +// static variables correctly in a thread safe way. Really each of the +// variables in HostInfoBaseFields should live in the functions in which +// they are used and each one should be static, but the work around is +// in place to avoid this restriction. Ick. +//---------------------------------------------------------------------- + +struct HostInfoBaseFields { + ~HostInfoBaseFields() { + if (m_lldb_process_tmp_dir.Exists()) { + // Remove the LLDB temporary directory if we have one. Set "recurse" to + // true to all files that were created for the LLDB process can be cleaned + // up. + FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true); + } + } + + uint32_t m_number_cpus; + std::string m_vendor_string; + std::string m_os_string; + std::string m_host_triple; + + ArchSpec m_host_arch_32; + ArchSpec m_host_arch_64; + + FileSpec m_lldb_so_dir; + FileSpec m_lldb_support_exe_dir; + FileSpec m_lldb_headers_dir; + FileSpec m_lldb_python_dir; + FileSpec m_lldb_clang_resource_dir; + FileSpec m_lldb_system_plugin_dir; + FileSpec m_lldb_user_plugin_dir; + FileSpec m_lldb_process_tmp_dir; + FileSpec m_lldb_global_tmp_dir; +}; + +HostInfoBaseFields *g_fields = nullptr; } -void -HostInfoBase::Initialize() -{ - g_fields = new HostInfoBaseFields(); +void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } + +void HostInfoBase::Terminate() { + delete g_fields; + g_fields = nullptr; } -void -HostInfoBase::Terminate() -{ - delete g_fields; - g_fields = nullptr; +uint32_t HostInfoBase::GetNumberCPUS() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_number_cpus = std::thread::hardware_concurrency(); + }); + return g_fields->m_number_cpus; } -uint32_t -HostInfoBase::GetNumberCPUS() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_number_cpus = std::thread::hardware_concurrency(); - }); - return g_fields->m_number_cpus; +uint32_t HostInfoBase::GetMaxThreadNameLength() { return 0; } + +llvm::StringRef HostInfoBase::GetVendorString() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_vendor_string = + HostInfo::GetArchitecture().GetTriple().getVendorName().str(); + }); + return g_fields->m_vendor_string; } -uint32_t -HostInfoBase::GetMaxThreadNameLength() -{ - return 0; +llvm::StringRef HostInfoBase::GetOSString() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_os_string = + std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); + }); + return g_fields->m_os_string; } -llvm::StringRef -HostInfoBase::GetVendorString() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_vendor_string = HostInfo::GetArchitecture().GetTriple().getVendorName().str(); - }); - return g_fields->m_vendor_string; +llvm::StringRef HostInfoBase::GetTargetTriple() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_host_triple = + HostInfo::GetArchitecture().GetTriple().getTriple(); + }); + return g_fields->m_host_triple; } -llvm::StringRef -HostInfoBase::GetOSString() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); - }); - return g_fields->m_os_string; +const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, + g_fields->m_host_arch_64); + }); + + // If an explicit 32 or 64-bit architecture was requested, return that. + if (arch_kind == eArchKind32) + return g_fields->m_host_arch_32; + if (arch_kind == eArchKind64) + return g_fields->m_host_arch_64; + + // Otherwise prefer the 64-bit architecture if it is valid. + return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 + : g_fields->m_host_arch_32; } -llvm::StringRef -HostInfoBase::GetTargetTriple() -{ +bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { + file_spec.Clear(); + +#if defined(LLDB_DISABLE_PYTHON) + if (type == lldb::ePathTypePythonDir) + return false; +#endif + + FileSpec *result = nullptr; + switch (type) { + case lldb::ePathTypeLLDBShlibDir: { static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple(); + static bool success = false; + std::call_once(g_once_flag, []() { + success = + HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", + g_fields->m_lldb_so_dir.GetPath().c_str()); }); - return g_fields->m_host_triple; -} - -const ArchSpec & -HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) -{ + if (success) + result = &g_fields->m_lldb_so_dir; + } break; + case lldb::ePathTypeSupportExecutableDir: { static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSupportExeDirectory( + g_fields->m_lldb_support_exe_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", + g_fields->m_lldb_support_exe_dir.GetPath().c_str()); }); + if (success) + result = &g_fields->m_lldb_support_exe_dir; + } break; + case lldb::ePathTypeHeaderDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", + g_fields->m_lldb_headers_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_headers_dir; + } break; + case lldb::ePathTypePythonDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", + g_fields->m_lldb_python_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_python_dir; + } break; + case lldb::ePathTypeClangDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = + HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", + g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_clang_resource_dir; + } break; + case lldb::ePathTypeLLDBSystemPlugins: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSystemPluginsDirectory( + g_fields->m_lldb_system_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", + g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_system_plugin_dir; + } break; + case lldb::ePathTypeLLDBUserPlugins: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeUserPluginsDirectory( + g_fields->m_lldb_user_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", + g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_user_plugin_dir; + } break; + case lldb::ePathTypeLLDBTempSystemDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeProcessTempFileDirectory( + g_fields->m_lldb_process_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf( + "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", + g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_process_tmp_dir; + } break; + case lldb::ePathTypeGlobalLLDBTempSystemDir: { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeGlobalTempFileDirectory( + g_fields->m_lldb_global_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(" + "ePathTypeGlobalLLDBTempSystemDir) => '%s'", + g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_global_tmp_dir; + } break; + } - // If an explicit 32 or 64-bit architecture was requested, return that. - if (arch_kind == eArchKind32) - return g_fields->m_host_arch_32; - if (arch_kind == eArchKind64) - return g_fields->m_host_arch_64; - - // Otherwise prefer the 64-bit architecture if it is valid. - return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32; + if (!result) + return false; + file_spec = *result; + return true; } -bool -HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) -{ - file_spec.Clear(); +bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { + // To get paths related to LLDB we get the path to the executable that + // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", + // on linux this is assumed to be the "lldb" main executable. If LLDB on + // linux is actually in a shared library (liblldb.so) then this function will + // need to be modified to "do the right thing". -#if defined(LLDB_DISABLE_PYTHON) - if (type == lldb::ePathTypePythonDir) - return false; -#endif + FileSpec lldb_file_spec( + Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>( + reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath)))); - FileSpec *result = nullptr; - switch (type) - { - case lldb::ePathTypeLLDBShlibDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_so_dir; - } - break; - case lldb::ePathTypeSupportExecutableDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", - g_fields->m_lldb_support_exe_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_support_exe_dir; - } - break; - case lldb::ePathTypeHeaderDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_headers_dir; - } - break; - case lldb::ePathTypePythonDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_python_dir; - } - break; - case lldb::ePathTypeClangDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_clang_resource_dir; - } - break; - case lldb::ePathTypeLLDBSystemPlugins: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", - g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_system_plugin_dir; - } - break; - case lldb::ePathTypeLLDBUserPlugins: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", - g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_user_plugin_dir; - } - break; - case lldb::ePathTypeLLDBTempSystemDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeProcessTempFileDirectory (g_fields->m_lldb_process_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_process_tmp_dir; - } - break; - case lldb::ePathTypeGlobalLLDBTempSystemDir: - { - static std::once_flag g_once_flag; - static bool success = false; - std::call_once(g_once_flag, []() { - success = HostInfo::ComputeGlobalTempFileDirectory (g_fields->m_lldb_global_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); - }); - if (success) - result = &g_fields->m_lldb_global_tmp_dir; - } - break; - } + // This is necessary because when running the testsuite the shlib might be a + // symbolic link inside the Python resource dir. + FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); - if (!result) - return false; - file_spec = *result; - return true; -} + // Remove the filename so that this FileSpec only represents the directory. + file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); -bool -HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) -{ - // To get paths related to LLDB we get the path to the executable that - // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", - // on linux this is assumed to be the "lldb" main executable. If LLDB on - // linux is actually in a shared library (liblldb.so) then this function will - // need to be modified to "do the right thing". - - FileSpec lldb_file_spec( - Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath)))); - - // This is necessary because when running the testsuite the shlib might be a symbolic link inside the Python resource dir. - FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); - - // Remove the filename so that this FileSpec only represents the directory. - file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); - - return (bool)file_spec.GetDirectory(); + return (bool)file_spec.GetDirectory(); } -bool -HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); +bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { + return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); } -bool -HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) -{ - FileSpec temp_file_spec; - if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) - return false; +bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { + FileSpec temp_file_spec; + if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) + return false; - std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; - temp_file_spec.AppendPathComponent(pid_str); - if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success()) - return false; + std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; + temp_file_spec.AppendPathComponent(pid_str); + if (!FileSystem::MakeDirectory(temp_file_spec, + eFilePermissionsDirectoryDefault) + .Success()) + return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); - return true; + file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + return true; } -bool -HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) -{ - llvm::SmallVector<char, 16> tmpdir; - llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); - file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); - return true; +bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + llvm::SmallVector<char, 16> tmpdir; + llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); + file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); + return true; } -bool -HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) -{ - file_spec.Clear(); +bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { + file_spec.Clear(); - FileSpec temp_file_spec; - if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) - return false; + FileSpec temp_file_spec; + if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) + return false; - temp_file_spec.AppendPathComponent("lldb"); - if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success()) - return false; + temp_file_spec.AppendPathComponent("lldb"); + if (!FileSystem::MakeDirectory(temp_file_spec, + eFilePermissionsDirectoryDefault) + .Success()) + return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); - return true; + file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + return true; } -bool -HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the header directory for all platforms. - return false; +bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the header directory for all + // platforms. + return false; } -bool -HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the system plugins directory for all platforms. - return false; +bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the system plugins directory for + // all platforms. + return false; } -bool -HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) -{ - return false; -} +bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; } -bool -HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) -{ - // TODO(zturner): Figure out how to compute the user plugins directory for all platforms. - return false; +bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { + // TODO(zturner): Figure out how to compute the user plugins directory for all + // platforms. + return false; } -void -HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - llvm::Triple triple(llvm::sys::getProcessTriple()); - - arch_32.Clear(); - arch_64.Clear(); - - switch (triple.getArch()) - { - default: - arch_32.SetTriple(triple); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::ppc64: - case llvm::Triple::x86_64: - arch_64.SetTriple(triple); - arch_32.SetTriple(triple.get32BitArchVariant()); - break; - - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::sparcv9: - case llvm::Triple::systemz: - arch_64.SetTriple(triple); - break; - } +void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + llvm::Triple triple(llvm::sys::getProcessTriple()); + + arch_32.Clear(); + arch_64.Clear(); + + switch (triple.getArch()) { + default: + arch_32.SetTriple(triple); + break; + + case llvm::Triple::aarch64: + case llvm::Triple::ppc64: + case llvm::Triple::x86_64: + arch_64.SetTriple(triple); + arch_32.SetTriple(triple.get32BitArchVariant()); + break; + + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::sparcv9: + case llvm::Triple::systemz: + arch_64.SetTriple(triple); + break; + } } diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index 9fea54d..c1a09e1 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/HostNativeThreadBase.h" #include "lldb/Core/Log.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/HostNativeThreadBase.h" #include "lldb/Host/ThisThread.h" #include "lldb/Host/ThreadLauncher.h" #include "llvm/ADT/StringExtras.h" @@ -18,65 +18,50 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD) - , m_result(0) -{ -} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread) - , m_result(0) -{ -} + : m_thread(thread), m_result(0) {} -lldb::thread_t -HostNativeThreadBase::GetSystemHandle() const -{ - return m_thread; +lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { + return m_thread; } -lldb::thread_result_t -HostNativeThreadBase::GetResult() const -{ - return m_result; +lldb::thread_result_t HostNativeThreadBase::GetResult() const { + return m_result; } -bool -HostNativeThreadBase::IsJoinable() const -{ - return m_thread != LLDB_INVALID_HOST_THREAD; +bool HostNativeThreadBase::IsJoinable() const { + return m_thread != LLDB_INVALID_HOST_THREAD; } -void -HostNativeThreadBase::Reset() -{ - m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; +void HostNativeThreadBase::Reset() { + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; } -lldb::thread_t -HostNativeThreadBase::Release() -{ - lldb::thread_t result = m_thread; - m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; +lldb::thread_t HostNativeThreadBase::Release() { + lldb::thread_t result = m_thread; + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; - return result; + return result; } lldb::thread_result_t -HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) -{ - ThreadLauncher::HostThreadCreateInfo *info = (ThreadLauncher::HostThreadCreateInfo *)arg; - ThisThread::SetName(info->thread_name.c_str(), HostInfo::GetMaxThreadNameLength()); +HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) { + ThreadLauncher::HostThreadCreateInfo *info = + (ThreadLauncher::HostThreadCreateInfo *)arg; + ThisThread::SetName(info->thread_name.c_str(), + HostInfo::GetMaxThreadNameLength()); - thread_func_t thread_fptr = info->thread_fptr; - thread_arg_t thread_arg = info->thread_arg; + thread_func_t thread_fptr = info->thread_fptr; + thread_arg_t thread_arg = info->thread_arg; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("thread created"); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("thread created"); - delete info; - return thread_fptr(thread_arg); + delete info; + return thread_fptr(thread_arg); } diff --git a/lldb/source/Host/common/HostProcess.cpp b/lldb/source/Host/common/HostProcess.cpp index 0262e1c..2d99d8e 100644 --- a/lldb/source/Host/common/HostProcess.cpp +++ b/lldb/source/Host/common/HostProcess.cpp @@ -7,59 +7,42 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeProcess.h" #include "lldb/Host/HostProcess.h" +#include "lldb/Host/HostNativeProcess.h" #include "lldb/Host/HostThread.h" using namespace lldb; using namespace lldb_private; -HostProcess::HostProcess() - : m_native_process(new HostNativeProcess) -{ -} +HostProcess::HostProcess() : m_native_process(new HostNativeProcess) {} HostProcess::HostProcess(lldb::process_t process) - : m_native_process(new HostNativeProcess(process)) -{ -} + : m_native_process(new HostNativeProcess(process)) {} -HostProcess::~HostProcess() -{ -} +HostProcess::~HostProcess() {} -Error HostProcess::Terminate() -{ - return m_native_process->Terminate(); -} +Error HostProcess::Terminate() { return m_native_process->Terminate(); } -Error HostProcess::GetMainModule(FileSpec &file_spec) const -{ - return m_native_process->GetMainModule(file_spec); +Error HostProcess::GetMainModule(FileSpec &file_spec) const { + return m_native_process->GetMainModule(file_spec); } -lldb::pid_t HostProcess::GetProcessId() const -{ - return m_native_process->GetProcessId(); +lldb::pid_t HostProcess::GetProcessId() const { + return m_native_process->GetProcessId(); } -bool HostProcess::IsRunning() const -{ - return m_native_process->IsRunning(); -} +bool HostProcess::IsRunning() const { return m_native_process->IsRunning(); } HostThread -HostProcess::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - return m_native_process->StartMonitoring(callback, monitor_signals); +HostProcess::StartMonitoring(const Host::MonitorChildProcessCallback &callback, + bool monitor_signals) { + return m_native_process->StartMonitoring(callback, monitor_signals); } -HostNativeProcessBase &HostProcess::GetNativeProcess() -{ - return *m_native_process; +HostNativeProcessBase &HostProcess::GetNativeProcess() { + return *m_native_process; } -const HostNativeProcessBase &HostProcess::GetNativeProcess() const -{ - return *m_native_process; +const HostNativeProcessBase &HostProcess::GetNativeProcess() const { + return *m_native_process; } diff --git a/lldb/source/Host/common/HostThread.cpp b/lldb/source/Host/common/HostThread.cpp index 7757477..738b7ef 100644 --- a/lldb/source/Host/common/HostThread.cpp +++ b/lldb/source/Host/common/HostThread.cpp @@ -7,72 +7,41 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/HostNativeThread.h" using namespace lldb; using namespace lldb_private; -HostThread::HostThread() - : m_native_thread(new HostNativeThread) -{ -} +HostThread::HostThread() : m_native_thread(new HostNativeThread) {} HostThread::HostThread(lldb::thread_t thread) - : m_native_thread(new HostNativeThread(thread)) -{ -} + : m_native_thread(new HostNativeThread(thread)) {} -Error -HostThread::Join(lldb::thread_result_t *result) -{ - return m_native_thread->Join(result); +Error HostThread::Join(lldb::thread_result_t *result) { + return m_native_thread->Join(result); } -Error -HostThread::Cancel() -{ - return m_native_thread->Cancel(); -} +Error HostThread::Cancel() { return m_native_thread->Cancel(); } -void -HostThread::Reset() -{ - return m_native_thread->Reset(); -} +void HostThread::Reset() { return m_native_thread->Reset(); } -lldb::thread_t -HostThread::Release() -{ - return m_native_thread->Release(); -} +lldb::thread_t HostThread::Release() { return m_native_thread->Release(); } -bool -HostThread::IsJoinable() const -{ - return m_native_thread->IsJoinable(); -} +bool HostThread::IsJoinable() const { return m_native_thread->IsJoinable(); } -HostNativeThread & -HostThread::GetNativeThread() -{ - return static_cast<HostNativeThread &>(*m_native_thread); +HostNativeThread &HostThread::GetNativeThread() { + return static_cast<HostNativeThread &>(*m_native_thread); } -const HostNativeThread & -HostThread::GetNativeThread() const -{ - return static_cast<const HostNativeThread &>(*m_native_thread); +const HostNativeThread &HostThread::GetNativeThread() const { + return static_cast<const HostNativeThread &>(*m_native_thread); } -lldb::thread_result_t -HostThread::GetResult() const -{ - return m_native_thread->GetResult(); +lldb::thread_result_t HostThread::GetResult() const { + return m_native_thread->GetResult(); } -bool -HostThread::EqualsThread(lldb::thread_t thread) const -{ - return m_native_thread->GetSystemHandle() == thread; +bool HostThread::EqualsThread(lldb::thread_t thread) const { + return m_native_thread->GetSystemHandle() == thread; } diff --git a/lldb/source/Host/common/LockFileBase.cpp b/lldb/source/Host/common/LockFileBase.cpp index f746945..b30acc5d 100644 --- a/lldb/source/Host/common/LockFileBase.cpp +++ b/lldb/source/Host/common/LockFileBase.cpp @@ -12,113 +12,71 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error -AlreadyLocked () -{ - return Error ("Already locked"); -} - -Error -NotLocked () -{ - return Error ("Not locked"); -} +Error AlreadyLocked() { return Error("Already locked"); } +Error NotLocked() { return Error("Not locked"); } } -LockFileBase::LockFileBase (int fd) : - m_fd (fd), - m_locked (false), - m_start (0), - m_len (0) -{ - -} +LockFileBase::LockFileBase(int fd) + : m_fd(fd), m_locked(false), m_start(0), m_len(0) {} -bool -LockFileBase::IsLocked () const -{ - return m_locked; -} +bool LockFileBase::IsLocked() const { return m_locked; } -Error -LockFileBase::WriteLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoWriteLock (start, len); - }, start, len); +Error LockFileBase::WriteLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoWriteLock(start, len); }, + start, len); } -Error -LockFileBase::TryWriteLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoTryWriteLock (start, len); - }, start, len); +Error LockFileBase::TryWriteLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoTryWriteLock(start, len); }, + start, len); } -Error -LockFileBase::ReadLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoReadLock (start, len); - }, start, len); +Error LockFileBase::ReadLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoReadLock(start, len); }, + start, len); } -Error -LockFileBase::TryReadLock (const uint64_t start, const uint64_t len) -{ - return DoLock ([&] (const uint64_t start, const uint64_t len) - { - return DoTryReadLock (start, len); - }, start, len); - +Error LockFileBase::TryReadLock(const uint64_t start, const uint64_t len) { + return DoLock([&](const uint64_t start, + const uint64_t len) { return DoTryReadLock(start, len); }, + start, len); } -Error -LockFileBase::Unlock () -{ - if (!IsLocked ()) - return NotLocked (); - - const auto error = DoUnlock (); - if (error.Success ()) - { - m_locked = false; - m_start = 0; - m_len = 0; - } - return error; +Error LockFileBase::Unlock() { + if (!IsLocked()) + return NotLocked(); + + const auto error = DoUnlock(); + if (error.Success()) { + m_locked = false; + m_start = 0; + m_len = 0; + } + return error; } -bool -LockFileBase::IsValidFile () const -{ - return m_fd != -1; -} +bool LockFileBase::IsValidFile() const { return m_fd != -1; } -Error -LockFileBase::DoLock (const Locker &locker, const uint64_t start, const uint64_t len) -{ - if (!IsValidFile ()) - return Error("File is invalid"); +Error LockFileBase::DoLock(const Locker &locker, const uint64_t start, + const uint64_t len) { + if (!IsValidFile()) + return Error("File is invalid"); - if (IsLocked ()) - return AlreadyLocked (); + if (IsLocked()) + return AlreadyLocked(); - const auto error = locker (start, len); - if (error.Success ()) - { - m_locked = true; - m_start = start; - m_len = len; - } + const auto error = locker(start, len); + if (error.Success()) { + m_locked = true; + m_start = start; + m_len = len; + } - return error; + return error; } diff --git a/lldb/source/Host/common/MonitoringProcessLauncher.cpp b/lldb/source/Host/common/MonitoringProcessLauncher.cpp index 2845155..cb342e7 100644 --- a/lldb/source/Host/common/MonitoringProcessLauncher.cpp +++ b/lldb/source/Host/common/MonitoringProcessLauncher.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" @@ -20,81 +20,73 @@ using namespace lldb; using namespace lldb_private; -MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher) - : m_delegate_launcher(std::move(delegate_launcher)) -{ -} +MonitoringProcessLauncher::MonitoringProcessLauncher( + std::unique_ptr<ProcessLauncher> delegate_launcher) + : m_delegate_launcher(std::move(delegate_launcher)) {} HostProcess -MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - ProcessLaunchInfo resolved_info(launch_info); +MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + ProcessLaunchInfo resolved_info(launch_info); - error.Clear(); - char exe_path[PATH_MAX]; + error.Clear(); + char exe_path[PATH_MAX]; - PlatformSP host_platform_sp(Platform::GetHostPlatform()); + PlatformSP host_platform_sp(Platform::GetHostPlatform()); - const ArchSpec &arch_spec = resolved_info.GetArchitecture(); + const ArchSpec &arch_spec = resolved_info.GetArchitecture(); - FileSpec exe_spec(resolved_info.GetExecutableFile()); + FileSpec exe_spec(resolved_info.GetExecutableFile()); - FileSpec::FileType file_type = exe_spec.GetFileType(); - if (file_type != FileSpec::eFileTypeRegular) - { - ModuleSpec module_spec(exe_spec, arch_spec); - lldb::ModuleSP exe_module_sp; - error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); + FileSpec::FileType file_type = exe_spec.GetFileType(); + if (file_type != FileSpec::eFileTypeRegular) { + ModuleSpec module_spec(exe_spec, arch_spec); + lldb::ModuleSP exe_module_sp; + error = + host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); - if (error.Fail()) - return HostProcess(); + if (error.Fail()) + return HostProcess(); - if (exe_module_sp) - exe_spec = exe_module_sp->GetFileSpec(); - } + if (exe_module_sp) + exe_spec = exe_module_sp->GetFileSpec(); + } - if (exe_spec.Exists()) - { - exe_spec.GetPath(exe_path, sizeof(exe_path)); - } - else - { - resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); - return HostProcess(); - } - - resolved_info.SetExecutableFile(exe_spec, false); - assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); + if (exe_spec.Exists()) { + exe_spec.GetPath(exe_path, sizeof(exe_path)); + } else { + resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + return HostProcess(); + } - HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); + resolved_info.SetExecutableFile(exe_spec, false); + assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); - if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + HostProcess process = + m_delegate_launcher->LaunchProcess(resolved_info, error); - Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); + if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - bool monitor_signals = false; - if (callback) - { - // If the ProcessLaunchInfo specified a callback, use that. - monitor_signals = launch_info.GetMonitorSignals(); - } - else - { - callback = Process::SetProcessExitStatus; - } + Host::MonitorChildProcessCallback callback = + launch_info.GetMonitorProcessCallback(); - process.StartMonitoring(callback, monitor_signals); - if (log) - log->PutCString("started monitoring child process."); + bool monitor_signals = false; + if (callback) { + // If the ProcessLaunchInfo specified a callback, use that. + monitor_signals = launch_info.GetMonitorSignals(); + } else { + callback = Process::SetProcessExitStatus; } - else - { - // Invalid process ID, something didn't go well - if (error.Success()) - error.SetErrorString("process launch failed for unknown reasons"); - } - return process; + + process.StartMonitoring(callback, monitor_signals); + if (log) + log->PutCString("started monitoring child process."); + } else { + // Invalid process ID, something didn't go well + if (error.Success()) + error.SetErrorString("process launch failed for unknown reasons"); + } + return process; } diff --git a/lldb/source/Host/common/NativeBreakpoint.cpp b/lldb/source/Host/common/NativeBreakpoint.cpp index 622b4ea..d61a2f5 100644 --- a/lldb/source/Host/common/NativeBreakpoint.cpp +++ b/lldb/source/Host/common/NativeBreakpoint.cpp @@ -9,108 +9,101 @@ #include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/lldb-defines.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/lldb-defines.h" using namespace lldb_private; -NativeBreakpoint::NativeBreakpoint (lldb::addr_t addr) : - m_addr (addr), - m_ref_count (1), - m_enabled (true) -{ - assert (addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address"); +NativeBreakpoint::NativeBreakpoint(lldb::addr_t addr) + : m_addr(addr), m_ref_count(1), m_enabled(true) { + assert(addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address"); } -NativeBreakpoint::~NativeBreakpoint () -{ -} +NativeBreakpoint::~NativeBreakpoint() {} -void -NativeBreakpoint::AddRef () -{ - ++m_ref_count; +void NativeBreakpoint::AddRef() { + ++m_ref_count; - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " bumped up, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " bumped up, new ref count %" PRIu32, + __FUNCTION__, m_addr, m_ref_count); } -int32_t -NativeBreakpoint::DecRef () -{ - --m_ref_count; +int32_t NativeBreakpoint::DecRef() { + --m_ref_count; - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " ref count decremented, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " ref count decremented, new ref count %" PRIu32, + __FUNCTION__, m_addr, m_ref_count); - return m_ref_count; + return m_ref_count; } -Error -NativeBreakpoint::Enable () -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - - if (m_enabled) - { - // We're already enabled. Just log and exit. - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already enabled, ignoring.", __FUNCTION__, m_addr); - return Error (); - } +Error NativeBreakpoint::Enable() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // Log and enable. + if (m_enabled) { + // We're already enabled. Just log and exit. if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", __FUNCTION__, m_addr); - - Error error = DoEnable (); - if (error.Success ()) - { - m_enabled = true; - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", __FUNCTION__, m_addr); - } - else - { - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ()); - } - - return error; -} + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " already enabled, ignoring.", + __FUNCTION__, m_addr); + return Error(); + } + + // Log and enable. + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", + __FUNCTION__, m_addr); + + Error error = DoEnable(); + if (error.Success()) { + m_enabled = true; + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", + __FUNCTION__, m_addr); + } else { + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", + __FUNCTION__, m_addr, error.AsCString()); + } -Error -NativeBreakpoint::Disable () -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + return error; +} - if (!m_enabled) - { - // We're already disabled. Just log and exit. - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already disabled, ignoring.", __FUNCTION__, m_addr); - return Error (); - } +Error NativeBreakpoint::Disable() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // Log and disable. + if (!m_enabled) { + // We're already disabled. Just log and exit. if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", __FUNCTION__, m_addr); - - Error error = DoDisable (); - if (error.Success ()) - { - m_enabled = false; - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", __FUNCTION__, m_addr); - } - else - { - if (log) - log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ()); - } - - return error; + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 + " already disabled, ignoring.", + __FUNCTION__, m_addr); + return Error(); + } + + // Log and disable. + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", + __FUNCTION__, m_addr); + + Error error = DoDisable(); + if (error.Success()) { + m_enabled = false; + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", + __FUNCTION__, m_addr); + } else { + if (log) + log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", + __FUNCTION__, m_addr, error.AsCString()); + } + + return error; } diff --git a/lldb/source/Host/common/NativeBreakpointList.cpp b/lldb/source/Host/common/NativeBreakpointList.cpp index 67873a0..a76d72ff 100644 --- a/lldb/source/Host/common/NativeBreakpointList.cpp +++ b/lldb/source/Host/common/NativeBreakpointList.cpp @@ -17,204 +17,213 @@ using namespace lldb; using namespace lldb_private; -NativeBreakpointList::NativeBreakpointList() : m_mutex() -{ -} +NativeBreakpointList::NativeBreakpointList() : m_mutex() {} + +Error NativeBreakpointList::AddRef(lldb::addr_t addr, size_t size_hint, + bool hardware, + CreateBreakpointFunc create_func) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find(addr); + if (iter != m_breakpoints.end()) { + // Yes - bump up ref count. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- already enabled, upping ref count", + __FUNCTION__, addr); -Error -NativeBreakpointList::AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + iter->second->AddRef(); + return Error(); + } + + // Create a new breakpoint using the given create func. + if (log) + log->Printf( + "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + NativeBreakpointSP breakpoint_sp; + Error error = create_func(addr, size_hint, hardware, breakpoint_sp); + if (error.Fail()) { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + log->Printf( + "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 + ", size_hint = %lu, hardware = %s -- FAILED: %s", + __FUNCTION__, addr, size_hint, hardware ? "true" : "false", + error.AsCString()); + return error; + } - std::lock_guard<std::recursive_mutex> guard(m_mutex); + // Remember the breakpoint. + assert(breakpoint_sp && "NativeBreakpoint create function succeeded but " + "returned NULL breakpoint"); + m_breakpoints.insert(BreakpointMap::value_type(addr, breakpoint_sp)); - // Check if the breakpoint is already set. - auto iter = m_breakpoints.find (addr); - if (iter != m_breakpoints.end ()) - { - // Yes - bump up ref count. - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already enabled, upping ref count", __FUNCTION__, addr); + return error; +} - iter->second->AddRef (); - return Error (); - } +Error NativeBreakpointList::DecRef(lldb::addr_t addr) { + Error error; - // Create a new breakpoint using the given create func. - if (log) - log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - NativeBreakpointSP breakpoint_sp; - Error error = create_func (addr, size_hint, hardware, breakpoint_sp); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s -- FAILED: %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false", error.AsCString ()); - return error; - } + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - // Remember the breakpoint. - assert (breakpoint_sp && "NativeBreakpoint create function succeeded but returned NULL breakpoint"); - m_breakpoints.insert (BreakpointMap::value_type (addr, breakpoint_sp)); + std::lock_guard<std::recursive_mutex> guard(m_mutex); + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + error.SetErrorString("breakpoint not found"); return error; -} + } -Error -NativeBreakpointList::DecRef (lldb::addr_t addr) -{ - Error error; + // Decrement ref count. + const int32_t new_ref_count = iter->second->DecRef(); + assert(new_ref_count >= 0 && "NativeBreakpoint ref count went negative"); - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (new_ref_count > 0) { + // Still references to this breakpoint. Leave it alone. if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // Check if the breakpoint is already set. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - error.SetErrorString ("breakpoint not found"); - return error; - } - - // Decrement ref count. - const int32_t new_ref_count = iter->second->DecRef (); - assert (new_ref_count >= 0 && "NativeBreakpoint ref count went negative"); + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- new breakpoint ref count %" PRIu32, + __FUNCTION__, addr, new_ref_count); + return error; + } - if (new_ref_count > 0) - { - // Still references to this breakpoint. Leave it alone. - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- new breakpoint ref count %" PRIu32, __FUNCTION__, addr, new_ref_count); - return error; - } + // Breakpoint has no more references. Disable it if it's not + // already disabled. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removing due to no remaining references", + __FUNCTION__, addr); - // Breakpoint has no more references. Disable it if it's not - // already disabled. + // If it's enabled, we need to disable it. + if (iter->second->IsEnabled()) { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", __FUNCTION__, addr); - - // If it's enabled, we need to disable it. - if (iter->second->IsEnabled ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- currently enabled, now disabling", __FUNCTION__, addr); - error = iter->second->Disable (); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removal FAILED: %s", __FUNCTION__, addr, error.AsCString ()); - // Continue since we still want to take it out of the breakpoint list. - } - } - else - { - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already disabled, nothing to do", __FUNCTION__, addr); + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- currently enabled, now disabling", + __FUNCTION__, addr); + error = iter->second->Disable(); + if (error.Fail()) { + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removal FAILED: %s", + __FUNCTION__, addr, error.AsCString()); + // Continue since we still want to take it out of the breakpoint list. } - - // Take the breakpoint out of the list. + } else { if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removed from breakpoint map", __FUNCTION__, addr); - - m_breakpoints.erase (iter); - return error; + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- already disabled, nothing to do", + __FUNCTION__, addr); + } + + // Take the breakpoint out of the list. + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 + " -- removed from breakpoint map", + __FUNCTION__, addr); + + m_breakpoints.erase(iter); + return error; } -Error -NativeBreakpointList::EnableBreakpoint (lldb::addr_t addr) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - return Error ("breakpoint not found"); - } +Error NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - // Enable it. - return iter->second->Enable (); -} + std::lock_guard<std::recursive_mutex> guard(m_mutex); -Error -NativeBreakpointList::DisableBreakpoint (lldb::addr_t addr) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); - return Error ("breakpoint not found"); - } + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + return Error("breakpoint not found"); + } - // Disable it. - return iter->second->Disable (); + // Enable it. + return iter->second->Enable(); } -Error -NativeBreakpointList::GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); +Error NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); - std::lock_guard<std::recursive_mutex> guard(m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find (addr); - if (iter == m_breakpoints.end ()) - { - // Not found! - breakpoint_sp.reset (); - return Error ("breakpoint not found"); - } + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", + __FUNCTION__, addr); + return Error("breakpoint not found"); + } - // Disable it. - breakpoint_sp = iter->second; - return Error (); + // Disable it. + return iter->second->Disable(); } -Error -NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const -{ - for (const auto &map : m_breakpoints) - { - lldb::addr_t bp_addr = map.first; - // Breapoint not in range, ignore - if (bp_addr < addr || addr + size <= bp_addr) - continue; - const auto &bp_sp = map.second; - // Not software breakpoint, ignore - if (!bp_sp->IsSoftwareBreakpoint()) - continue; - auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp); - auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr; - auto saved_opcodes = software_bp_sp->m_saved_opcodes; - auto opcode_size = software_bp_sp->m_opcode_size; - ::memcpy(opcode_addr, saved_opcodes, opcode_size); - } - return Error(); +Error NativeBreakpointList::GetBreakpoint(lldb::addr_t addr, + NativeBreakpointSP &breakpoint_sp) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find(addr); + if (iter == m_breakpoints.end()) { + // Not found! + breakpoint_sp.reset(); + return Error("breakpoint not found"); + } + + // Disable it. + breakpoint_sp = iter->second; + return Error(); +} + +Error NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, + size_t size) const { + for (const auto &map : m_breakpoints) { + lldb::addr_t bp_addr = map.first; + // Breapoint not in range, ignore + if (bp_addr < addr || addr + size <= bp_addr) + continue; + const auto &bp_sp = map.second; + // Not software breakpoint, ignore + if (!bp_sp->IsSoftwareBreakpoint()) + continue; + auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp); + auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr; + auto saved_opcodes = software_bp_sp->m_saved_opcodes; + auto opcode_size = software_bp_sp->m_opcode_size; + ::memcpy(opcode_addr, saved_opcodes, opcode_size); + } + return Error(); } diff --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp index bdc58fb..d77b8b2 100644 --- a/lldb/source/Host/common/NativeProcessProtocol.cpp +++ b/lldb/source/Host/common/NativeProcessProtocol.cpp @@ -9,7 +9,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/lldb-enumerations.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" @@ -21,6 +20,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -30,458 +30,403 @@ using namespace lldb_private; // ----------------------------------------------------------------------------- NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) - : m_pid(pid), - m_threads(), - m_current_thread_id(LLDB_INVALID_THREAD_ID), - m_threads_mutex(), - m_state(lldb::eStateInvalid), - m_state_mutex(), - m_exit_type(eExitTypeInvalid), - m_exit_status(0), - m_exit_description(), - m_delegates_mutex(), - m_delegates(), - m_breakpoint_list(), - m_watchpoint_list(), - m_terminal_fd(-1), - m_stop_id(0) -{ -} - -lldb_private::Error -NativeProcessProtocol::Interrupt () -{ - Error error; -#if !defined (SIGSTOP) - error.SetErrorString ("local host does not support signaling"); - return error; + : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), + m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), + m_exit_type(eExitTypeInvalid), m_exit_status(0), m_exit_description(), + m_delegates_mutex(), m_delegates(), m_breakpoint_list(), + m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} + +lldb_private::Error NativeProcessProtocol::Interrupt() { + Error error; +#if !defined(SIGSTOP) + error.SetErrorString("local host does not support signaling"); + return error; #else - return Signal (SIGSTOP); + return Signal(SIGSTOP); #endif } lldb_private::Error -NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) -{ - // Default: not implemented. - return Error ("not implemented"); +NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + // Default: not implemented. + return Error("not implemented"); } -bool -NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description) -{ - if (m_state == lldb::eStateExited) - { - *exit_type = m_exit_type; - *status = m_exit_status; - exit_description = m_exit_description; - return true; - } +bool NativeProcessProtocol::GetExitStatus(ExitType *exit_type, int *status, + std::string &exit_description) { + if (m_state == lldb::eStateExited) { + *exit_type = m_exit_type; + *status = m_exit_status; + exit_description = m_exit_description; + return true; + } - *status = 0; - return false; + *status = 0; + return false; } -bool -NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange) -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called", - __FUNCTION__, - exit_type, - status, +bool NativeProcessProtocol::SetExitStatus(ExitType exit_type, int status, + const char *exit_description, + bool bNotifyStateChange) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessProtocol::%s(%d, %d, %s, %s) called", + __FUNCTION__, exit_type, status, exit_description ? exit_description : "nullptr", bNotifyStateChange ? "true" : "false"); - // Exit status already set - if (m_state == lldb::eStateExited) - { - if (log) - log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status); - return false; - } + // Exit status already set + if (m_state == lldb::eStateExited) { + if (log) + log->Printf("NativeProcessProtocol::%s exit status already set to %d, " + "ignoring new set to %d", + __FUNCTION__, m_exit_status, status); + return false; + } - m_state = lldb::eStateExited; + m_state = lldb::eStateExited; - m_exit_type = exit_type; - m_exit_status = status; - if (exit_description && exit_description[0]) - m_exit_description = exit_description; - else - m_exit_description.clear(); + m_exit_type = exit_type; + m_exit_status = status; + if (exit_description && exit_description[0]) + m_exit_description = exit_description; + else + m_exit_description.clear(); - if (bNotifyStateChange) - SynchronouslyNotifyProcessStateChanged (lldb::eStateExited); + if (bNotifyStateChange) + SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); - return true; + return true; } -NativeThreadProtocolSP -NativeProcessProtocol::GetThreadAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - if (idx < m_threads.size ()) - return m_threads[idx]; - return NativeThreadProtocolSP (); +NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + if (idx < m_threads.size()) + return m_threads[idx]; + return NativeThreadProtocolSP(); } NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByIDUnlocked (lldb::tid_t tid) -{ - for (auto thread_sp : m_threads) - { - if (thread_sp->GetID() == tid) - return thread_sp; - } - return NativeThreadProtocolSP (); +NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { + for (auto thread_sp : m_threads) { + if (thread_sp->GetID() == tid) + return thread_sp; + } + return NativeThreadProtocolSP(); } -NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) -{ - std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - return GetThreadByIDUnlocked (tid); +NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + return GetThreadByIDUnlocked(tid); } -bool -NativeProcessProtocol::IsAlive () const -{ - return m_state != eStateDetached - && m_state != eStateExited - && m_state != eStateInvalid - && m_state != eStateUnloaded; +bool NativeProcessProtocol::IsAlive() const { + return m_state != eStateDetached && m_state != eStateExited && + m_state != eStateInvalid && m_state != eStateUnloaded; } -bool -NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const -{ - ArchSpec process_arch; - if (!GetArchitecture (process_arch)) - return false; - byte_order = process_arch.GetByteOrder (); - return true; +bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { + ArchSpec process_arch; + if (!GetArchitecture(process_arch)) + return false; + byte_order = process_arch.GetByteOrder(); + return true; } -const NativeWatchpointList::WatchpointMap& -NativeProcessProtocol::GetWatchpointMap () const -{ - return m_watchpoint_list.GetWatchpointMap(); +const NativeWatchpointList::WatchpointMap & +NativeProcessProtocol::GetWatchpointMap() const { + return m_watchpoint_list.GetWatchpointMap(); } -uint32_t -NativeProcessProtocol::GetMaxWatchpoints () const -{ - // This default implementation will return the number of - // *hardware* breakpoints available. MacOSX and other OS - // implementations that support software breakpoints will want to - // override this correctly for their implementation. - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - // get any thread - NativeThreadProtocolSP thread_sp (const_cast<NativeProcessProtocol*> (this)->GetThreadAtIndex (0)); - if (!thread_sp) - { - if (log) - log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__); - return 0; - } +uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { + // This default implementation will return the number of + // *hardware* breakpoints available. MacOSX and other OS + // implementations that support software breakpoints will want to + // override this correctly for their implementation. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // get any thread + NativeThreadProtocolSP thread_sp( + const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); + if (!thread_sp) { + if (log) + log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " + "grab a NativeRegisterContext!", + __FUNCTION__); + return 0; + } + + NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); + if (!reg_ctx_sp) { + if (log) + log->Warning("NativeProcessProtocol::%s (): failed to get a " + "RegisterContextNativeProcess from the first thread!", + __FUNCTION__); + return 0; + } + + return reg_ctx_sp->NumSupportedHardwareWatchpoints(); +} - NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ()); - if (!reg_ctx_sp) - { +Error NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, + bool hardware) { + // This default implementation assumes setting the watchpoint for + // the process will require setting the watchpoint for each of the + // threads. Furthermore, it will track watchpoints set for the + // process and will add them to each thread that is attached to + // via the (FIXME implement) OnThreadAttached () method. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Update the thread list + UpdateThreads(); + + // Keep track of the threads we successfully set the watchpoint + // for. If one of the thread watchpoint setting operations fails, + // back off and remove the watchpoint for all the threads that + // were successfully set so we get back to a consistent state. + std::vector<NativeThreadProtocolSP> watchpoint_established_threads; + + // Tell each thread to set a watchpoint. In the event that + // hardware watchpoints are requested but the SetWatchpoint fails, + // try to set a software watchpoint as a fallback. It's + // conceivable that if there are more threads than hardware + // watchpoints available, some of the threads will fail to set + // hardware watchpoints while software ones may be available. + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + Error thread_error = + thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); + if (thread_error.Fail() && hardware) { + // Try software watchpoints since we failed on hardware watchpoint setting + // and we may have just run out of hardware watchpoints. + thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); + if (thread_error.Success()) { if (log) - log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__); - return 0; + log->Warning( + "hardware watchpoint requested but software watchpoint set"); + } } - return reg_ctx_sp->NumSupportedHardwareWatchpoints (); -} - -Error -NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) -{ - // This default implementation assumes setting the watchpoint for - // the process will require setting the watchpoint for each of the - // threads. Furthermore, it will track watchpoints set for the - // process and will add them to each thread that is attached to - // via the (FIXME implement) OnThreadAttached () method. - - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - // Update the thread list - UpdateThreads (); - - // Keep track of the threads we successfully set the watchpoint - // for. If one of the thread watchpoint setting operations fails, - // back off and remove the watchpoint for all the threads that - // were successfully set so we get back to a consistent state. - std::vector<NativeThreadProtocolSP> watchpoint_established_threads; - - // Tell each thread to set a watchpoint. In the event that - // hardware watchpoints are requested but the SetWatchpoint fails, - // try to set a software watchpoint as a fallback. It's - // conceivable that if there are more threads than hardware - // watchpoints available, some of the threads will fail to set - // hardware watchpoints while software ones may be available. - std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware); - if (thread_error.Fail () && hardware) - { - // Try software watchpoints since we failed on hardware watchpoint setting - // and we may have just run out of hardware watchpoints. - thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false); - if (thread_error.Success ()) - { - if (log) - log->Warning ("hardware watchpoint requested but software watchpoint set"); - } + if (thread_error.Success()) { + // Remember that we set this watchpoint successfully in + // case we need to clear it later. + watchpoint_established_threads.push_back(thread_sp); + } else { + // Unset the watchpoint for each thread we successfully + // set so that we get back to a consistent state of "not + // set" for the watchpoint. + for (auto unwatch_thread_sp : watchpoint_established_threads) { + Error remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); + if (remove_error.Fail() && log) { + log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " + "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", + __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), + remove_error.AsCString()); } + } - if (thread_error.Success ()) - { - // Remember that we set this watchpoint successfully in - // case we need to clear it later. - watchpoint_established_threads.push_back (thread_sp); - } - else - { - // Unset the watchpoint for each thread we successfully - // set so that we get back to a consistent state of "not - // set" for the watchpoint. - for (auto unwatch_thread_sp : watchpoint_established_threads) - { - Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr); - if (remove_error.Fail () && log) - { - log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ()); - } - } - - return thread_error; - } + return thread_error; } - return m_watchpoint_list.Add (addr, size, watch_flags, hardware); + } + return m_watchpoint_list.Add(addr, size, watch_flags, hardware); } -Error -NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) -{ - // Update the thread list - UpdateThreads (); - - Error overall_error; - - std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - const Error thread_error = thread_sp->RemoveWatchpoint (addr); - if (thread_error.Fail ()) - { - // Keep track of the first thread error if any threads - // fail. We want to try to remove the watchpoint from - // every thread, though, even if one or more have errors. - if (!overall_error.Fail ()) - overall_error = thread_error; - } - } - const Error error = m_watchpoint_list.Remove(addr); - return overall_error.Fail() ? overall_error : error; -} +Error NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { + // Update the thread list + UpdateThreads(); -bool -NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate) -{ - std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); - if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ()) - return false; + Error overall_error; - m_delegates.push_back (&native_delegate); - native_delegate.InitializeDelegate (this); - return true; + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + const Error thread_error = thread_sp->RemoveWatchpoint(addr); + if (thread_error.Fail()) { + // Keep track of the first thread error if any threads + // fail. We want to try to remove the watchpoint from + // every thread, though, even if one or more have errors. + if (!overall_error.Fail()) + overall_error = thread_error; + } + } + const Error error = m_watchpoint_list.Remove(addr); + return overall_error.Fail() ? overall_error : error; } -bool -NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate) -{ - std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); - - const auto initial_size = m_delegates.size (); - m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ()); +bool NativeProcessProtocol::RegisterNativeDelegate( + NativeDelegate &native_delegate) { + std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); + if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != + m_delegates.end()) + return false; - // We removed the delegate if the count of delegates shrank after - // removing all copies of the given native_delegate from the vector. - return m_delegates.size () < initial_size; + m_delegates.push_back(&native_delegate); + native_delegate.InitializeDelegate(this); + return true; } -void -NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); +bool NativeProcessProtocol::UnregisterNativeDelegate( + NativeDelegate &native_delegate) { + std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); - std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); - for (auto native_delegate: m_delegates) - native_delegate->ProcessStateChanged (this, state); + const auto initial_size = m_delegates.size(); + m_delegates.erase( + remove(m_delegates.begin(), m_delegates.end(), &native_delegate), + m_delegates.end()); - if (log) - { - if (!m_delegates.empty ()) - { - log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64, - __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); - } - else - { - log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates", - __FUNCTION__, lldb_private::StateAsCString (state), GetID ()); - } - } + // We removed the delegate if the count of delegates shrank after + // removing all copies of the given native_delegate from the vector. + return m_delegates.size() < initial_size; } -void -NativeProcessProtocol::NotifyDidExec () -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); - - { - std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); - for (auto native_delegate: m_delegates) - native_delegate->DidExec (this); +void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( + lldb::StateType state) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); + for (auto native_delegate : m_delegates) + native_delegate->ProcessStateChanged(this, state); + + if (log) { + if (!m_delegates.empty()) { + log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " + "from process %" PRIu64, + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); + } else { + log->Printf("NativeProcessProtocol::%s: would send state notification " + "[%s] from process %" PRIu64 ", but no delegates", + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } + } } +void NativeProcessProtocol::NotifyDidExec() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessProtocol::%s - preparing to call delegates", + __FUNCTION__); -Error -NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + { + std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); + for (auto native_delegate : m_delegates) + native_delegate->DidExec(this); + } +} - return m_breakpoint_list.AddRef (addr, size_hint, false, - [this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error - { return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); }); +Error NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, + uint32_t size_hint) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); + + return m_breakpoint_list.AddRef( + addr, size_hint, false, + [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, + NativeBreakpointSP &breakpoint_sp) -> Error { + return SoftwareBreakpoint::CreateSoftwareBreakpoint( + *this, addr, size_hint, breakpoint_sp); + }); } -Error -NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.DecRef (addr); +Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.DecRef(addr); } -Error -NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.EnableBreakpoint (addr); +Error NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.EnableBreakpoint(addr); } -Error -NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr) -{ - return m_breakpoint_list.DisableBreakpoint (addr); +Error NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { + return m_breakpoint_list.DisableBreakpoint(addr); } -lldb::StateType -NativeProcessProtocol::GetState () const -{ - std::lock_guard<std::recursive_mutex> guard(m_state_mutex); - return m_state; +lldb::StateType NativeProcessProtocol::GetState() const { + std::lock_guard<std::recursive_mutex> guard(m_state_mutex); + return m_state; } -void -NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates) -{ - std::lock_guard<std::recursive_mutex> guard(m_state_mutex); +void NativeProcessProtocol::SetState(lldb::StateType state, + bool notify_delegates) { + std::lock_guard<std::recursive_mutex> guard(m_state_mutex); - if (state == m_state) - return; + if (state == m_state) + return; - m_state = state; + m_state = state; - if (StateIsStoppedState (state, false)) - { - ++m_stop_id; + if (StateIsStoppedState(state, false)) { + ++m_stop_id; - // Give process a chance to do any stop id bump processing, such as - // clearing cached data that is invalidated each time the process runs. - // Note if/when we support some threads running, we'll end up needing - // to manage this per thread and per process. - DoStopIDBumped (m_stop_id); - } + // Give process a chance to do any stop id bump processing, such as + // clearing cached data that is invalidated each time the process runs. + // Note if/when we support some threads running, we'll end up needing + // to manage this per thread and per process. + DoStopIDBumped(m_stop_id); + } - // Optionally notify delegates of the state change. - if (notify_delegates) - SynchronouslyNotifyProcessStateChanged (state); + // Optionally notify delegates of the state change. + if (notify_delegates) + SynchronouslyNotifyProcessStateChanged(state); } -uint32_t NativeProcessProtocol::GetStopID () const -{ - std::lock_guard<std::recursive_mutex> guard(m_state_mutex); - return m_stop_id; +uint32_t NativeProcessProtocol::GetStopID() const { + std::lock_guard<std::recursive_mutex> guard(m_state_mutex); + return m_stop_id; } -void -NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */) -{ - // Default implementation does nothing. +void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { + // Default implementation does nothing. } -Error -NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, - ArchSpec &arch) -{ - // Grab process info for the running process. - ProcessInstanceInfo process_info; - if (!Host::GetProcessInfo(pid, process_info)) - return Error("failed to get process info"); - - // Resolve the executable module. - ModuleSpecList module_specs; - if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), - 0, 0, module_specs)) - return Error("failed to get module specifications"); - lldbassert(module_specs.GetSize() == 1); - - arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); - if (arch.IsValid()) - return Error(); - else - return Error("failed to retrieve a valid architecture from the exe module"); +Error NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, + ArchSpec &arch) { + // Grab process info for the running process. + ProcessInstanceInfo process_info; + if (!Host::GetProcessInfo(pid, process_info)) + return Error("failed to get process info"); + + // Resolve the executable module. + ModuleSpecList module_specs; + if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, + 0, module_specs)) + return Error("failed to get module specifications"); + lldbassert(module_specs.GetSize() == 1); + + arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); + if (arch.IsValid()) + return Error(); + else + return Error("failed to retrieve a valid architecture from the exe module"); } #ifndef __linux__ -// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are +// These need to be implemented to support lldb-gdb-server on a given platform. +// Stubs are // provided to make the rest of the code link on non-supported platforms. -Error -NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) -{ - llvm_unreachable("Platform has no NativeProcessProtocol support"); +Error NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop, + NativeProcessProtocolSP &process_sp) { + llvm_unreachable("Platform has no NativeProcessProtocol support"); } -Error -NativeProcessProtocol::Attach (lldb::pid_t pid, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) -{ - llvm_unreachable("Platform has no NativeProcessProtocol support"); +Error NativeProcessProtocol::Attach(lldb::pid_t pid, + NativeDelegate &native_delegate, + MainLoop &mainloop, + NativeProcessProtocolSP &process_sp) { + llvm_unreachable("Platform has no NativeProcessProtocol support"); } #endif diff --git a/lldb/source/Host/common/NativeRegisterContext.cpp b/lldb/source/Host/common/NativeRegisterContext.cpp index 5ed0a43..e143b9a 100644 --- a/lldb/source/Host/common/NativeRegisterContext.cpp +++ b/lldb/source/Host/common/NativeRegisterContext.cpp @@ -12,25 +12,21 @@ #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" +#include "lldb/Host/PosixApi.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Host/PosixApi.h" using namespace lldb; using namespace lldb_private; -NativeRegisterContext::NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx) : - m_thread (thread), - m_concrete_frame_idx (concrete_frame_idx) -{ -} +NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread, + uint32_t concrete_frame_idx) + : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -NativeRegisterContext::~NativeRegisterContext() -{ -} +NativeRegisterContext::~NativeRegisterContext() {} // FIXME revisit invalidation, process stop ids, etc. Right now we don't // support caching in NativeRegisterContext. We can do this later by @@ -59,459 +55,385 @@ NativeRegisterContext::~NativeRegisterContext() // } // } - const RegisterInfo * -NativeRegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx) -{ - if (reg_name && reg_name[0]) - { - const uint32_t num_registers = GetRegisterCount(); - for (uint32_t reg = start_idx; reg < num_registers; ++reg) - { - const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); - - if ((reg_info->name != nullptr && ::strcasecmp (reg_info->name, reg_name) == 0) || - (reg_info->alt_name != nullptr && ::strcasecmp (reg_info->alt_name, reg_name) == 0)) - { - return reg_info; - } - } +NativeRegisterContext::GetRegisterInfoByName(const char *reg_name, + uint32_t start_idx) { + if (reg_name && reg_name[0]) { + const uint32_t num_registers = GetRegisterCount(); + for (uint32_t reg = start_idx; reg < num_registers; ++reg) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + + if ((reg_info->name != nullptr && + ::strcasecmp(reg_info->name, reg_name) == 0) || + (reg_info->alt_name != nullptr && + ::strcasecmp(reg_info->alt_name, reg_name) == 0)) { + return reg_info; + } } + } + return nullptr; +} + +const RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind, + uint32_t num) { + const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); + if (reg_num == LLDB_INVALID_REGNUM) return nullptr; + return GetRegisterInfoAtIndex(reg_num); } -const RegisterInfo * -NativeRegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num) -{ - const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); - if (reg_num == LLDB_INVALID_REGNUM) - return nullptr; - return GetRegisterInfoAtIndex (reg_num); +const char *NativeRegisterContext::GetRegisterName(uint32_t reg) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info) + return reg_info->name; + return nullptr; } -const char * -NativeRegisterContext::GetRegisterName (uint32_t reg) -{ - const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info) - return reg_info->name; +const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex( + uint32_t reg_index) const { + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) return nullptr; -} -const char* -NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const -{ - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - return nullptr; - - for (uint32_t set_index = 0; set_index < GetRegisterSetCount (); ++set_index) - { - const RegisterSet *const reg_set = GetRegisterSet (set_index); - if (!reg_set) - continue; - - for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; ++reg_num_index) - { - const uint32_t reg_num = reg_set->registers[reg_num_index]; - // FIXME double check we're checking the right register kind here. - if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) - { - // The given register is a member of this register set. Return the register set name. - return reg_set->name; - } - } + for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) { + const RegisterSet *const reg_set = GetRegisterSet(set_index); + if (!reg_set) + continue; + + for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; + ++reg_num_index) { + const uint32_t reg_num = reg_set->registers[reg_num_index]; + // FIXME double check we're checking the right register kind here. + if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) { + // The given register is a member of this register set. Return the + // register set name. + return reg_set->name; + } } + } - // Didn't find it. - return nullptr; + // Didn't find it. + return nullptr; } -lldb::addr_t -NativeRegisterContext::GetPC (lldb::addr_t fail_value) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); +lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - if (log) - log->Printf ("NativeRegisterContext::%s using reg index %" PRIu32 " (default %" PRIu64 ")", __FUNCTION__, reg, fail_value); + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + if (log) + log->Printf("NativeRegisterContext::%s using reg index %" PRIu32 + " (default %" PRIu64 ")", + __FUNCTION__, reg, fail_value); - const uint64_t retval = ReadRegisterAsUnsigned (reg, fail_value); + const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value); - if (log) - log->Printf ("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, __FUNCTION__, retval); + if (log) + log->Printf("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, + __FUNCTION__, retval); - return retval; + return retval; } lldb::addr_t -NativeRegisterContext::GetPCfromBreakpointLocation (lldb::addr_t fail_value) -{ - return GetPC (fail_value); +NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) { + return GetPC(fail_value); } -Error -NativeRegisterContext::SetPC (lldb::addr_t pc) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - return WriteRegisterFromUnsigned (reg, pc); +Error NativeRegisterContext::SetPC(lldb::addr_t pc) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + return WriteRegisterFromUnsigned(reg, pc); } -lldb::addr_t -NativeRegisterContext::GetSP (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP); + return ReadRegisterAsUnsigned(reg, fail_value); } -Error -NativeRegisterContext::SetSP (lldb::addr_t sp) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - return WriteRegisterFromUnsigned (reg, sp); +Error NativeRegisterContext::SetSP(lldb::addr_t sp) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP); + return WriteRegisterFromUnsigned(reg, sp); } -lldb::addr_t -NativeRegisterContext::GetFP (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FP); + return ReadRegisterAsUnsigned(reg, fail_value); } -Error -NativeRegisterContext::SetFP (lldb::addr_t fp) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - return WriteRegisterFromUnsigned (reg, fp); +Error NativeRegisterContext::SetFP(lldb::addr_t fp) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FP); + return WriteRegisterFromUnsigned(reg, fp); } -lldb::addr_t -NativeRegisterContext::GetReturnAddress (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA); + return ReadRegisterAsUnsigned(reg, fail_value); } -lldb::addr_t -NativeRegisterContext::GetFlags (lldb::addr_t fail_value) -{ - uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - return ReadRegisterAsUnsigned (reg, fail_value); +lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS); + return ReadRegisterAsUnsigned(reg, fail_value); } - lldb::addr_t -NativeRegisterContext::ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value) -{ - if (reg != LLDB_INVALID_REGNUM) - return ReadRegisterAsUnsigned (GetRegisterInfoAtIndex (reg), fail_value); - return fail_value; +NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg, + lldb::addr_t fail_value) { + if (reg != LLDB_INVALID_REGNUM) + return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value); + return fail_value; } uint64_t -NativeRegisterContext::ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - - if (reg_info) - { - RegisterValue value; - Error error = ReadRegister (reg_info, value); - if (error.Success ()) - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() succeeded, value %" PRIu64, __FUNCTION__, value.GetAsUInt64()); - return value.GetAsUInt64(); - } - else - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() failed, error %s", __FUNCTION__, error.AsCString ()); - } - } - else - { - if (log) - log->Printf ("NativeRegisterContext::%s ReadRegister() null reg_info", __FUNCTION__); +NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, + lldb::addr_t fail_value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + if (reg_info) { + RegisterValue value; + Error error = ReadRegister(reg_info, value); + if (error.Success()) { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() succeeded, value " + "%" PRIu64, + __FUNCTION__, value.GetAsUInt64()); + return value.GetAsUInt64(); + } else { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() failed, error %s", + __FUNCTION__, error.AsCString()); } - return fail_value; + } else { + if (log) + log->Printf("NativeRegisterContext::%s ReadRegister() null reg_info", + __FUNCTION__); + } + return fail_value; } -Error -NativeRegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval) -{ - if (reg == LLDB_INVALID_REGNUM) - return Error ("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__); - return WriteRegisterFromUnsigned (GetRegisterInfoAtIndex (reg), uval); +Error NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg, + uint64_t uval) { + if (reg == LLDB_INVALID_REGNUM) + return Error("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__); + return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval); } -Error -NativeRegisterContext::WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval) -{ - assert (reg_info); - if (!reg_info) - return Error ("reg_info is nullptr"); +Error NativeRegisterContext::WriteRegisterFromUnsigned( + const RegisterInfo *reg_info, uint64_t uval) { + assert(reg_info); + if (!reg_info) + return Error("reg_info is nullptr"); - RegisterValue value; - if (!value.SetUInt(uval, reg_info->byte_size)) - return Error ("RegisterValue::SetUInt () failed"); + RegisterValue value; + if (!value.SetUInt(uval, reg_info->byte_size)) + return Error("RegisterValue::SetUInt () failed"); - return WriteRegister (reg_info, value); + return WriteRegister(reg_info, value); } -lldb::tid_t -NativeRegisterContext::GetThreadID() const -{ - return m_thread.GetID(); +lldb::tid_t NativeRegisterContext::GetThreadID() const { + return m_thread.GetID(); } -uint32_t -NativeRegisterContext::NumSupportedHardwareBreakpoints () -{ - return 0; -} +uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; } -uint32_t -NativeRegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - return LLDB_INVALID_INDEX32; +uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + return LLDB_INVALID_INDEX32; } -bool -NativeRegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx) -{ - return false; +bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { + return false; } +uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; } -uint32_t -NativeRegisterContext::NumSupportedHardwareWatchpoints () -{ - return 0; +uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, + uint32_t watch_flags) { + return LLDB_INVALID_INDEX32; } -uint32_t -NativeRegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - return LLDB_INVALID_INDEX32; +bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) { + return false; } -bool -NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index) -{ - return false; +Error NativeRegisterContext::ClearAllHardwareWatchpoints() { + return Error("not implemented"); } -Error -NativeRegisterContext::ClearAllHardwareWatchpoints () -{ - return Error ("not implemented"); +Error NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { + is_hit = false; + return Error("not implemented"); } -Error -NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) -{ - is_hit = false; - return Error ("not implemented"); +Error NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) { + wp_index = LLDB_INVALID_INDEX32; + return Error("not implemented"); } -Error -NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - wp_index = LLDB_INVALID_INDEX32; - return Error ("not implemented"); +Error NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + is_vacant = false; + return Error("not implemented"); } -Error -NativeRegisterContext::IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) -{ - is_vacant = false; - return Error ("not implemented"); +lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) { + return LLDB_INVALID_ADDRESS; } -lldb::addr_t -NativeRegisterContext::GetWatchpointAddress (uint32_t wp_index) -{ - return LLDB_INVALID_ADDRESS; +lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) { + return LLDB_INVALID_ADDRESS; } -lldb::addr_t -NativeRegisterContext::GetWatchpointHitAddress (uint32_t wp_index) -{ - return LLDB_INVALID_ADDRESS; -} +bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; } -bool -NativeRegisterContext::HardwareSingleStep (bool enable) -{ - return false; -} +Error NativeRegisterContext::ReadRegisterValueFromMemory( + const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len, + RegisterValue ®_value) { + Error error; + if (reg_info == nullptr) { + error.SetErrorString("invalid register info argument."); + return error; + } + + // Moving from addr into a register + // + // Case 1: src_len == dst_len + // + // |AABBCCDD| Address contents + // |AABBCCDD| Register contents + // + // Case 2: src_len > dst_len + // + // Error! (The register should always be big enough to hold the data) + // + // Case 3: src_len < dst_len + // + // |AABB| Address contents + // |AABB0000| Register contents [on little-endian hardware] + // |0000AABB| Register contents [on big-endian hardware] + if (src_len > RegisterValue::kMaxRegisterByteSize) { + error.SetErrorString("register too small to receive memory data"); + return error; + } -Error -NativeRegisterContext::ReadRegisterValueFromMemory ( - const RegisterInfo *reg_info, - lldb::addr_t src_addr, - size_t src_len, - RegisterValue ®_value) -{ - Error error; - if (reg_info == nullptr) - { - error.SetErrorString ("invalid register info argument."); - return error; - } + const size_t dst_len = reg_info->byte_size; + if (src_len > dst_len) { + error.SetErrorStringWithFormat( + "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 + " bytes)", + static_cast<uint64_t>(src_len), reg_info->name, + static_cast<uint64_t>(dst_len)); + return error; + } - // Moving from addr into a register - // - // Case 1: src_len == dst_len - // - // |AABBCCDD| Address contents - // |AABBCCDD| Register contents - // - // Case 2: src_len > dst_len - // - // Error! (The register should always be big enough to hold the data) - // - // Case 3: src_len < dst_len - // - // |AABB| Address contents - // |AABB0000| Register contents [on little-endian hardware] - // |0000AABB| Register contents [on big-endian hardware] - if (src_len > RegisterValue::kMaxRegisterByteSize) - { - error.SetErrorString ("register too small to receive memory data"); - return error; - } + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (!process_sp) { + error.SetErrorString("invalid process"); + return error; + } - const size_t dst_len = reg_info->byte_size; + uint8_t src[RegisterValue::kMaxRegisterByteSize]; - if (src_len > dst_len) - { - error.SetErrorStringWithFormat("%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 " bytes)", - static_cast<uint64_t>(src_len), reg_info->name, static_cast<uint64_t>(dst_len)); - return error; - } + // Read the memory + size_t bytes_read; + error = process_sp->ReadMemory(src_addr, src, src_len, bytes_read); + if (error.Fail()) + return error; - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString("invalid process"); - return error; - } + // Make sure the memory read succeeded... + if (bytes_read != src_len) { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", + static_cast<uint64_t>(bytes_read), + static_cast<uint64_t>(src_len)); + return error; + } + + // We now have a memory buffer that contains the part or all of the register + // value. Set the register value using this memory data. + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder(byte_order)) { + error.SetErrorString("NativeProcessProtocol::GetByteOrder () failed"); + return error; + } - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Read the memory - size_t bytes_read; - error = process_sp->ReadMemory (src_addr, src, src_len, bytes_read); - if (error.Fail ()) - return error; - - // Make sure the memory read succeeded... - if (bytes_read != src_len) - { - // This might happen if we read _some_ bytes but not all - error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", - static_cast<uint64_t>(bytes_read), static_cast<uint64_t>(src_len)); - return error; - } + reg_value.SetFromMemoryData(reg_info, src, src_len, byte_order, error); - // We now have a memory buffer that contains the part or all of the register - // value. Set the register value using this memory data. - // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are assuming - // they are the same. - lldb::ByteOrder byte_order; - if (!process_sp->GetByteOrder (byte_order)) - { - error.SetErrorString ( "NativeProcessProtocol::GetByteOrder () failed"); - return error; - } + return error; +} - reg_value.SetFromMemoryData ( - reg_info, - src, - src_len, - byte_order, - error); +Error NativeRegisterContext::WriteRegisterValueToMemory( + const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, + const RegisterValue ®_value) { - return error; -} + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + Error error; -Error -NativeRegisterContext::WriteRegisterValueToMemory ( - const RegisterInfo *reg_info, - lldb::addr_t dst_addr, - size_t dst_len, - const RegisterValue ®_value) -{ - - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - Error error; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (process_sp) - { - - // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are assuming - // they are the same. - lldb::ByteOrder byte_order; - if (!process_sp->GetByteOrder (byte_order)) - return Error ("NativeProcessProtocol::GetByteOrder () failed"); - - const size_t bytes_copied = reg_value.GetAsMemoryData ( - reg_info, - dst, - dst_len, - byte_order, - error); - - if (error.Success()) - { - if (bytes_copied == 0) - { - error.SetErrorString("byte copy failed."); - } - else - { - size_t bytes_written; - error = process_sp->WriteMemory(dst_addr, dst, bytes_copied, bytes_written); - if (error.Fail ()) - return error; - - if (bytes_written != bytes_copied) - { - // This might happen if we read _some_ bytes but not all - error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 " bytes", - static_cast<uint64_t>(bytes_written), static_cast<uint64_t>(bytes_copied)); - } - } + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (process_sp) { + + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are + // assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder(byte_order)) + return Error("NativeProcessProtocol::GetByteOrder () failed"); + + const size_t bytes_copied = + reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error); + + if (error.Success()) { + if (bytes_copied == 0) { + error.SetErrorString("byte copy failed."); + } else { + size_t bytes_written; + error = + process_sp->WriteMemory(dst_addr, dst, bytes_copied, bytes_written); + if (error.Fail()) + return error; + + if (bytes_written != bytes_copied) { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 + " bytes", + static_cast<uint64_t>(bytes_written), + static_cast<uint64_t>(bytes_copied)); } + } } - else - error.SetErrorString("invalid process"); + } else + error.SetErrorString("invalid process"); - return error; + return error; } uint32_t -NativeRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const -{ - const uint32_t num_regs = GetRegisterCount(); +NativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) const { + const uint32_t num_regs = GetRegisterCount(); - assert (kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); - if (reg_info->kinds[kind] == num) - return reg_idx; - } + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } - - diff --git a/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp b/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp index 0d7c6ec..3590c68 100644 --- a/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp +++ b/lldb/source/Host/common/NativeRegisterContextRegisterInfo.cpp @@ -7,44 +7,37 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-types.h" -#include "lldb/lldb-private-forward.h" #include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-types.h" using namespace lldb_private; -NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info_interface) : - NativeRegisterContext (thread, concrete_frame_idx), - m_register_info_interface_up (register_info_interface) -{ - assert (register_info_interface && "null register_info_interface"); +NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( + NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface) + : NativeRegisterContext(thread, concrete_frame_idx), + m_register_info_interface_up(register_info_interface) { + assert(register_info_interface && "null register_info_interface"); } -uint32_t -NativeRegisterContextRegisterInfo::GetRegisterCount () const -{ - return m_register_info_interface_up->GetRegisterCount (); +uint32_t NativeRegisterContextRegisterInfo::GetRegisterCount() const { + return m_register_info_interface_up->GetRegisterCount(); } -uint32_t -NativeRegisterContextRegisterInfo::GetUserRegisterCount () const -{ - return m_register_info_interface_up->GetUserRegisterCount (); +uint32_t NativeRegisterContextRegisterInfo::GetUserRegisterCount() const { + return m_register_info_interface_up->GetUserRegisterCount(); } -const RegisterInfo * -NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const -{ - if (reg_index <= GetRegisterCount ()) - return m_register_info_interface_up->GetRegisterInfo () + reg_index; - else - return nullptr; +const RegisterInfo *NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex( + uint32_t reg_index) const { + if (reg_index <= GetRegisterCount()) + return m_register_info_interface_up->GetRegisterInfo() + reg_index; + else + return nullptr; } -const RegisterInfoInterface& -NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const -{ - return *m_register_info_interface_up; +const RegisterInfoInterface & +NativeRegisterContextRegisterInfo::GetRegisterInfoInterface() const { + return *m_register_info_interface_up; } diff --git a/lldb/source/Host/common/NativeThreadProtocol.cpp b/lldb/source/Host/common/NativeThreadProtocol.cpp index ea406e9..2e76cff 100644 --- a/lldb/source/Host/common/NativeThreadProtocol.cpp +++ b/lldb/source/Host/common/NativeThreadProtocol.cpp @@ -16,60 +16,53 @@ using namespace lldb; using namespace lldb_private; -NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) : - m_process_wp (process->shared_from_this ()), - m_tid (tid) -{ -} +NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol *process, + lldb::tid_t tid) + : m_process_wp(process->shared_from_this()), m_tid(tid) {} -Error -NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); +Error NativeThreadProtocol::ReadRegister(uint32_t reg, + RegisterValue ®_value) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); + const RegisterInfo *const reg_info = + register_context_sp->GetRegisterInfoAtIndex(reg); + if (!reg_info) + return Error("no register info for reg num %" PRIu32, reg); - return register_context_sp->ReadRegister (reg_info, reg_value);; + return register_context_sp->ReadRegister(reg_info, reg_value); + ; } -Error -NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); +Error NativeThreadProtocol::WriteRegister(uint32_t reg, + const RegisterValue ®_value) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); + const RegisterInfo *const reg_info = + register_context_sp->GetRegisterInfoAtIndex(reg); + if (!reg_info) + return Error("no register info for reg num %" PRIu32, reg); - return register_context_sp->WriteRegister (reg_info, reg_value); + return register_context_sp->WriteRegister(reg_info, reg_value); } -Error -NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->WriteAllRegisterValues (data_sp); +Error NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); + return register_context_sp->WriteAllRegisterValues(data_sp); } -Error -NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->ReadAllRegisterValues (data_sp); +Error NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) { + NativeRegisterContextSP register_context_sp = GetRegisterContext(); + if (!register_context_sp) + return Error("no register context"); + return register_context_sp->ReadAllRegisterValues(data_sp); } -NativeProcessProtocolSP -NativeThreadProtocol::GetProcess () -{ - return m_process_wp.lock (); +NativeProcessProtocolSP NativeThreadProtocol::GetProcess() { + return m_process_wp.lock(); } diff --git a/lldb/source/Host/common/NativeWatchpointList.cpp b/lldb/source/Host/common/NativeWatchpointList.cpp index 209d213..5948adf 100644 --- a/lldb/source/Host/common/NativeWatchpointList.cpp +++ b/lldb/source/Host/common/NativeWatchpointList.cpp @@ -14,22 +14,18 @@ using namespace lldb; using namespace lldb_private; -Error -NativeWatchpointList::Add (addr_t addr, size_t size, uint32_t watch_flags, bool hardware) -{ - m_watchpoints[addr] = {addr, size, watch_flags, hardware}; - return Error (); +Error NativeWatchpointList::Add(addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) { + m_watchpoints[addr] = {addr, size, watch_flags, hardware}; + return Error(); } -Error -NativeWatchpointList::Remove (addr_t addr) -{ - m_watchpoints.erase(addr); - return Error (); +Error NativeWatchpointList::Remove(addr_t addr) { + m_watchpoints.erase(addr); + return Error(); } -const NativeWatchpointList::WatchpointMap& -NativeWatchpointList::GetWatchpointMap () const -{ - return m_watchpoints; +const NativeWatchpointList::WatchpointMap & +NativeWatchpointList::GetWatchpointMap() const { + return m_watchpoints; } diff --git a/lldb/source/Host/common/OptionParser.cpp b/lldb/source/Host/common/OptionParser.cpp index 16a29a1..053179c 100644 --- a/lldb/source/Host/common/OptionParser.cpp +++ b/lldb/source/Host/common/OptionParser.cpp @@ -15,102 +15,67 @@ using namespace lldb_private; -void -OptionParser::Prepare(std::unique_lock<std::mutex> &lock) -{ - static std::mutex g_mutex; - lock = std::unique_lock<std::mutex>(g_mutex); +void OptionParser::Prepare(std::unique_lock<std::mutex> &lock) { + static std::mutex g_mutex; + lock = std::unique_lock<std::mutex>(g_mutex); #ifdef __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif } -void -OptionParser::EnableError(bool error) -{ - opterr = error ? 1 : 0; -} +void OptionParser::EnableError(bool error) { opterr = error ? 1 : 0; } -int -OptionParser::Parse (int argc, - char * const argv [], - const char *optstring, - const Option *longopts, - int *longindex) -{ - std::vector<option> opts; - while (longopts->definition != nullptr) - { - option opt; - opt.flag = longopts->flag; - opt.val = longopts->val; - opt.name = longopts->definition->long_option; - opt.has_arg = longopts->definition->option_has_arg; - opts.push_back(opt); - ++longopts; - } - opts.push_back(option()); - return getopt_long_only(argc, argv, optstring, &opts[0], longindex); +int OptionParser::Parse(int argc, char *const argv[], const char *optstring, + const Option *longopts, int *longindex) { + std::vector<option> opts; + while (longopts->definition != nullptr) { + option opt; + opt.flag = longopts->flag; + opt.val = longopts->val; + opt.name = longopts->definition->long_option; + opt.has_arg = longopts->definition->option_has_arg; + opts.push_back(opt); + ++longopts; + } + opts.push_back(option()); + return getopt_long_only(argc, argv, optstring, &opts[0], longindex); } -char* -OptionParser::GetOptionArgument() -{ - return optarg; -} +char *OptionParser::GetOptionArgument() { return optarg; } -int -OptionParser::GetOptionIndex() -{ - return optind; -} +int OptionParser::GetOptionIndex() { return optind; } -int -OptionParser::GetOptionErrorCause() -{ - return optopt; -} +int OptionParser::GetOptionErrorCause() { return optopt; } -std::string -OptionParser::GetShortOptionString(struct option *long_options) -{ - std::string s; - int i=0; - bool done = false; - while (!done) - { - if (long_options[i].name == 0 && - long_options[i].has_arg == 0 && - long_options[i].flag == 0 && - long_options[i].val == 0) - { - done = true; - } - else - { - if (long_options[i].flag == NULL && - isalpha(long_options[i].val)) - { - s.append(1, (char)long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - - case optional_argument: - s.append(2, ':'); - break; - case required_argument: - s.append(1, ':'); - break; - } - } - ++i; +std::string OptionParser::GetShortOptionString(struct option *long_options) { + std::string s; + int i = 0; + bool done = false; + while (!done) { + if (long_options[i].name == 0 && long_options[i].has_arg == 0 && + long_options[i].flag == 0 && long_options[i].val == 0) { + done = true; + } else { + if (long_options[i].flag == NULL && isalpha(long_options[i].val)) { + s.append(1, (char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + + case optional_argument: + s.append(2, ':'); + break; + case required_argument: + s.append(1, ':'); + break; } + } + ++i; } - return s; + } + return s; } diff --git a/lldb/source/Host/common/PipeBase.cpp b/lldb/source/Host/common/PipeBase.cpp index a9d6e6f..cf7e6c9 100644 --- a/lldb/source/Host/common/PipeBase.cpp +++ b/lldb/source/Host/common/PipeBase.cpp @@ -11,17 +11,14 @@ using namespace lldb_private; - PipeBase::~PipeBase() = default; -Error -PipeBase::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) -{ - return OpenAsWriterWithTimeout(name, child_process_inherit, std::chrono::microseconds::zero()); +Error PipeBase::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) { + return OpenAsWriterWithTimeout(name, child_process_inherit, + std::chrono::microseconds::zero()); } -Error -PipeBase::Read(void *buf, size_t size, size_t &bytes_read) -{ - return ReadWithTimeout(buf, size, std::chrono::microseconds::zero(), bytes_read); +Error PipeBase::Read(void *buf, size_t size, size_t &bytes_read) { + return ReadWithTimeout(buf, size, std::chrono::microseconds::zero(), + bytes_read); } diff --git a/lldb/source/Host/common/ProcessRunLock.cpp b/lldb/source/Host/common/ProcessRunLock.cpp index 669a96d..a6d59a0 100644 --- a/lldb/source/Host/common/ProcessRunLock.cpp +++ b/lldb/source/Host/common/ProcessRunLock.cpp @@ -4,68 +4,60 @@ namespace lldb_private { - ProcessRunLock::ProcessRunLock() - : m_running(false) - { - int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void) err; - //#if LLDB_CONFIGURATION_DEBUG - // assert(err == 0); - //#endif - } +ProcessRunLock::ProcessRunLock() : m_running(false) { + int err = ::pthread_rwlock_init(&m_rwlock, NULL); + (void)err; + //#if LLDB_CONFIGURATION_DEBUG + // assert(err == 0); + //#endif +} - ProcessRunLock::~ProcessRunLock() - { - int err = ::pthread_rwlock_destroy(&m_rwlock); (void) err; - //#if LLDB_CONFIGURATION_DEBUG - // assert(err == 0); - //#endif - } +ProcessRunLock::~ProcessRunLock() { + int err = ::pthread_rwlock_destroy(&m_rwlock); + (void)err; + //#if LLDB_CONFIGURATION_DEBUG + // assert(err == 0); + //#endif +} - bool ProcessRunLock::ReadTryLock() - { - ::pthread_rwlock_rdlock(&m_rwlock); - if (m_running == false) - { - return true; - } - ::pthread_rwlock_unlock(&m_rwlock); - return false; - } +bool ProcessRunLock::ReadTryLock() { + ::pthread_rwlock_rdlock(&m_rwlock); + if (m_running == false) { + return true; + } + ::pthread_rwlock_unlock(&m_rwlock); + return false; +} - bool ProcessRunLock::ReadUnlock() - { - return ::pthread_rwlock_unlock(&m_rwlock) == 0; - } +bool ProcessRunLock::ReadUnlock() { + return ::pthread_rwlock_unlock(&m_rwlock) == 0; +} - bool ProcessRunLock::SetRunning() - { - ::pthread_rwlock_wrlock(&m_rwlock); - m_running = true; - ::pthread_rwlock_unlock(&m_rwlock); - return true; - } +bool ProcessRunLock::SetRunning() { + ::pthread_rwlock_wrlock(&m_rwlock); + m_running = true; + ::pthread_rwlock_unlock(&m_rwlock); + return true; +} - bool ProcessRunLock::TrySetRunning() - { - bool r; +bool ProcessRunLock::TrySetRunning() { + bool r; - if (::pthread_rwlock_trywrlock(&m_rwlock) == 0) - { - r = !m_running; - m_running = true; - ::pthread_rwlock_unlock(&m_rwlock); - return r; - } - return false; - } + if (::pthread_rwlock_trywrlock(&m_rwlock) == 0) { + r = !m_running; + m_running = true; + ::pthread_rwlock_unlock(&m_rwlock); + return r; + } + return false; +} - bool ProcessRunLock::SetStopped() - { - ::pthread_rwlock_wrlock(&m_rwlock); - m_running = false; - ::pthread_rwlock_unlock(&m_rwlock); - return true; - } +bool ProcessRunLock::SetStopped() { + ::pthread_rwlock_wrlock(&m_rwlock); + m_running = false; + ::pthread_rwlock_unlock(&m_rwlock); + return true; +} } #endif diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index ea049ae..d986c2fe 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -35,15 +35,15 @@ #endif #ifdef __ANDROID_NDK__ -#include <linux/tcp.h> -#include <bits/error_constants.h> +#include <arpa/inet.h> #include <asm-generic/errno-base.h> +#include <bits/error_constants.h> #include <errno.h> -#include <arpa/inet.h> +#include <linux/tcp.h> #if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) -#include <unistd.h> -#include <sys/syscall.h> #include <fcntl.h> +#include <sys/syscall.h> +#include <unistd.h> #endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC #endif // __ANDROID_NDK__ @@ -51,439 +51,407 @@ using namespace lldb; using namespace lldb_private; #if defined(_WIN32) -typedef const char * set_socket_option_arg_type; -typedef char * get_socket_option_arg_type; +typedef const char *set_socket_option_arg_type; +typedef char *get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = INVALID_SOCKET; -#else // #if defined(_WIN32) -typedef const void * set_socket_option_arg_type; -typedef void * get_socket_option_arg_type; +#else // #if defined(_WIN32) +typedef const void *set_socket_option_arg_type; +typedef void *get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = -1; #endif // #if defined(_WIN32) namespace { -bool IsInterrupted() -{ +bool IsInterrupted() { #if defined(_WIN32) - return ::WSAGetLastError() == WSAEINTR; + return ::WSAGetLastError() == WSAEINTR; #else - return errno == EINTR; + return errno == EINTR; #endif } - } Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close) - : IOObject(eFDTypeSocket, should_close) - , m_protocol(protocol) - , m_socket(socket) -{ - -} - -Socket::~Socket() -{ - Close(); -} - -std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error) -{ - error.Clear(); - - std::unique_ptr<Socket> socket_up; - switch (protocol) - { - case ProtocolTcp: - socket_up.reset(new TCPSocket(child_processes_inherit, error)); - break; - case ProtocolUdp: - socket_up.reset(new UDPSocket(child_processes_inherit, error)); - break; - case ProtocolUnixDomain: + : IOObject(eFDTypeSocket, should_close), m_protocol(protocol), + m_socket(socket) {} + +Socket::~Socket() { Close(); } + +std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, + bool child_processes_inherit, + Error &error) { + error.Clear(); + + std::unique_ptr<Socket> socket_up; + switch (protocol) { + case ProtocolTcp: + socket_up.reset(new TCPSocket(child_processes_inherit, error)); + break; + case ProtocolUdp: + socket_up.reset(new UDPSocket(child_processes_inherit, error)); + break; + case ProtocolUnixDomain: #ifndef LLDB_DISABLE_POSIX - socket_up.reset(new DomainSocket(child_processes_inherit, error)); + socket_up.reset(new DomainSocket(child_processes_inherit, error)); #else - error.SetErrorString("Unix domain sockets are not supported on this platform."); + error.SetErrorString( + "Unix domain sockets are not supported on this platform."); #endif - break; - case ProtocolUnixAbstract: + break; + case ProtocolUnixAbstract: #ifdef __linux__ - socket_up.reset(new AbstractSocket(child_processes_inherit, error)); + socket_up.reset(new AbstractSocket(child_processes_inherit, error)); #else - error.SetErrorString("Abstract domain sockets are not supported on this platform."); + error.SetErrorString( + "Abstract domain sockets are not supported on this platform."); #endif - break; - } + break; + } - if (error.Fail()) - socket_up.reset(); + if (error.Fail()) + socket_up.reset(); - return socket_up; + return socket_up; } -Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); - if (log) - log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); - - Error error; - std::unique_ptr<Socket> connect_socket(Create(ProtocolTcp, child_processes_inherit, error)); - if (error.Fail()) - return error; +Error Socket::TcpConnect(llvm::StringRef host_and_port, + bool child_processes_inherit, Socket *&socket) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, + host_and_port.data()); + + Error error; + std::unique_ptr<Socket> connect_socket( + Create(ProtocolTcp, child_processes_inherit, error)); + if (error.Fail()) + return error; - error = connect_socket->Connect(host_and_port); - if (error.Success()) - socket = connect_socket.release(); + error = connect_socket->Connect(host_and_port); + if (error.Success()) + socket = connect_socket.release(); - return error; + return error; } -Error -Socket::TcpListen (llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket, - Predicate<uint16_t>* predicate, - int backlog) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("Socket::%s (%s)", __FUNCTION__, host_and_port.data()); - - Error error; - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) - return error; - - std::unique_ptr<TCPSocket> listen_socket(new TCPSocket(child_processes_inherit, error)); - if (error.Fail()) - return error; - - 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". - 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. - if (predicate) - predicate->SetValue (port, eBroadcastAlways); - socket = listen_socket.release(); - } +Error Socket::TcpListen(llvm::StringRef host_and_port, + bool child_processes_inherit, Socket *&socket, + Predicate<uint16_t> *predicate, int backlog) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("Socket::%s (%s)", __FUNCTION__, host_and_port.data()); + + Error error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error)) + return error; + std::unique_ptr<TCPSocket> listen_socket( + new TCPSocket(child_processes_inherit, error)); + if (error.Fail()) return error; + + 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". + 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. + if (predicate) + predicate->SetValue(port, eBroadcastAlways); + socket = listen_socket.release(); + } + + return error; } -Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); +Error Socket::UdpConnect(llvm::StringRef host_and_port, + bool child_processes_inherit, Socket *&send_socket, + Socket *&recv_socket) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, + host_and_port.data()); - return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, recv_socket); + return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, + recv_socket); } -Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); - if (error.Fail()) - return error; +Error Socket::UnixDomainConnect(llvm::StringRef name, + bool child_processes_inherit, Socket *&socket) { + Error error; + std::unique_ptr<Socket> connect_socket( + Create(ProtocolUnixDomain, child_processes_inherit, error)); + if (error.Fail()) + return error; - error = connect_socket->Connect(name); - if (error.Success()) - socket = connect_socket.release(); + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); - return error; + return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); - if (error.Fail()) - return error; - - error = listen_socket->Listen(name, 5); - if (error.Fail()) - return error; +Error Socket::UnixDomainAccept(llvm::StringRef name, + bool child_processes_inherit, Socket *&socket) { + Error error; + std::unique_ptr<Socket> listen_socket( + Create(ProtocolUnixDomain, child_processes_inherit, error)); + if (error.Fail()) + return error; - error = listen_socket->Accept(name, child_processes_inherit, socket); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; + + error = listen_socket->Accept(name, child_processes_inherit, socket); + return error; } -Error -Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixAbstract, child_processes_inherit, error)); - if (error.Fail()) - return error; - - error = connect_socket->Connect(name); - if (error.Success()) - socket = connect_socket.release(); +Error Socket::UnixAbstractConnect(llvm::StringRef name, + bool child_processes_inherit, + Socket *&socket) { + Error error; + std::unique_ptr<Socket> connect_socket( + Create(ProtocolUnixAbstract, child_processes_inherit, error)); + if (error.Fail()) return error; -} -Error -Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixAbstract,child_processes_inherit, error)); - if (error.Fail()) - return error; + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); + return error; +} - error = listen_socket->Listen(name, 5); - if (error.Fail()) - return error; +Error Socket::UnixAbstractAccept(llvm::StringRef name, + bool child_processes_inherit, + Socket *&socket) { + Error error; + std::unique_ptr<Socket> listen_socket( + Create(ProtocolUnixAbstract, child_processes_inherit, error)); + if (error.Fail()) + return error; - error = listen_socket->Accept(name, child_processes_inherit, socket); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; -} -bool -Socket::DecodeHostAndPort(llvm::StringRef host_and_port, - std::string &host_str, - std::string &port_str, - int32_t& port, - Error *error_ptr) -{ - static RegularExpression g_regex ("([^:]+):([0-9]+)"); - RegularExpression::Match regex_match(2); - if (g_regex.Execute (host_and_port.data(), ®ex_match)) - { - if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) && - regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str)) - { - bool ok = false; - port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok); - if (ok && port <= UINT16_MAX) - { - if (error_ptr) - error_ptr->Clear(); - return true; - } - // port is too large - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); - return false; - } - } + error = listen_socket->Accept(name, child_processes_inherit, socket); + return error; +} - // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing - // a port with an empty host. - host_str.clear(); - port_str.clear(); - bool ok = false; - port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok); - if (ok && port < UINT16_MAX) - { - port_str = host_and_port; +bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, + std::string &host_str, std::string &port_str, + int32_t &port, Error *error_ptr) { + static RegularExpression g_regex("([^:]+):([0-9]+)"); + RegularExpression::Match regex_match(2); + if (g_regex.Execute(host_and_port.data(), ®ex_match)) { + if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) && + regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) { + bool ok = false; + port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok); + if (ok && port <= UINT16_MAX) { if (error_ptr) - error_ptr->Clear(); + error_ptr->Clear(); return true; + } + // port is too large + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "invalid host:port specification: '%s'", host_and_port.data()); + return false; } - + } + + // If this was unsuccessful, then check if it's simply a signed 32-bit + // integer, representing + // a port with an empty host. + host_str.clear(); + port_str.clear(); + bool ok = false; + port = StringConvert::ToUInt32(host_and_port.data(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { + port_str = host_and_port; if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); - return false; + error_ptr->Clear(); + return true; + } + + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", + host_and_port.data()); + return false; } -IOObject::WaitableHandle Socket::GetWaitableHandle() -{ - // TODO: On Windows, use WSAEventSelect - return m_socket; +IOObject::WaitableHandle Socket::GetWaitableHandle() { + // TODO: On Windows, use WSAEventSelect + return m_socket; } -Error Socket::Read (void *buf, size_t &num_bytes) -{ - Error error; - int bytes_received = 0; - do - { - bytes_received = ::recv (m_socket, static_cast<char *>(buf), num_bytes, 0); - } while (bytes_received < 0 && IsInterrupted ()); - - if (bytes_received < 0) - { - SetLastError (error); - num_bytes = 0; - } - else - num_bytes = bytes_received; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); - if (log) - { - log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", - static_cast<void*>(this), - static_cast<uint64_t>(m_socket), - buf, - static_cast<uint64_t>(num_bytes), - static_cast<int64_t>(bytes_received), - error.AsCString()); - } - - return error; +Error Socket::Read(void *buf, size_t &num_bytes) { + Error error; + int bytes_received = 0; + do { + bytes_received = ::recv(m_socket, static_cast<char *>(buf), num_bytes, 0); + } while (bytes_received < 0 && IsInterrupted()); + + if (bytes_received < 0) { + SetLastError(error); + num_bytes = 0; + } else + num_bytes = bytes_received; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); + if (log) { + log->Printf("%p Socket::Read() (socket = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 + " (error = %s)", + static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, + static_cast<uint64_t>(num_bytes), + static_cast<int64_t>(bytes_received), error.AsCString()); + } + + return error; } -Error Socket::Write (const void *buf, size_t &num_bytes) -{ - Error error; - int bytes_sent = 0; - do - { - bytes_sent = Send(buf, num_bytes); - } while (bytes_sent < 0 && IsInterrupted ()); - - if (bytes_sent < 0) - { - SetLastError (error); - num_bytes = 0; - } - else - num_bytes = bytes_sent; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); - if (log) - { - log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", - static_cast<void*>(this), - static_cast<uint64_t>(m_socket), - buf, - static_cast<uint64_t>(num_bytes), - static_cast<int64_t>(bytes_sent), - error.AsCString()); - } - - return error; +Error Socket::Write(const void *buf, size_t &num_bytes) { + Error error; + int bytes_sent = 0; + do { + bytes_sent = Send(buf, num_bytes); + } while (bytes_sent < 0 && IsInterrupted()); + + if (bytes_sent < 0) { + SetLastError(error); + num_bytes = 0; + } else + num_bytes = bytes_sent; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); + if (log) { + log->Printf("%p Socket::Write() (socket = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 + " (error = %s)", + static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, + static_cast<uint64_t>(num_bytes), + static_cast<int64_t>(bytes_sent), error.AsCString()); + } + + return error; } -Error Socket::PreDisconnect() -{ - Error error; - return error; +Error Socket::PreDisconnect() { + Error error; + return error; } -Error Socket::Close() -{ - Error error; - if (!IsValid() || !m_should_close_fd) - return error; +Error Socket::Close() { + Error error; + if (!IsValid() || !m_should_close_fd) + return error; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("%p Socket::Close (fd = %i)", static_cast<void*>(this), m_socket); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p Socket::Close (fd = %i)", static_cast<void *>(this), + m_socket); #if defined(_WIN32) - bool success = !!closesocket(m_socket); + bool success = !!closesocket(m_socket); #else - bool success = !!::close (m_socket); + bool success = !!::close(m_socket); #endif - // A reference to a FD was passed in, set it to an invalid value - m_socket = kInvalidSocketValue; - if (!success) - { - SetLastError (error); - } + // A reference to a FD was passed in, set it to an invalid value + m_socket = kInvalidSocketValue; + if (!success) { + SetLastError(error); + } - return error; + return error; } - -int Socket::GetOption(int level, int option_name, int &option_value) -{ - get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value); - socklen_t option_value_size = sizeof(int); - return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size); +int Socket::GetOption(int level, int option_name, int &option_value) { + get_socket_option_arg_type option_value_p = + reinterpret_cast<get_socket_option_arg_type>(&option_value); + socklen_t option_value_size = sizeof(int); + return ::getsockopt(m_socket, level, option_name, option_value_p, + &option_value_size); } -int Socket::SetOption(int level, int option_name, int option_value) -{ - set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value); - return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); +int Socket::SetOption(int level, int option_name, int option_value) { + set_socket_option_arg_type option_value_p = + reinterpret_cast<get_socket_option_arg_type>(&option_value); + return ::setsockopt(m_socket, level, option_name, option_value_p, + sizeof(option_value)); } -size_t Socket::Send(const void *buf, const size_t num_bytes) -{ - return ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); +size_t Socket::Send(const void *buf, const size_t num_bytes) { + return ::send(m_socket, static_cast<const char *>(buf), num_bytes, 0); } -void Socket::SetLastError(Error &error) -{ +void Socket::SetLastError(Error &error) { #if defined(_WIN32) - error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); + error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); #else - error.SetErrorToErrno(); + error.SetErrorToErrno(); #endif } -NativeSocket -Socket::CreateSocket(const int domain, - const int type, - const int protocol, - bool child_processes_inherit, - Error& error) -{ - error.Clear(); - auto socketType = type; +NativeSocket Socket::CreateSocket(const int domain, const int type, + const int protocol, + bool child_processes_inherit, Error &error) { + error.Clear(); + auto socketType = type; #ifdef SOCK_CLOEXEC - if (!child_processes_inherit) - socketType |= SOCK_CLOEXEC; + if (!child_processes_inherit) + socketType |= SOCK_CLOEXEC; #endif - auto sock = ::socket (domain, socketType, protocol); - if (sock == kInvalidSocketValue) - SetLastError(error); + auto sock = ::socket(domain, socketType, protocol); + if (sock == kInvalidSocketValue) + SetLastError(error); - return sock; + return sock; } -NativeSocket -Socket::AcceptSocket(NativeSocket sockfd, - struct sockaddr *addr, - socklen_t *addrlen, - bool child_processes_inherit, - Error& error) -{ - error.Clear(); +NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, + socklen_t *addrlen, + bool child_processes_inherit, Error &error) { + error.Clear(); #if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) - // Temporary workaround for statically linking Android lldb-server with the - // latest API. - int fd = syscall(__NR_accept, sockfd, addr, addrlen); - if (fd >= 0 && !child_processes_inherit) - { - int flags = ::fcntl(fd, F_GETFD); - if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1) - return fd; - SetLastError(error); - close(fd); - } - return fd; + // Temporary workaround for statically linking Android lldb-server with the + // latest API. + int fd = syscall(__NR_accept, sockfd, addr, addrlen); + if (fd >= 0 && !child_processes_inherit) { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1) + return fd; + SetLastError(error); + close(fd); + } + return fd; #elif defined(SOCK_CLOEXEC) - int flags = 0; - if (!child_processes_inherit) { - flags |= SOCK_CLOEXEC; - } + int flags = 0; + if (!child_processes_inherit) { + flags |= SOCK_CLOEXEC; + } #if defined(__NetBSD__) - NativeSocket fd = ::paccept (sockfd, addr, addrlen, nullptr, flags); + NativeSocket fd = ::paccept(sockfd, addr, addrlen, nullptr, flags); #else - NativeSocket fd = ::accept4 (sockfd, addr, addrlen, flags); + NativeSocket fd = ::accept4(sockfd, addr, addrlen, flags); #endif #else - NativeSocket fd = ::accept (sockfd, addr, addrlen); + NativeSocket fd = ::accept(sockfd, addr, addrlen); #endif - if (fd == kInvalidSocketValue) - SetLastError(error); - return fd; + if (fd == kInvalidSocketValue) + SetLastError(error); + return fd; } diff --git a/lldb/source/Host/common/SocketAddress.cpp b/lldb/source/Host/common/SocketAddress.cpp index 7413800..9e0d84e 100644 --- a/lldb/source/Host/common/SocketAddress.cpp +++ b/lldb/source/Host/common/SocketAddress.cpp @@ -32,336 +32,254 @@ #endif // TODO: implement shortened form "::" for runs of zeros -const char* inet_ntop(int af, const void * src, - char * dst, socklen_t size) -{ - if (size==0) +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { + if (size == 0) { + return nullptr; + } + + switch (af) { + case AF_INET: { { - return nullptr; + const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src)); + if (formatted && strlen(formatted) < size) { + return ::strcpy(dst, formatted); + } } - - switch (af) - { - case AF_INET: - { - { - const char* formatted = inet_ntoa(*static_cast<const in_addr*>(src)); - if (formatted && strlen(formatted) < size) - { - return ::strcpy(dst, formatted); - } - } - return nullptr; - case AF_INET6: - { - char tmp[INET6_ADDRSTRLEN] = {0}; - const uint16_t* src16 = static_cast<const uint16_t*>(src); - int full_size = ::snprintf(tmp, sizeof(tmp), - "%x:%x:%x:%x:%x:%x:%x:%x", - ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), - ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]) - ); - if (full_size < static_cast<int>(size)) - { - return ::strcpy(dst, tmp); - } - return nullptr; - } - } + return nullptr; + case AF_INET6: { + char tmp[INET6_ADDRSTRLEN] = {0}; + const uint16_t *src16 = static_cast<const uint16_t *>(src); + int full_size = ::snprintf( + tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]), + ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]), + ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])); + if (full_size < static_cast<int>(size)) { + return ::strcpy(dst, tmp); } return nullptr; -} + } + } + } + return nullptr; +} #endif - using namespace lldb_private; //---------------------------------------------------------------------- // SocketAddress constructor //---------------------------------------------------------------------- -SocketAddress::SocketAddress () -{ - Clear (); -} - -SocketAddress::SocketAddress (const struct sockaddr &s) -{ - m_socket_addr.sa = s; -} +SocketAddress::SocketAddress() { Clear(); } +SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } -SocketAddress::SocketAddress (const struct sockaddr_in &s) -{ - m_socket_addr.sa_ipv4 = s; +SocketAddress::SocketAddress(const struct sockaddr_in &s) { + m_socket_addr.sa_ipv4 = s; } - -SocketAddress::SocketAddress (const struct sockaddr_in6 &s) -{ - m_socket_addr.sa_ipv6 = s; +SocketAddress::SocketAddress(const struct sockaddr_in6 &s) { + m_socket_addr.sa_ipv6 = s; } - -SocketAddress::SocketAddress (const struct sockaddr_storage &s) -{ - m_socket_addr.sa_storage = s; +SocketAddress::SocketAddress(const struct sockaddr_storage &s) { + m_socket_addr.sa_storage = s; } //---------------------------------------------------------------------- // SocketAddress copy constructor //---------------------------------------------------------------------- -SocketAddress::SocketAddress (const SocketAddress& rhs) : - m_socket_addr (rhs.m_socket_addr) -{ -} +SocketAddress::SocketAddress(const SocketAddress &rhs) + : m_socket_addr(rhs.m_socket_addr) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -SocketAddress::~SocketAddress() -{ -} +SocketAddress::~SocketAddress() {} -void -SocketAddress::Clear () -{ - memset (&m_socket_addr, 0, sizeof(m_socket_addr)); +void SocketAddress::Clear() { + memset(&m_socket_addr, 0, sizeof(m_socket_addr)); } -bool -SocketAddress::IsValid () const -{ - return GetLength () != 0; +bool SocketAddress::IsValid() const { return GetLength() != 0; } + +static socklen_t GetFamilyLength(sa_family_t family) { + switch (family) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + assert(0 && "Unsupported address family"); + return 0; } -static socklen_t -GetFamilyLength (sa_family_t family) -{ - switch (family) - { - case AF_INET: return sizeof(struct sockaddr_in); - case AF_INET6: return sizeof(struct sockaddr_in6); - } - assert(0 && "Unsupported address family"); - return 0; -} - -socklen_t -SocketAddress::GetLength () const -{ +socklen_t SocketAddress::GetLength() const { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - return m_socket_addr.sa.sa_len; + return m_socket_addr.sa.sa_len; #else - return GetFamilyLength (GetFamily()); + return GetFamilyLength(GetFamily()); #endif } -socklen_t -SocketAddress::GetMaxLength () -{ - return sizeof (sockaddr_t); -} +socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); } -sa_family_t -SocketAddress::GetFamily () const -{ - return m_socket_addr.sa.sa_family; +sa_family_t SocketAddress::GetFamily() const { + return m_socket_addr.sa.sa_family; } -void -SocketAddress::SetFamily (sa_family_t family) -{ - m_socket_addr.sa.sa_family = family; +void SocketAddress::SetFamily(sa_family_t family) { + m_socket_addr.sa.sa_family = family; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - m_socket_addr.sa.sa_len = GetFamilyLength (family); + m_socket_addr.sa.sa_len = GetFamilyLength(family); #endif } -std::string -SocketAddress::GetIPAddress () const -{ - char str[INET6_ADDRSTRLEN] = {0}; - switch (GetFamily()) - { - case AF_INET: - if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str))) - return str; - break; - case AF_INET6: - if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str))) - return str; - break; - } - return ""; +std::string SocketAddress::GetIPAddress() const { + char str[INET6_ADDRSTRLEN] = {0}; + switch (GetFamily()) { + case AF_INET: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, + sizeof(str))) + return str; + break; + case AF_INET6: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, + sizeof(str))) + return str; + break; + } + return ""; } -uint16_t -SocketAddress::GetPort () const -{ - switch (GetFamily()) - { - case AF_INET: return ntohs(m_socket_addr.sa_ipv4.sin_port); - case AF_INET6: return ntohs(m_socket_addr.sa_ipv6.sin6_port); - } - return 0; +uint16_t SocketAddress::GetPort() const { + switch (GetFamily()) { + case AF_INET: + return ntohs(m_socket_addr.sa_ipv4.sin_port); + case AF_INET6: + return ntohs(m_socket_addr.sa_ipv6.sin6_port); + } + return 0; } -bool -SocketAddress::SetPort (uint16_t port) -{ - switch (GetFamily()) - { - case AF_INET: - m_socket_addr.sa_ipv4.sin_port = htons(port); - return true; - - case AF_INET6: - m_socket_addr.sa_ipv6.sin6_port = htons(port); - return true; - } - return false; +bool SocketAddress::SetPort(uint16_t port) { + switch (GetFamily()) { + case AF_INET: + m_socket_addr.sa_ipv4.sin_port = htons(port); + return true; + + case AF_INET6: + m_socket_addr.sa_ipv6.sin6_port = htons(port); + return true; + } + return false; } //---------------------------------------------------------------------- // SocketAddress assignment operator //---------------------------------------------------------------------- -const SocketAddress& -SocketAddress::operator=(const SocketAddress& rhs) -{ - if (this != &rhs) - m_socket_addr = rhs.m_socket_addr; - return *this; +const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) { + if (this != &rhs) + m_socket_addr = rhs.m_socket_addr; + return *this; } -const SocketAddress& -SocketAddress::operator=(const struct addrinfo *addr_info) -{ - Clear(); - if (addr_info && - addr_info->ai_addr && - addr_info->ai_addrlen > 0&& - addr_info->ai_addrlen <= sizeof m_socket_addr) - { - ::memcpy (&m_socket_addr, - addr_info->ai_addr, - addr_info->ai_addrlen); - } - return *this; +const SocketAddress &SocketAddress:: +operator=(const struct addrinfo *addr_info) { + Clear(); + if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && + addr_info->ai_addrlen <= sizeof m_socket_addr) { + ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); + } + return *this; } -const SocketAddress& -SocketAddress::operator=(const struct sockaddr &s) -{ - m_socket_addr.sa = s; - return *this; +const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) { + m_socket_addr.sa = s; + return *this; } -const SocketAddress& -SocketAddress::operator=(const struct sockaddr_in &s) -{ - m_socket_addr.sa_ipv4 = s; - return *this; +const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) { + m_socket_addr.sa_ipv4 = s; + return *this; } -const SocketAddress& -SocketAddress::operator=(const struct sockaddr_in6 &s) -{ - m_socket_addr.sa_ipv6 = s; - return *this; +const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) { + m_socket_addr.sa_ipv6 = s; + return *this; } -const SocketAddress& -SocketAddress::operator=(const struct sockaddr_storage &s) -{ - m_socket_addr.sa_storage = s; - return *this; +const SocketAddress &SocketAddress:: +operator=(const struct sockaddr_storage &s) { + m_socket_addr.sa_storage = s; + return *this; } -bool -SocketAddress::getaddrinfo (const char *host, - const char *service, - int ai_family, - int ai_socktype, - int ai_protocol, - int ai_flags) -{ - Clear (); - - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = ai_family; - hints.ai_socktype = ai_socktype; - hints.ai_protocol = ai_protocol; - hints.ai_flags = ai_flags; - - bool result = false; - struct addrinfo *service_info_list = NULL; - int err = ::getaddrinfo (host, service, &hints, &service_info_list); - if (err == 0 && service_info_list) - { - *this = service_info_list; - result = IsValid (); - } - - if (service_info_list) - ::freeaddrinfo(service_info_list); - - return result; +bool SocketAddress::getaddrinfo(const char *host, const char *service, + int ai_family, int ai_socktype, int ai_protocol, + int ai_flags) { + Clear(); + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = ai_family; + hints.ai_socktype = ai_socktype; + hints.ai_protocol = ai_protocol; + hints.ai_flags = ai_flags; + + bool result = false; + struct addrinfo *service_info_list = NULL; + int err = ::getaddrinfo(host, service, &hints, &service_info_list); + if (err == 0 && service_info_list) { + *this = service_info_list; + result = IsValid(); + } + + if (service_info_list) + ::freeaddrinfo(service_info_list); + + return result; } +bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) { + switch (family) { + case AF_INET: + SetFamily(AF_INET); + if (SetPort(port)) { + m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + return true; + } + break; -bool -SocketAddress::SetToLocalhost (sa_family_t family, uint16_t port) -{ - switch (family) - { - case AF_INET: - SetFamily (AF_INET); - if (SetPort (port)) - { - m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - return true; - } - break; - - case AF_INET6: - SetFamily (AF_INET6); - if (SetPort (port)) - { - m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; - return true; - } - break; - + case AF_INET6: + SetFamily(AF_INET6); + if (SetPort(port)) { + m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; + return true; } - Clear(); - return false; + break; + } + Clear(); + return false; } -bool -SocketAddress::SetToAnyAddress (sa_family_t family, uint16_t port) -{ - switch (family) - { - case AF_INET: - SetFamily (AF_INET); - if (SetPort (port)) - { - m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_ANY); - return true; - } - break; - - case AF_INET6: - SetFamily (AF_INET6); - if (SetPort (port)) - { - m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; - return true; - } - break; - +bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) { + switch (family) { + case AF_INET: + SetFamily(AF_INET); + if (SetPort(port)) { + m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); + return true; + } + break; + + case AF_INET6: + SetFamily(AF_INET6); + if (SetPort(port)) { + m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; + return true; } - Clear(); - return false; + break; + } + Clear(); + return false; } diff --git a/lldb/source/Host/common/SoftwareBreakpoint.cpp b/lldb/source/Host/common/SoftwareBreakpoint.cpp index 51cb34f..149ce6b 100644 --- a/lldb/source/Host/common/SoftwareBreakpoint.cpp +++ b/lldb/source/Host/common/SoftwareBreakpoint.cpp @@ -21,296 +21,332 @@ using namespace lldb_private; // static members // ------------------------------------------------------------------- -Error -SoftwareBreakpoint::CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_sp) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); +Error SoftwareBreakpoint::CreateSoftwareBreakpoint( + NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, + NativeBreakpointSP &breakpoint_sp) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + + // Validate the address. + if (addr == LLDB_INVALID_ADDRESS) + return Error("SoftwareBreakpoint::%s invalid load address specified.", + __FUNCTION__); + + // Ask the NativeProcessProtocol subclass to fill in the correct software + // breakpoint + // trap for the breakpoint site. + size_t bp_opcode_size = 0; + const uint8_t *bp_opcode_bytes = NULL; + Error error = process.GetSoftwareBreakpointTrapOpcode( + size_hint, bp_opcode_size, bp_opcode_bytes); + + if (error.Fail()) { if (log) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - // Validate the address. - if (addr == LLDB_INVALID_ADDRESS) - return Error ("SoftwareBreakpoint::%s invalid load address specified.", __FUNCTION__); - - // Ask the NativeProcessProtocol subclass to fill in the correct software breakpoint - // trap for the breakpoint site. - size_t bp_opcode_size = 0; - const uint8_t *bp_opcode_bytes = NULL; - Error error = process.GetSoftwareBreakpointTrapOpcode (size_hint, bp_opcode_size, bp_opcode_bytes); - - if (error.Fail ()) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to retrieve software breakpoint trap opcode: %s", __FUNCTION__, error.AsCString ()); - return error; - } - - // Validate size of trap opcode. - if (bp_opcode_size == 0) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", __FUNCTION__); - return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%" PRIx64, addr); - } - - if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s cannot support %lu trapcode bytes, max size is %lu", __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned too many trap opcode bytes: requires %lu but we only support a max of %lu", bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - } - - // Validate that we received opcodes. - if (!bp_opcode_bytes) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", __FUNCTION__); - return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned NULL trap opcode bytes, unable to get breakpoint trap for address 0x%" PRIx64, addr); - } - - // Enable the breakpoint. - uint8_t saved_opcode_bytes [MAX_TRAP_OPCODE_SIZE]; - error = EnableSoftwareBreakpoint (process, addr, bp_opcode_size, bp_opcode_bytes, saved_opcode_bytes); - if (error.Fail ()) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s: failed to enable new breakpoint at 0x%" PRIx64 ": %s", __FUNCTION__, addr, error.AsCString ()); - return error; - } + log->Printf("SoftwareBreakpoint::%s failed to retrieve software " + "breakpoint trap opcode: %s", + __FUNCTION__, error.AsCString()); + return error; + } + // Validate size of trap opcode. + if (bp_opcode_size == 0) { if (log) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr); - - // Set the breakpoint and verified it was written properly. Now - // create a breakpoint remover that understands how to undo this - // breakpoint. - breakpoint_sp.reset (new SoftwareBreakpoint (process, addr, saved_opcode_bytes, bp_opcode_bytes, bp_opcode_size)); - return Error (); -} - -Error -SoftwareBreakpoint::EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes) -{ - assert (bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && "bp_opcode_size out of valid range"); - assert (bp_opcode_bytes && "bp_opcode_bytes is NULL"); - assert (saved_opcode_bytes && "saved_opcode_bytes is NULL"); - - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + log->Printf("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", + __FUNCTION__); + return Error("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " + "returned zero, unable to get breakpoint trap for address " + "0x%" PRIx64, + addr); + } + + if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE) { if (log) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + log->Printf("SoftwareBreakpoint::%s cannot support %lu trapcode bytes, " + "max size is %lu", + __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE); + return Error("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " + "returned too many trap opcode bytes: requires %lu but we " + "only support a max of %lu", + bp_opcode_size, MAX_TRAP_OPCODE_SIZE); + } + + // Validate that we received opcodes. + if (!bp_opcode_bytes) { + if (log) + log->Printf("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", + __FUNCTION__); + return Error("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " + "returned NULL trap opcode bytes, unable to get breakpoint " + "trap for address 0x%" PRIx64, + addr); + } + + // Enable the breakpoint. + uint8_t saved_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; + error = EnableSoftwareBreakpoint(process, addr, bp_opcode_size, + bp_opcode_bytes, saved_opcode_bytes); + if (error.Fail()) { + if (log) + log->Printf("SoftwareBreakpoint::%s: failed to enable new breakpoint at " + "0x%" PRIx64 ": %s", + __FUNCTION__, addr, error.AsCString()); + return error; + } + + if (log) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", + __FUNCTION__, addr); + + // Set the breakpoint and verified it was written properly. Now + // create a breakpoint remover that understands how to undo this + // breakpoint. + breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes, + bp_opcode_bytes, bp_opcode_size)); + return Error(); +} - // Save the original opcodes by reading them so we can restore later. - size_t bytes_read = 0; +Error SoftwareBreakpoint::EnableSoftwareBreakpoint( + NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, + const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes) { + assert(bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && + "bp_opcode_size out of valid range"); + assert(bp_opcode_bytes && "bp_opcode_bytes is NULL"); + assert(saved_opcode_bytes && "saved_opcode_bytes is NULL"); - Error error = process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read); - if (error.Fail ()) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ()); - return error; - } + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - // Ensure we read as many bytes as we expected. - if (bytes_read != bp_opcode_size) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read); - return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read); - } + // Save the original opcodes by reading them so we can restore later. + size_t bytes_read = 0; - // Log what we read. + Error error = + process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read); + if (error.Fail()) { if (log) - { - int i = 0; - for (const uint8_t *read_byte = saved_opcode_bytes; read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) - { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " ovewriting byte index %d (was 0x%hhx)", - __FUNCTION__, addr, i++, *read_byte); - } - } - - // Write a software breakpoint in place of the original opcode. - size_t bytes_written = 0; - error = process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written); - if (error.Fail ()) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to write memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ()); - return error; - } - - // Ensure we wrote as many bytes as we expected. - if (bytes_written != bp_opcode_size) - { - error.SetErrorStringWithFormat("SoftwareBreakpoint::%s failed write memory while attempting to set breakpoint: attempted to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_written); - if (log) - log->PutCString (error.AsCString ()); - return error; - } - - uint8_t verify_bp_opcode_bytes [MAX_TRAP_OPCODE_SIZE]; - size_t verify_bytes_read = 0; - error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size, verify_bytes_read); - if (error.Fail ()) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify the breakpoint set: %s", __FUNCTION__, error.AsCString ()); - return error; - } + log->Printf("SoftwareBreakpoint::%s failed to read memory while " + "attempting to set breakpoint: %s", + __FUNCTION__, error.AsCString()); + return error; + } - // Ensure we read as many verification bytes as we expected. - if (verify_bytes_read != bp_opcode_size) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read); - return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read); + // Ensure we read as many bytes as we expected. + if (bytes_read != bp_opcode_size) { + if (log) + log->Printf("SoftwareBreakpoint::%s failed to read memory while " + "attempting to set breakpoint: attempted to read %lu bytes " + "but only read %" PRIu64, + __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read); + return Error("SoftwareBreakpoint::%s failed to read memory while " + "attempting to set breakpoint: attempted to read %lu bytes " + "but only read %" PRIu64, + __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read); + } + + // Log what we read. + if (log) { + int i = 0; + for (const uint8_t *read_byte = saved_opcode_bytes; + read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) { + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 + " ovewriting byte index %d (was 0x%hhx)", + __FUNCTION__, addr, i++, *read_byte); } + } - if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0) - { - if (log) - log->Printf ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr); - return Error ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr); - } + // Write a software breakpoint in place of the original opcode. + size_t bytes_written = 0; + error = + process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written); + if (error.Fail()) { + if (log) + log->Printf("SoftwareBreakpoint::%s failed to write memory while " + "attempting to set breakpoint: %s", + __FUNCTION__, error.AsCString()); + return error; + } + + // Ensure we wrote as many bytes as we expected. + if (bytes_written != bp_opcode_size) { + error.SetErrorStringWithFormat( + "SoftwareBreakpoint::%s failed write memory while attempting to set " + "breakpoint: attempted to write %lu bytes but only wrote %" PRIu64, + __FUNCTION__, bp_opcode_size, (uint64_t)bytes_written); + if (log) + log->PutCString(error.AsCString()); + return error; + } + uint8_t verify_bp_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; + size_t verify_bytes_read = 0; + error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size, + verify_bytes_read); + if (error.Fail()) { if (log) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr); + log->Printf("SoftwareBreakpoint::%s failed to read memory while " + "attempting to verify the breakpoint set: %s", + __FUNCTION__, error.AsCString()); + return error; + } - return Error (); + // Ensure we read as many verification bytes as we expected. + if (verify_bytes_read != bp_opcode_size) { + if (log) + log->Printf("SoftwareBreakpoint::%s failed to read memory while " + "attempting to verify breakpoint: attempted to read %lu " + "bytes but only read %" PRIu64, + __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read); + return Error("SoftwareBreakpoint::%s failed to read memory while " + "attempting to verify breakpoint: attempted to read %lu bytes " + "but only read %" PRIu64, + __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read); + } + + if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0) { + if (log) + log->Printf("SoftwareBreakpoint::%s: verification of software breakpoint " + "writing failed - trap opcodes not successfully read back " + "after writing when setting breakpoint at 0x%" PRIx64, + __FUNCTION__, addr); + return Error("SoftwareBreakpoint::%s: verification of software breakpoint " + "writing failed - trap opcodes not successfully read back " + "after writing when setting breakpoint at 0x%" PRIx64, + __FUNCTION__, addr); + } + + if (log) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", + __FUNCTION__, addr); + + return Error(); } // ------------------------------------------------------------------- // instance-level members // ------------------------------------------------------------------- -SoftwareBreakpoint::SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size) : - NativeBreakpoint (addr), - m_process (process), - m_saved_opcodes (), - m_trap_opcodes (), - m_opcode_size (opcode_size) -{ - assert ( opcode_size > 0 && "setting software breakpoint with no trap opcodes"); - assert ( opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large"); - - ::memcpy (m_saved_opcodes, saved_opcodes, opcode_size); - ::memcpy (m_trap_opcodes, trap_opcodes, opcode_size); +SoftwareBreakpoint::SoftwareBreakpoint(NativeProcessProtocol &process, + lldb::addr_t addr, + const uint8_t *saved_opcodes, + const uint8_t *trap_opcodes, + size_t opcode_size) + : NativeBreakpoint(addr), m_process(process), m_saved_opcodes(), + m_trap_opcodes(), m_opcode_size(opcode_size) { + assert(opcode_size > 0 && "setting software breakpoint with no trap opcodes"); + assert(opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large"); + + ::memcpy(m_saved_opcodes, saved_opcodes, opcode_size); + ::memcpy(m_trap_opcodes, trap_opcodes, opcode_size); } -Error -SoftwareBreakpoint::DoEnable () -{ - return EnableSoftwareBreakpoint (m_process, m_addr, m_opcode_size, m_trap_opcodes, m_saved_opcodes); +Error SoftwareBreakpoint::DoEnable() { + return EnableSoftwareBreakpoint(m_process, m_addr, m_opcode_size, + m_trap_opcodes, m_saved_opcodes); } -Error -SoftwareBreakpoint::DoDisable () -{ - Error error; - assert (m_addr && (m_addr != LLDB_INVALID_ADDRESS) && "can't remove a software breakpoint for an invalid address"); +Error SoftwareBreakpoint::DoDisable() { + Error error; + assert(m_addr && (m_addr != LLDB_INVALID_ADDRESS) && + "can't remove a software breakpoint for an invalid address"); - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, m_addr); - - assert ( (m_opcode_size > 0) && "cannot restore opcodes when there are no opcodes"); - - if (m_opcode_size > 0) - { - // Clear a software breakpoint instruction - uint8_t curr_break_op [MAX_TRAP_OPCODE_SIZE]; - bool break_op_found = false; - assert (m_opcode_size <= sizeof (curr_break_op)); - - // Read the breakpoint opcode - size_t bytes_read = 0; - error = m_process.ReadMemory (m_addr, curr_break_op, m_opcode_size, bytes_read); - if (error.Success() && bytes_read < m_opcode_size) - { - error.SetErrorStringWithFormat ("SoftwareBreakpointr::%s addr=0x%" PRIx64 ": tried to read %lu bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_read); - } - if (error.Success ()) - { - bool verify = false; - // Make sure the breakpoint opcode exists at this address - if (::memcmp (curr_break_op, m_trap_opcodes, m_opcode_size) == 0) - { - break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore - // the saved opcode. - size_t bytes_written = 0; - error = m_process.WriteMemory (m_addr, m_saved_opcodes, m_opcode_size, bytes_written); - if (error.Success() && bytes_written < m_opcode_size) - { - error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_written); - } - if (error.Success ()) - { - verify = true; - } - } - else - { - error.SetErrorString("Original breakpoint trap is no longer in memory."); - // Set verify to true and so we can check if the original opcode has already been restored - verify = true; - } + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, + m_addr); - if (verify) - { - uint8_t verify_opcode [MAX_TRAP_OPCODE_SIZE]; - assert (m_opcode_size <= sizeof (verify_opcode)); - // Verify that our original opcode made it back to the inferior - - size_t verify_bytes_read = 0; - error = m_process.ReadMemory (m_addr, verify_opcode, m_opcode_size, verify_bytes_read); - if (error.Success() && verify_bytes_read < m_opcode_size) - { - error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to read %lu verification bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)verify_bytes_read); - } - if (error.Success ()) - { - // compare the memory we just read with the original opcode - if (::memcmp (m_saved_opcodes, verify_opcode, m_opcode_size) == 0) - { - // SUCCESS - if (log) - { - int i = 0; - for (const uint8_t *verify_byte = verify_opcode; verify_byte < verify_opcode + m_opcode_size; ++verify_byte) - { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " replaced byte index %d with 0x%hhx", - __FUNCTION__, m_addr, i++, *verify_byte); - } - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, m_addr); - } - return error; - } - else - { - if (break_op_found) - error.SetErrorString("Failed to restore original opcode."); - } - } - else - error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored."); - } + assert((m_opcode_size > 0) && + "cannot restore opcodes when there are no opcodes"); + + if (m_opcode_size > 0) { + // Clear a software breakpoint instruction + uint8_t curr_break_op[MAX_TRAP_OPCODE_SIZE]; + bool break_op_found = false; + assert(m_opcode_size <= sizeof(curr_break_op)); + + // Read the breakpoint opcode + size_t bytes_read = 0; + error = + m_process.ReadMemory(m_addr, curr_break_op, m_opcode_size, bytes_read); + if (error.Success() && bytes_read < m_opcode_size) { + error.SetErrorStringWithFormat( + "SoftwareBreakpointr::%s addr=0x%" PRIx64 + ": tried to read %lu bytes but only read %" PRIu64, + __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_read); + } + if (error.Success()) { + bool verify = false; + // Make sure the breakpoint opcode exists at this address + if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) { + break_op_found = true; + // We found a valid breakpoint opcode at this address, now restore + // the saved opcode. + size_t bytes_written = 0; + error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size, + bytes_written); + if (error.Success() && bytes_written < m_opcode_size) { + error.SetErrorStringWithFormat( + "SoftwareBreakpoint::%s addr=0x%" PRIx64 + ": tried to write %lu bytes but only wrote %" PRIu64, + __FUNCTION__, m_addr, m_opcode_size, (uint64_t)bytes_written); } + if (error.Success()) { + verify = true; + } + } else { + error.SetErrorString( + "Original breakpoint trap is no longer in memory."); + // Set verify to true and so we can check if the original opcode has + // already been restored + verify = true; + } + + if (verify) { + uint8_t verify_opcode[MAX_TRAP_OPCODE_SIZE]; + assert(m_opcode_size <= sizeof(verify_opcode)); + // Verify that our original opcode made it back to the inferior + + size_t verify_bytes_read = 0; + error = m_process.ReadMemory(m_addr, verify_opcode, m_opcode_size, + verify_bytes_read); + if (error.Success() && verify_bytes_read < m_opcode_size) { + error.SetErrorStringWithFormat( + "SoftwareBreakpoint::%s addr=0x%" PRIx64 + ": tried to read %lu verification bytes but only read %" PRIu64, + __FUNCTION__, m_addr, m_opcode_size, (uint64_t)verify_bytes_read); + } + if (error.Success()) { + // compare the memory we just read with the original opcode + if (::memcmp(m_saved_opcodes, verify_opcode, m_opcode_size) == 0) { + // SUCCESS + if (log) { + int i = 0; + for (const uint8_t *verify_byte = verify_opcode; + verify_byte < verify_opcode + m_opcode_size; ++verify_byte) { + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 + " replaced byte index %d with 0x%hhx", + __FUNCTION__, m_addr, i++, *verify_byte); + } + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 + " -- SUCCESS", + __FUNCTION__, m_addr); + } + return error; + } else { + if (break_op_found) + error.SetErrorString("Failed to restore original opcode."); + } + } else + error.SetErrorString("Failed to read memory to verify that " + "breakpoint trap was restored."); + } } + } - if (log && error.Fail ()) - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s", - __FUNCTION__, - m_addr, - error.AsCString()); - return error; -} - -bool -SoftwareBreakpoint::IsSoftwareBreakpoint () const -{ - return true; + if (log && error.Fail()) + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s", + __FUNCTION__, m_addr, error.AsCString()); + return error; } +bool SoftwareBreakpoint::IsSoftwareBreakpoint() const { return true; } diff --git a/lldb/source/Host/common/StringConvert.cpp b/lldb/source/Host/common/StringConvert.cpp index c4ff675..b417143 100644 --- a/lldb/source/Host/common/StringConvert.cpp +++ b/lldb/source/Host/common/StringConvert.cpp @@ -15,103 +15,86 @@ // Project includes #include "lldb/Host/StringConvert.h" -namespace lldb_private -{ - namespace StringConvert - { +namespace lldb_private { +namespace StringConvert { - int32_t - ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) - { - if (s && s[0]) - { - char *end = nullptr; - const long sval = ::strtol (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); - return (int32_t)sval; // All characters were used, return the result - } - } - if (success_ptr) - *success_ptr = false; - return fail_value; - } +int32_t ToSInt32(const char *s, int32_t fail_value, int base, + bool *success_ptr) { + if (s && s[0]) { + char *end = nullptr; + const long sval = ::strtol(s, &end, base); + if (*end == '\0') { + if (success_ptr) + *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); + return (int32_t)sval; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} - uint32_t - ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) - { - if (s && s[0]) - { - char *end = nullptr; - const unsigned long uval = ::strtoul (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = (uval <= UINT32_MAX); - return (uint32_t)uval; // All characters were used, return the result - } - } - if (success_ptr) - *success_ptr = false; - return fail_value; - } +uint32_t ToUInt32(const char *s, uint32_t fail_value, int base, + bool *success_ptr) { + if (s && s[0]) { + char *end = nullptr; + const unsigned long uval = ::strtoul(s, &end, base); + if (*end == '\0') { + if (success_ptr) + *success_ptr = (uval <= UINT32_MAX); + return (uint32_t)uval; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} - int64_t - ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) - { - if (s && s[0]) - { - char *end = nullptr; - int64_t uval = ::strtoll (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = true; - return uval; // All characters were used, return the result - } - } - if (success_ptr) - *success_ptr = false; - return fail_value; - } +int64_t ToSInt64(const char *s, int64_t fail_value, int base, + bool *success_ptr) { + if (s && s[0]) { + char *end = nullptr; + int64_t uval = ::strtoll(s, &end, base); + if (*end == '\0') { + if (success_ptr) + *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} - uint64_t - ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) - { - if (s && s[0]) - { - char *end = nullptr; - uint64_t uval = ::strtoull (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = true; - return uval; // All characters were used, return the result - } - } - if (success_ptr) *success_ptr = false; - return fail_value; - } +uint64_t ToUInt64(const char *s, uint64_t fail_value, int base, + bool *success_ptr) { + if (s && s[0]) { + char *end = nullptr; + uint64_t uval = ::strtoull(s, &end, base); + if (*end == '\0') { + if (success_ptr) + *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} - double - ToDouble (const char *s, double fail_value, bool *success_ptr) - { - if (s && s[0]) - { - char *end = nullptr; - double val = strtod (s, &end); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = true; - return val; // All characters were used, return the result - } - } - if (success_ptr) - *success_ptr = false; - return fail_value; - } +double ToDouble(const char *s, double fail_value, bool *success_ptr) { + if (s && s[0]) { + char *end = nullptr; + double val = strtod(s, &end); + if (*end == '\0') { + if (success_ptr) + *success_ptr = true; + return val; // All characters were used, return the result } + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} +} } diff --git a/lldb/source/Host/common/Symbols.cpp b/lldb/source/Host/common/Symbols.cpp index a6ecaf2..8453428 100644 --- a/lldb/source/Host/common/Symbols.cpp +++ b/lldb/source/Host/common/Symbols.cpp @@ -34,294 +34,259 @@ using namespace llvm::MachO; #if defined(__APPLE__) // Forward declaration of method defined in source/Host/macosx/Symbols.cpp -int -LocateMacOSXFilesUsingDebugSymbols -( - const ModuleSpec &module_spec, - ModuleSpec &return_module_spec -); +int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, + ModuleSpec &return_module_spec); #else -int -LocateMacOSXFilesUsingDebugSymbols -( - const ModuleSpec &module_spec, - ModuleSpec &return_module_spec -) { - // Cannot find MacOSX files using debug symbols on non MacOSX. - return 0; +int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, + ModuleSpec &return_module_spec) { + // Cannot find MacOSX files using debug symbols on non MacOSX. + return 0; } #endif -static bool -FileAtPathContainsArchAndUUID (const FileSpec &file_fspec, const ArchSpec *arch, const lldb_private::UUID *uuid) -{ - ModuleSpecList module_specs; - if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) - { - ModuleSpec spec; - for (size_t i = 0; i < module_specs.GetSize(); ++i) - { - assert(module_specs.GetModuleSpecAtIndex(i, spec)); - if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && - (arch == NULL || (spec.GetArchitecturePtr() && spec.GetArchitecture().IsCompatibleMatch(*arch)))) - { - return true; - } - } +static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, + const ArchSpec *arch, + const lldb_private::UUID *uuid) { + ModuleSpecList module_specs; + if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { + ModuleSpec spec; + for (size_t i = 0; i < module_specs.GetSize(); ++i) { + assert(module_specs.GetModuleSpecAtIndex(i, spec)); + if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && + (arch == NULL || (spec.GetArchitecturePtr() && + spec.GetArchitecture().IsCompatibleMatch(*arch)))) { + return true; + } } - return false; + } + return false; } -static bool -LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec) -{ - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - if (exec_fspec) - { - char path[PATH_MAX]; - if (exec_fspec->GetPath(path, sizeof(path))) - { - // Make sure the module isn't already just a dSYM file... - if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) - { - if (log) - { - if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) - { - log->Printf ("Searching for dSYM bundle next to executable %s, UUID %s", path, module_spec.GetUUIDPtr()->GetAsString().c_str()); - } - else - { - log->Printf ("Searching for dSYM bundle next to executable %s", path); - } - } - size_t obj_file_path_length = strlen(path); - ::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1); - ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1); - - dsym_fspec.SetFile(path, false); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) - { - if (log) - { - log->Printf ("dSYM with matching UUID & arch found at %s", path); - } - return true; +static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, + FileSpec &dsym_fspec) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + if (exec_fspec) { + char path[PATH_MAX]; + if (exec_fspec->GetPath(path, sizeof(path))) { + // Make sure the module isn't already just a dSYM file... + if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) { + if (log) { + if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) { + log->Printf( + "Searching for dSYM bundle next to executable %s, UUID %s", + path, module_spec.GetUUIDPtr()->GetAsString().c_str()); + } else { + log->Printf("Searching for dSYM bundle next to executable %s", + path); + } + } + size_t obj_file_path_length = strlen(path); + ::strncat(path, ".dSYM/Contents/Resources/DWARF/", + sizeof(path) - strlen(path) - 1); + ::strncat(path, exec_fspec->GetFilename().AsCString(), + sizeof(path) - strlen(path) - 1); + + dsym_fspec.SetFile(path, false); + + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + if (dsym_fspec.Exists() && + FileAtPathContainsArchAndUUID(dsym_fspec, + module_spec.GetArchitecturePtr(), + module_spec.GetUUIDPtr())) { + if (log) { + log->Printf("dSYM with matching UUID & arch found at %s", path); + } + return true; + } else { + path[obj_file_path_length] = '\0'; + + char *last_dot = strrchr(path, '.'); + while (last_dot != NULL && last_dot[0]) { + char *next_slash = strchr(last_dot, '/'); + if (next_slash != NULL) { + *next_slash = '\0'; + ::strncat(path, ".dSYM/Contents/Resources/DWARF/", + sizeof(path) - strlen(path) - 1); + ::strncat(path, exec_fspec->GetFilename().AsCString(), + sizeof(path) - strlen(path) - 1); + dsym_fspec.SetFile(path, false); + if (dsym_fspec.Exists() && + FileAtPathContainsArchAndUUID( + dsym_fspec, module_spec.GetArchitecturePtr(), + module_spec.GetUUIDPtr())) { + if (log) { + log->Printf("dSYM with matching UUID & arch found at %s", + path); } + return true; + } else { + *last_dot = '\0'; + char *prev_slash = strrchr(path, '/'); + if (prev_slash != NULL) + *prev_slash = '\0'; else - { - path[obj_file_path_length] = '\0'; - - char *last_dot = strrchr(path, '.'); - while (last_dot != NULL && last_dot[0]) - { - char *next_slash = strchr(last_dot, '/'); - if (next_slash != NULL) - { - *next_slash = '\0'; - ::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1); - ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1); - dsym_fspec.SetFile(path, false); - if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) - { - if (log) - { - log->Printf ("dSYM with matching UUID & arch found at %s", path); - } - return true; - } - else - { - *last_dot = '\0'; - char *prev_slash = strrchr(path, '/'); - if (prev_slash != NULL) - *prev_slash = '\0'; - else - break; - } - } - else - { - break; - } - } - } + break; + } + } else { + break; } + } } + } } - dsym_fspec.Clear(); - return false; + } + dsym_fspec.Clear(); + return false; } -FileSpec -LocateExecutableSymbolFileDsym (const ModuleSpec &module_spec) -{ - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - - Timer scoped_timer (LLVM_PRETTY_FUNCTION, - "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", - (const void*)uuid); - - FileSpec symbol_fspec; - ModuleSpec dsym_module_spec; - // First try and find the dSYM in the same directory as the executable or in - // an appropriate parent directory - if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false) - { - // We failed to easily find the dSYM above, so use DebugSymbols - LocateMacOSXFilesUsingDebugSymbols (module_spec, dsym_module_spec); - } - else - { - dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; - } - return dsym_module_spec.GetSymbolFileSpec(); +FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", + arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); + + FileSpec symbol_fspec; + ModuleSpec dsym_module_spec; + // First try and find the dSYM in the same directory as the executable or in + // an appropriate parent directory + if (LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec) == false) { + // We failed to easily find the dSYM above, so use DebugSymbols + LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec); + } else { + dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; + } + return dsym_module_spec.GetSymbolFileSpec(); } -ModuleSpec -Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) -{ - ModuleSpec result; - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - Timer scoped_timer (LLVM_PRETTY_FUNCTION, - "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", - (const void*)uuid); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (exec_fspec && - ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) - { - result.GetFileSpec() = exec_fspec; - } - else - { - LocateMacOSXFilesUsingDebugSymbols (module_spec, result); - } - return result; +ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) { + ModuleSpec result; + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", + arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); + + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + if (exec_fspec && + ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { + result.GetFileSpec() = exec_fspec; + } else { + LocateMacOSXFilesUsingDebugSymbols(module_spec, result); + } + return result; } -FileSpec -Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) -{ - FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); - if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists()) - return symbol_file_spec; +FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { + FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); + if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists()) + return symbol_file_spec; - const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); - if (symbol_filename && symbol_filename[0]) - { - FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths()); + const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); + if (symbol_filename && symbol_filename[0]) { + FileSpecList debug_file_search_paths( + Target::GetDefaultDebugFileSearchPaths()); - // Add module directory. - const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory(); - debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true)); + // Add module directory. + const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory(); + debug_file_search_paths.AppendIfUnique( + FileSpec(file_dir.AsCString("."), true)); - // Add current working directory. - debug_file_search_paths.AppendIfUnique (FileSpec(".", true)); + // Add current working directory. + debug_file_search_paths.AppendIfUnique(FileSpec(".", true)); #ifndef LLVM_ON_WIN32 - // Add /usr/lib/debug directory. - debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true)); + // Add /usr/lib/debug directory. + debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); #endif // LLVM_ON_WIN32 - std::string uuid_str; - const UUID &module_uuid = module_spec.GetUUID(); - if (module_uuid.IsValid()) - { - // 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(""); - uuid_str.insert (2, 1, '/'); - uuid_str = uuid_str + ".debug"; - } + std::string uuid_str; + const UUID &module_uuid = module_spec.GetUUID(); + if (module_uuid.IsValid()) { + // 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(""); + uuid_str.insert(2, 1, '/'); + uuid_str = uuid_str + ".debug"; + } - size_t num_directories = debug_file_search_paths.GetSize(); - for (size_t idx = 0; idx < num_directories; ++idx) - { - FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex (idx); - dirspec.ResolvePath(); - if (!dirspec.Exists() || !dirspec.IsDirectory()) - continue; - - std::vector<std::string> files; - std::string dirname = dirspec.GetPath(); - - files.push_back (dirname + "/" + symbol_filename); - files.push_back (dirname + "/.debug/" + symbol_filename); - files.push_back (dirname + "/.build-id/" + uuid_str); - - // Some debug files may stored in the module directory like this: - // /usr/lib/debug/usr/lib/library.so.debug - if (!file_dir.IsEmpty()) - files.push_back (dirname + file_dir.AsCString() + "/" + symbol_filename); - - const uint32_t num_files = files.size(); - for (size_t idx_file = 0; idx_file < num_files; ++idx_file) - { - const std::string &filename = files[idx_file]; - FileSpec file_spec (filename.c_str(), true); - - if (llvm::sys::fs::equivalent (file_spec.GetPath(), module_spec.GetFileSpec().GetPath())) - continue; - - if (file_spec.Exists()) - { - lldb_private::ModuleSpecList specs; - const size_t num_specs = ObjectFile::GetModuleSpecifications (file_spec, 0, 0, specs); - assert (num_specs <= 1 && "Symbol Vendor supports only a single architecture"); - if (num_specs == 1) - { - ModuleSpec mspec; - if (specs.GetModuleSpecAtIndex (0, mspec)) - { - if (mspec.GetUUID() == module_uuid) - return file_spec; - } - } - } + size_t num_directories = debug_file_search_paths.GetSize(); + for (size_t idx = 0; idx < num_directories; ++idx) { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); + dirspec.ResolvePath(); + if (!dirspec.Exists() || !dirspec.IsDirectory()) + continue; + + std::vector<std::string> files; + std::string dirname = dirspec.GetPath(); + + files.push_back(dirname + "/" + symbol_filename); + files.push_back(dirname + "/.debug/" + symbol_filename); + files.push_back(dirname + "/.build-id/" + uuid_str); + + // Some debug files may stored in the module directory like this: + // /usr/lib/debug/usr/lib/library.so.debug + if (!file_dir.IsEmpty()) + files.push_back(dirname + file_dir.AsCString() + "/" + symbol_filename); + + const uint32_t num_files = files.size(); + for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { + const std::string &filename = files[idx_file]; + FileSpec file_spec(filename.c_str(), true); + + if (llvm::sys::fs::equivalent(file_spec.GetPath(), + module_spec.GetFileSpec().GetPath())) + continue; + + if (file_spec.Exists()) { + lldb_private::ModuleSpecList specs; + const size_t num_specs = + ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); + assert(num_specs <= 1 && + "Symbol Vendor supports only a single architecture"); + if (num_specs == 1) { + ModuleSpec mspec; + if (specs.GetModuleSpecAtIndex(0, mspec)) { + if (mspec.GetUUID() == module_uuid) + return file_spec; } + } } + } } + } - return LocateExecutableSymbolFileDsym(module_spec); + return LocateExecutableSymbolFileDsym(module_spec); } -#if !defined (__APPLE__) +#if !defined(__APPLE__) -FileSpec -Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle, - const lldb_private::UUID *uuid, - const ArchSpec *arch) -{ - // FIXME - return FileSpec(); +FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle, + const lldb_private::UUID *uuid, + const ArchSpec *arch) { + // FIXME + return FileSpec(); } -bool -Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup) -{ - // Fill in the module_spec.GetFileSpec() for the object file and/or the - // module_spec.GetSymbolFileSpec() for the debug symbols file. - return false; +bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + bool force_lookup) { + // Fill in the module_spec.GetFileSpec() for the object file and/or the + // module_spec.GetSymbolFileSpec() for the debug symbols file. + return false; } #endif diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp index 07b0cdf..dd3cd89 100644 --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -24,262 +24,233 @@ using namespace lldb_private; namespace { const int kDomain = AF_INET; -const int kType = SOCK_STREAM; - +const int kType = SOCK_STREAM; } TCPSocket::TCPSocket(NativeSocket socket, bool should_close) - : Socket(socket, ProtocolTcp, should_close) -{ - -} + : Socket(socket, ProtocolTcp, should_close) {} TCPSocket::TCPSocket(bool child_processes_inherit, Error &error) - : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true) -{ -} - + : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, + child_processes_inherit, error), + true) {} // Return the port number that is being used by the socket. -uint16_t -TCPSocket::GetLocalPortNumber() const -{ - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; +uint16_t TCPSocket::GetLocalPortNumber() const { + if (m_socket != kInvalidSocketValue) { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength(); + if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort(); + } + return 0; } -std::string -TCPSocket::GetLocalIPAddress() const -{ - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); - } - return ""; +std::string TCPSocket::GetLocalIPAddress() const { + // We bound to port zero, so we need to figure out which port we actually + // bound to + if (m_socket != kInvalidSocketValue) { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength(); + if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress(); + } + return ""; } -uint16_t -TCPSocket::GetRemotePortNumber() const -{ - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; +uint16_t TCPSocket::GetRemotePortNumber() const { + if (m_socket != kInvalidSocketValue) { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength(); + if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort(); + } + return 0; } -std::string -TCPSocket::GetRemoteIPAddress () const -{ - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); - } - return ""; +std::string TCPSocket::GetRemoteIPAddress() const { + // We bound to port zero, so we need to figure out which port we actually + // bound to + if (m_socket != kInvalidSocketValue) { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength(); + if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress(); + } + return ""; } -Error -TCPSocket::Connect(llvm::StringRef name) -{ - if (m_socket == kInvalidSocketValue) - return Error("Invalid socket"); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); - if (log) - log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); - - Error error; - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) - return error; - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = kDomain; - sa.sin_port = htons (port); - - int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr); - - if (inet_pton_result <= 0) - { - struct hostent *host_entry = gethostbyname (host_str.c_str()); - if (host_entry) - host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); - inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) - { - if (inet_pton_result == -1) - SetLastError(error); - else - error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); - - return error; - } - } +Error TCPSocket::Connect(llvm::StringRef name) { + if (m_socket == kInvalidSocketValue) + return Error("Invalid socket"); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); - if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) - { - SetLastError (error); - return error; + Error error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + return error; + + struct sockaddr_in sa; + ::memset(&sa, 0, sizeof(sa)); + sa.sin_family = kDomain; + sa.sin_port = htons(port); + + int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); + + if (inet_pton_result <= 0) { + struct hostent *host_entry = gethostbyname(host_str.c_str()); + if (host_entry) + host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list); + inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); + if (inet_pton_result <= 0) { + if (inet_pton_result == -1) + SetLastError(error); + else + error.SetErrorStringWithFormat("invalid host string: '%s'", + host_str.c_str()); + + return error; } + } - // Keep our TCP packets coming without any delays. - SetOptionNoDelay(); - error.Clear(); + if (-1 == + ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) { + SetLastError(error); return error; + } + + // Keep our TCP packets coming without any delays. + SetOptionNoDelay(); + error.Clear(); + return error; } -Error -TCPSocket::Listen(llvm::StringRef name, int backlog) -{ - Error error; +Error TCPSocket::Listen(llvm::StringRef name, int backlog) { + Error error; - // enable local address reuse - SetOptionReuseAddress(); + // enable local address reuse + SetOptionReuseAddress(); - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data()); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data()); - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) - return error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + return error; - SocketAddress bind_addr; + SocketAddress bind_addr; - // Only bind to the loopback address if we are expecting a connection from - // localhost to avoid any firewall issues. - const bool bind_addr_success = (host_str == "127.0.0.1") ? - bind_addr.SetToLocalhost (kDomain, port) : - bind_addr.SetToAnyAddress (kDomain, port); + // Only bind to the loopback address if we are expecting a connection from + // localhost to avoid any firewall issues. + const bool bind_addr_success = (host_str == "127.0.0.1") + ? bind_addr.SetToLocalhost(kDomain, port) + : bind_addr.SetToAnyAddress(kDomain, port); - if (!bind_addr_success) - { - error.SetErrorString("Failed to bind port"); - return error; - } + if (!bind_addr_success) { + error.SetErrorString("Failed to bind port"); + return error; + } - int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength()); - if (err != -1) - err = ::listen (GetNativeSocket(), backlog); + int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength()); + if (err != -1) + err = ::listen(GetNativeSocket(), backlog); - if (err == -1) - SetLastError (error); + if (err == -1) + SetLastError(error); - return error; + return error; } -Error -TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) -{ - Error error; - std::string host_str; - std::string port_str; - int32_t port; - if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) - return error; - - const sa_family_t family = kDomain; - const int socktype = kType; - const int protocol = IPPROTO_TCP; - SocketAddress listen_addr; - if (host_str.empty()) - listen_addr.SetToLocalhost(family, port); - else if (host_str.compare("*") == 0) - listen_addr.SetToAnyAddress(family, port); - else - { - if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol)) - { - error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str()); - return error; - } +Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&conn_socket) { + Error error; + std::string host_str; + std::string port_str; + int32_t port; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + return error; + + const sa_family_t family = kDomain; + const int socktype = kType; + const int protocol = IPPROTO_TCP; + SocketAddress listen_addr; + if (host_str.empty()) + listen_addr.SetToLocalhost(family, port); + else if (host_str.compare("*") == 0) + listen_addr.SetToAnyAddress(family, port); + else { + if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, + socktype, protocol)) { + error.SetErrorStringWithFormat("unable to resolve hostname '%s'", + host_str.c_str()); + return error; } + } - bool accept_connection = false; - std::unique_ptr<TCPSocket> accepted_socket; + bool accept_connection = false; + std::unique_ptr<TCPSocket> accepted_socket; - // Loop until we are happy with our connection - while (!accept_connection) - { - struct sockaddr_in accept_addr; - ::memset (&accept_addr, 0, sizeof accept_addr); -#if !(defined (__linux__) || defined(_WIN32)) - accept_addr.sin_len = sizeof accept_addr; + // Loop until we are happy with our connection + while (!accept_connection) { + struct sockaddr_in accept_addr; + ::memset(&accept_addr, 0, sizeof accept_addr); +#if !(defined(__linux__) || defined(_WIN32)) + accept_addr.sin_len = sizeof accept_addr; #endif - socklen_t accept_addr_len = sizeof accept_addr; + socklen_t accept_addr_len = sizeof accept_addr; - int sock = AcceptSocket (GetNativeSocket(), - (struct sockaddr *)&accept_addr, - &accept_addr_len, - child_processes_inherit, - error); + int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr, + &accept_addr_len, child_processes_inherit, error); - if (error.Fail()) - break; + if (error.Fail()) + break; - bool is_same_addr = true; + bool is_same_addr = true; #if !(defined(__linux__) || (defined(_WIN32))) - is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); + is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); #endif - if (is_same_addr) - is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr); - - if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) - { - accept_connection = true; - accepted_socket.reset(new TCPSocket(sock, true)); - } - else - { - const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; - ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - accepted_socket.reset(); - } + if (is_same_addr) + is_same_addr = (accept_addr.sin_addr.s_addr == + listen_addr.sockaddr_in().sin_addr.s_addr); + + if (is_same_addr || + (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) { + accept_connection = true; + accepted_socket.reset(new TCPSocket(sock, true)); + } else { + const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; + const uint8_t *listen_ip = + (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; + ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u " + "(expecting %u.%u.%u.%u)\n", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + accepted_socket.reset(); } + } - if (!accepted_socket) - return error; - - // Keep our TCP packets coming without any delays. - accepted_socket->SetOptionNoDelay(); - error.Clear(); - conn_socket = accepted_socket.release(); + if (!accepted_socket) return error; + + // Keep our TCP packets coming without any delays. + accepted_socket->SetOptionNoDelay(); + error.Clear(); + conn_socket = accepted_socket.release(); + return error; } -int -TCPSocket::SetOptionNoDelay() -{ - return SetOption (IPPROTO_TCP, TCP_NODELAY, 1); +int TCPSocket::SetOptionNoDelay() { + return SetOption(IPPROTO_TCP, TCP_NODELAY, 1); } -int -TCPSocket::SetOptionReuseAddress() -{ - return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); +int TCPSocket::SetOptionReuseAddress() { + return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); } diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index c59766a..022b3fa 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -19,120 +19,91 @@ #include <termios.h> #endif - using namespace lldb_private; -bool -Terminal::IsATerminal () const -{ - - return m_fd >= 0 && ::isatty (m_fd); -} - +bool Terminal::IsATerminal() const { return m_fd >= 0 && ::isatty(m_fd); } -bool -Terminal::SetEcho (bool enabled) -{ - if (FileDescriptorIsValid()) - { +bool Terminal::SetEcho(bool enabled) { + if (FileDescriptorIsValid()) { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (IsATerminal ()) - { - struct termios fd_termios; - if (::tcgetattr(m_fd, &fd_termios) == 0) - { - bool set_corectly = false; - if (enabled) - { - if (fd_termios.c_lflag & ECHO) - set_corectly = true; - else - fd_termios.c_lflag |= ECHO; - } - else - { - if (fd_termios.c_lflag & ECHO) - fd_termios.c_lflag &= ~ECHO; - else - set_corectly = true; - } - - if (set_corectly) - return true; - return ::tcsetattr (m_fd, TCSANOW, &fd_termios) == 0; - } + if (IsATerminal()) { + struct termios fd_termios; + if (::tcgetattr(m_fd, &fd_termios) == 0) { + bool set_corectly = false; + if (enabled) { + if (fd_termios.c_lflag & ECHO) + set_corectly = true; + else + fd_termios.c_lflag |= ECHO; + } else { + if (fd_termios.c_lflag & ECHO) + fd_termios.c_lflag &= ~ECHO; + else + set_corectly = true; } -#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED + + if (set_corectly) + return true; + return ::tcsetattr(m_fd, TCSANOW, &fd_termios) == 0; + } } - return false; +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED + } + return false; } -bool -Terminal::SetCanonical (bool enabled) -{ - if (FileDescriptorIsValid()) - { +bool Terminal::SetCanonical(bool enabled) { + if (FileDescriptorIsValid()) { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (IsATerminal ()) - { - struct termios fd_termios; - if (::tcgetattr(m_fd, &fd_termios) == 0) - { - bool set_corectly = false; - if (enabled) - { - if (fd_termios.c_lflag & ICANON) - set_corectly = true; - else - fd_termios.c_lflag |= ICANON; - } - else - { - if (fd_termios.c_lflag & ICANON) - fd_termios.c_lflag &= ~ICANON; - else - set_corectly = true; - } - - if (set_corectly) - return true; - return ::tcsetattr (m_fd, TCSANOW, &fd_termios) == 0; - } + if (IsATerminal()) { + struct termios fd_termios; + if (::tcgetattr(m_fd, &fd_termios) == 0) { + bool set_corectly = false; + if (enabled) { + if (fd_termios.c_lflag & ICANON) + set_corectly = true; + else + fd_termios.c_lflag |= ICANON; + } else { + if (fd_termios.c_lflag & ICANON) + fd_termios.c_lflag &= ~ICANON; + else + set_corectly = true; } -#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED + + if (set_corectly) + return true; + return ::tcsetattr(m_fd, TCSANOW, &fd_termios) == 0; + } } - return false; +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED + } + return false; } //---------------------------------------------------------------------- // Default constructor //---------------------------------------------------------------------- -TerminalState::TerminalState() : - m_tty(), - m_tflags(-1), +TerminalState::TerminalState() + : m_tty(), m_tflags(-1), #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap(), + m_termios_ap(), #endif - m_process_group(-1) -{ + m_process_group(-1) { } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -TerminalState::~TerminalState() -{ -} +TerminalState::~TerminalState() {} -void -TerminalState::Clear () -{ - m_tty.Clear(); - m_tflags = -1; +void TerminalState::Clear() { + m_tty.Clear(); + m_tflags = -1; #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap.reset(); + m_termios_ap.reset(); #endif - m_process_group = -1; + m_process_group = -1; } //---------------------------------------------------------------------- @@ -140,142 +111,114 @@ TerminalState::Clear () // 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); - if (m_tty.IsATerminal()) - { +bool TerminalState::Save(int fd, bool save_process_group) { + m_tty.SetFileDescriptor(fd); + if (m_tty.IsATerminal()) { #ifndef LLDB_DISABLE_POSIX - m_tflags = ::fcntl (fd, F_GETFL, 0); + m_tflags = ::fcntl(fd, F_GETFL, 0); #endif #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (m_termios_ap.get() == NULL) - m_termios_ap.reset (new struct termios); - int err = ::tcgetattr (fd, m_termios_ap.get()); - if (err != 0) - m_termios_ap.reset(); + if (m_termios_ap.get() == NULL) + m_termios_ap.reset(new struct termios); + int err = ::tcgetattr(fd, m_termios_ap.get()); + if (err != 0) + m_termios_ap.reset(); #endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED #ifndef LLDB_DISABLE_POSIX - if (save_process_group) - m_process_group = ::tcgetpgrp (0); - else - m_process_group = -1; -#endif - } + if (save_process_group) + m_process_group = ::tcgetpgrp(0); else - { - m_tty.Clear(); - m_tflags = -1; + m_process_group = -1; +#endif + } else { + m_tty.Clear(); + m_tflags = -1; #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap.reset(); + m_termios_ap.reset(); #endif - m_process_group = -1; - } - return IsValid(); + m_process_group = -1; + } + return IsValid(); } //---------------------------------------------------------------------- // Restore the state of the TTY using the cached values from a // previous call to Save(). //---------------------------------------------------------------------- -bool -TerminalState::Restore () const -{ +bool TerminalState::Restore() const { #ifndef LLDB_DISABLE_POSIX - if (IsValid()) - { - const int fd = m_tty.GetFileDescriptor(); - if (TFlagsIsValid()) - fcntl (fd, F_SETFL, m_tflags); + if (IsValid()) { + const int fd = m_tty.GetFileDescriptor(); + if (TFlagsIsValid()) + fcntl(fd, F_SETFL, m_tflags); #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (TTYStateIsValid()) - tcsetattr (fd, TCSANOW, m_termios_ap.get()); + if (TTYStateIsValid()) + tcsetattr(fd, TCSANOW, m_termios_ap.get()); #endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (ProcessGroupIsValid()) - { - // Save the original signal handler. - void (*saved_sigttou_callback) (int) = NULL; - saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN); - // Set the process group - tcsetpgrp (fd, m_process_group); - // Restore the original signal handler. - signal (SIGTTOU, saved_sigttou_callback); - } - return true; + if (ProcessGroupIsValid()) { + // Save the original signal handler. + void (*saved_sigttou_callback)(int) = NULL; + saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); + // Set the process group + tcsetpgrp(fd, m_process_group); + // Restore the original signal handler. + signal(SIGTTOU, saved_sigttou_callback); } + return true; + } #endif - return false; + return false; } - - - //---------------------------------------------------------------------- // 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 () && (TFlagsIsValid() || TTYStateIsValid()); +bool TerminalState::IsValid() const { + return m_tty.FileDescriptorIsValid() && + (TFlagsIsValid() || TTYStateIsValid()); } //---------------------------------------------------------------------- // Returns true if m_tflags is valid //---------------------------------------------------------------------- -bool -TerminalState::TFlagsIsValid() const -{ - return m_tflags != -1; -} +bool TerminalState::TFlagsIsValid() const { return m_tflags != -1; } //---------------------------------------------------------------------- // Returns true if m_ttystate is valid //---------------------------------------------------------------------- -bool -TerminalState::TTYStateIsValid() const -{ +bool TerminalState::TTYStateIsValid() const { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - return m_termios_ap.get() != 0; + return m_termios_ap.get() != 0; #else - return false; + return false; #endif } //---------------------------------------------------------------------- // Returns true if m_process_group is valid //---------------------------------------------------------------------- -bool -TerminalState::ProcessGroupIsValid() const -{ - return static_cast<int32_t>(m_process_group) != -1; +bool TerminalState::ProcessGroupIsValid() const { + return static_cast<int32_t>(m_process_group) != -1; } //------------------------------------------------------------------ // Constructor //------------------------------------------------------------------ -TerminalStateSwitcher::TerminalStateSwitcher () : - m_currentState(UINT32_MAX) -{ -} +TerminalStateSwitcher::TerminalStateSwitcher() : m_currentState(UINT32_MAX) {} //------------------------------------------------------------------ // Destructor //------------------------------------------------------------------ -TerminalStateSwitcher::~TerminalStateSwitcher () -{ -} +TerminalStateSwitcher::~TerminalStateSwitcher() {} //------------------------------------------------------------------ // Returns the number of states that this switcher contains //------------------------------------------------------------------ -uint32_t -TerminalStateSwitcher::GetNumberOfStates() const -{ - return llvm::array_lengthof(m_ttystates); +uint32_t TerminalStateSwitcher::GetNumberOfStates() const { + return llvm::array_lengthof(m_ttystates); } //------------------------------------------------------------------ @@ -283,28 +226,26 @@ TerminalStateSwitcher::GetNumberOfStates() const // // Returns true if the restore was successful, false otherwise. //------------------------------------------------------------------ -bool -TerminalStateSwitcher::Restore (uint32_t idx) const -{ - const uint32_t num_states = GetNumberOfStates(); - if (idx >= num_states) - return false; - - // See if we already are in this state? - if (m_currentState < num_states && (idx == m_currentState) && 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. - if (m_ttystates[idx].Restore()) - { - m_currentState = idx; - return true; - } - - // We failed to set the state. The tty state was invalid or not - // initialized. +bool TerminalStateSwitcher::Restore(uint32_t idx) const { + const uint32_t num_states = GetNumberOfStates(); + if (idx >= num_states) return false; + + // See if we already are in this state? + if (m_currentState < num_states && (idx == m_currentState) && + 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. + if (m_ttystates[idx].Restore()) { + m_currentState = idx; + return true; + } + + // We failed to set the state. The tty state was invalid or not + // initialized. + return false; } //------------------------------------------------------------------ @@ -313,13 +254,10 @@ TerminalStateSwitcher::Restore (uint32_t idx) const // // Returns true if the restore was successful, false otherwise. //------------------------------------------------------------------ -bool -TerminalStateSwitcher::Save (uint32_t idx, int fd, bool save_process_group) -{ - const uint32_t num_states = GetNumberOfStates(); - if (idx < num_states) - return m_ttystates[idx].Save(fd, save_process_group); - return false; +bool TerminalStateSwitcher::Save(uint32_t idx, int fd, + bool save_process_group) { + const uint32_t num_states = GetNumberOfStates(); + if (idx < num_states) + return m_ttystates[idx].Save(fd, save_process_group); + return false; } - - diff --git a/lldb/source/Host/common/ThisThread.cpp b/lldb/source/Host/common/ThisThread.cpp index 7637014..2fea0a1 100644 --- a/lldb/source/Host/common/ThisThread.cpp +++ b/lldb/source/Host/common/ThisThread.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/ThisThread.h" #include "lldb/Core/Error.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/ThisThread.h" #include "llvm/ADT/STLExtras.h" @@ -18,35 +18,33 @@ using namespace lldb; using namespace lldb_private; -void -ThisThread::SetName(llvm::StringRef name, int max_length) -{ - std::string truncated_name(name.data()); - - // Thread names are coming in like '<lldb.comm.debugger.edit>' and - // '<lldb.comm.debugger.editline>'. So just chopping the end of the string - // off leads to a lot of similar named threads. Go through the thread name - // and search for the last dot and use that. - - if (max_length > 0 && truncated_name.length() > static_cast<size_t>(max_length)) - { - // First see if we can get lucky by removing any initial or final braces. - std::string::size_type begin = truncated_name.find_first_not_of("(<"); - std::string::size_type end = truncated_name.find_last_not_of(")>."); - if (end - begin > static_cast<size_t>(max_length)) - { - // We're still too long. Since this is a dotted component, use everything after the last - // dot, up to a maximum of |length| characters. - std::string::size_type last_dot = truncated_name.rfind('.'); - if (last_dot != std::string::npos) - begin = last_dot + 1; - - end = std::min(end, begin + max_length); - } - - std::string::size_type count = end - begin + 1; - truncated_name = truncated_name.substr(begin, count); +void ThisThread::SetName(llvm::StringRef name, int max_length) { + std::string truncated_name(name.data()); + + // Thread names are coming in like '<lldb.comm.debugger.edit>' and + // '<lldb.comm.debugger.editline>'. So just chopping the end of the string + // off leads to a lot of similar named threads. Go through the thread name + // and search for the last dot and use that. + + if (max_length > 0 && + truncated_name.length() > static_cast<size_t>(max_length)) { + // First see if we can get lucky by removing any initial or final braces. + std::string::size_type begin = truncated_name.find_first_not_of("(<"); + std::string::size_type end = truncated_name.find_last_not_of(")>."); + if (end - begin > static_cast<size_t>(max_length)) { + // We're still too long. Since this is a dotted component, use everything + // after the last + // dot, up to a maximum of |length| characters. + std::string::size_type last_dot = truncated_name.rfind('.'); + if (last_dot != std::string::npos) + begin = last_dot + 1; + + end = std::min(end, begin + max_length); } - SetName(truncated_name.c_str()); + std::string::size_type count = end - begin + 1; + truncated_name = truncated_name.substr(begin, count); + } + + SetName(truncated_name.c_str()); } diff --git a/lldb/source/Host/common/ThreadLauncher.cpp b/lldb/source/Host/common/ThreadLauncher.cpp index c19a233..b91c2fe 100644 --- a/lldb/source/Host/common/ThreadLauncher.cpp +++ b/lldb/source/Host/common/ThreadLauncher.cpp @@ -1,4 +1,5 @@ -//===-- ThreadLauncher.cpp ---------------------------------------*- C++ -*-===// +//===-- ThreadLauncher.cpp ---------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -8,11 +9,11 @@ //===----------------------------------------------------------------------===// // lldb Includes +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Core/Log.h" #include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThisThread.h" -#include "lldb/Host/ThreadLauncher.h" #if defined(_WIN32) #include "lldb/Host/windows/windows.h" @@ -21,64 +22,65 @@ using namespace lldb; using namespace lldb_private; -HostThread -ThreadLauncher::LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, lldb::thread_arg_t thread_arg, Error *error_ptr, size_t min_stack_byte_size) -{ - Error error; - if (error_ptr) - error_ptr->Clear(); +HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, + lldb::thread_func_t thread_function, + lldb::thread_arg_t thread_arg, + Error *error_ptr, + size_t min_stack_byte_size) { + Error error; + if (error_ptr) + error_ptr->Clear(); - // Host::ThreadCreateTrampoline will delete this pointer for us. - HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo(name.data(), thread_function, thread_arg); - lldb::thread_t thread; + // Host::ThreadCreateTrampoline will delete this pointer for us. + HostThreadCreateInfo *info_ptr = + new HostThreadCreateInfo(name.data(), thread_function, thread_arg); + lldb::thread_t thread; #ifdef _WIN32 - thread = - (lldb::thread_t)::_beginthreadex(0, (unsigned)min_stack_byte_size, HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); - if (thread == (lldb::thread_t)(-1L)) - error.SetError(::GetLastError(), eErrorTypeWin32); + thread = (lldb::thread_t)::_beginthreadex( + 0, (unsigned)min_stack_byte_size, + HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); + if (thread == (lldb::thread_t)(-1L)) + error.SetError(::GetLastError(), eErrorTypeWin32); #else - - // ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. +// ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. #if __has_feature(address_sanitizer) - const size_t eight_megabytes = 8 * 1024 * 1024; - if (min_stack_byte_size < eight_megabytes) - { - min_stack_byte_size += eight_megabytes; - } + const size_t eight_megabytes = 8 * 1024 * 1024; + if (min_stack_byte_size < eight_megabytes) { + min_stack_byte_size += eight_megabytes; + } #endif - pthread_attr_t *thread_attr_ptr = NULL; - pthread_attr_t thread_attr; - bool destroy_attr = false; - if (min_stack_byte_size > 0) - { - if (::pthread_attr_init (&thread_attr) == 0) - { - destroy_attr = true; - size_t default_min_stack_byte_size = 0; - if (::pthread_attr_getstacksize(&thread_attr, &default_min_stack_byte_size) == 0) - { - if (default_min_stack_byte_size < min_stack_byte_size) - { - if (::pthread_attr_setstacksize (&thread_attr, min_stack_byte_size) == 0) - thread_attr_ptr = &thread_attr; - } - } - + pthread_attr_t *thread_attr_ptr = NULL; + pthread_attr_t thread_attr; + bool destroy_attr = false; + if (min_stack_byte_size > 0) { + if (::pthread_attr_init(&thread_attr) == 0) { + destroy_attr = true; + size_t default_min_stack_byte_size = 0; + if (::pthread_attr_getstacksize(&thread_attr, + &default_min_stack_byte_size) == 0) { + if (default_min_stack_byte_size < min_stack_byte_size) { + if (::pthread_attr_setstacksize(&thread_attr, min_stack_byte_size) == + 0) + thread_attr_ptr = &thread_attr; } + } } - int err = ::pthread_create(&thread, thread_attr_ptr, HostNativeThread::ThreadCreateTrampoline, info_ptr); + } + int err = + ::pthread_create(&thread, thread_attr_ptr, + HostNativeThread::ThreadCreateTrampoline, info_ptr); - if (destroy_attr) - ::pthread_attr_destroy(&thread_attr); + if (destroy_attr) + ::pthread_attr_destroy(&thread_attr); - error.SetError(err, eErrorTypePOSIX); + error.SetError(err, eErrorTypePOSIX); #endif - if (error_ptr) - *error_ptr = error; - if (!error.Success()) - thread = LLDB_INVALID_HOST_THREAD; + if (error_ptr) + *error_ptr = error; + if (!error.Success()) + thread = LLDB_INVALID_HOST_THREAD; - return HostThread(thread); + return HostThread(thread); } diff --git a/lldb/source/Host/common/TimeValue.cpp b/lldb/source/Host/common/TimeValue.cpp index db74527..bfbe41a5 100644 --- a/lldb/source/Host/common/TimeValue.cpp +++ b/lldb/source/Host/common/TimeValue.cpp @@ -11,9 +11,9 @@ #include "lldb/Host/Config.h" // C Includes +#include <cstring> #include <stddef.h> #include <time.h> -#include <cstring> #ifdef _MSC_VER #include "lldb/Host/windows/windows.h" @@ -26,108 +26,68 @@ // Project includes #include "lldb/Core/Stream.h" - using namespace lldb_private; //---------------------------------------------------------------------- // TimeValue constructor //---------------------------------------------------------------------- -TimeValue::TimeValue() : - m_nano_seconds (0) -{ -} +TimeValue::TimeValue() : m_nano_seconds(0) {} //---------------------------------------------------------------------- // TimeValue copy constructor //---------------------------------------------------------------------- -TimeValue::TimeValue(const TimeValue& rhs) : - m_nano_seconds (rhs.m_nano_seconds) -{ -} +TimeValue::TimeValue(const TimeValue &rhs) + : m_nano_seconds(rhs.m_nano_seconds) {} -TimeValue::TimeValue(const struct timespec& ts) : - m_nano_seconds ((uint64_t) ts.tv_sec * NanoSecPerSec + ts.tv_nsec) -{ -} +TimeValue::TimeValue(const struct timespec &ts) + : m_nano_seconds((uint64_t)ts.tv_sec * NanoSecPerSec + ts.tv_nsec) {} -TimeValue::TimeValue(uint32_t seconds, uint64_t nanos) : - m_nano_seconds((uint64_t) seconds * NanoSecPerSec + nanos) -{ -} +TimeValue::TimeValue(uint32_t seconds, uint64_t nanos) + : m_nano_seconds((uint64_t)seconds * NanoSecPerSec + nanos) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -TimeValue::~TimeValue() -{ -} +TimeValue::~TimeValue() {} - -uint64_t -TimeValue::GetAsNanoSecondsSinceJan1_1970() const -{ - return m_nano_seconds; +uint64_t TimeValue::GetAsNanoSecondsSinceJan1_1970() const { + return m_nano_seconds; } -uint64_t -TimeValue::GetAsMicroSecondsSinceJan1_1970() const -{ - return m_nano_seconds / NanoSecPerMicroSec; +uint64_t TimeValue::GetAsMicroSecondsSinceJan1_1970() const { + return m_nano_seconds / NanoSecPerMicroSec; } -uint64_t -TimeValue::GetAsSecondsSinceJan1_1970() const -{ - return m_nano_seconds / NanoSecPerSec; +uint64_t TimeValue::GetAsSecondsSinceJan1_1970() const { + return m_nano_seconds / NanoSecPerSec; } - - -struct timespec -TimeValue::GetAsTimeSpec () const -{ - struct timespec ts; - ts.tv_sec = m_nano_seconds / NanoSecPerSec; - ts.tv_nsec = m_nano_seconds % NanoSecPerSec; - return ts; +struct timespec TimeValue::GetAsTimeSpec() const { + struct timespec ts; + ts.tv_sec = m_nano_seconds / NanoSecPerSec; + ts.tv_nsec = m_nano_seconds % NanoSecPerSec; + return ts; } -void -TimeValue::Clear () -{ - m_nano_seconds = 0; -} +void TimeValue::Clear() { m_nano_seconds = 0; } -bool -TimeValue::IsValid () const -{ - return m_nano_seconds != 0; -} +bool TimeValue::IsValid() const { return m_nano_seconds != 0; } -void -TimeValue::OffsetWithSeconds (uint64_t sec) -{ - m_nano_seconds += sec * NanoSecPerSec; +void TimeValue::OffsetWithSeconds(uint64_t sec) { + m_nano_seconds += sec * NanoSecPerSec; } -void -TimeValue::OffsetWithMicroSeconds (uint64_t usec) -{ - m_nano_seconds += usec * NanoSecPerMicroSec; +void TimeValue::OffsetWithMicroSeconds(uint64_t usec) { + m_nano_seconds += usec * NanoSecPerMicroSec; } -void -TimeValue::OffsetWithNanoSeconds (uint64_t nsec) -{ - m_nano_seconds += nsec; -} +void TimeValue::OffsetWithNanoSeconds(uint64_t nsec) { m_nano_seconds += nsec; } -TimeValue -TimeValue::Now() -{ +TimeValue TimeValue::Now() { using namespace std::chrono; auto now = system_clock::now(); - auto ns_since_epoch = duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count(); + auto ns_since_epoch = + duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count(); return TimeValue(0, ns_since_epoch); } @@ -135,78 +95,63 @@ TimeValue::Now() //---------------------------------------------------------------------- // TimeValue assignment operator //---------------------------------------------------------------------- -const TimeValue& -TimeValue::operator=(const TimeValue& rhs) -{ - m_nano_seconds = rhs.m_nano_seconds; - return *this; +const TimeValue &TimeValue::operator=(const TimeValue &rhs) { + m_nano_seconds = rhs.m_nano_seconds; + return *this; } -void -TimeValue::Dump (Stream *s, uint32_t width) const -{ - if (s == NULL) - return; +void TimeValue::Dump(Stream *s, uint32_t width) const { + if (s == NULL) + return; #ifndef LLDB_DISABLE_POSIX - char time_buf[32]; - time_t time = GetAsSecondsSinceJan1_1970(); - char *time_cstr = ::ctime_r(&time, time_buf); - if (time_cstr) - { - char *newline = ::strpbrk(time_cstr, "\n\r"); - if (newline) - *newline = '\0'; - if (width > 0) - s->Printf("%-*s", width, time_cstr); - else - s->PutCString(time_cstr); - } - else if (width > 0) - s->Printf("%-*s", width, ""); + char time_buf[32]; + time_t time = GetAsSecondsSinceJan1_1970(); + char *time_cstr = ::ctime_r(&time, time_buf); + if (time_cstr) { + char *newline = ::strpbrk(time_cstr, "\n\r"); + if (newline) + *newline = '\0'; + if (width > 0) + s->Printf("%-*s", width, time_cstr); + else + s->PutCString(time_cstr); + } else if (width > 0) + s->Printf("%-*s", width, ""); #endif } -bool -lldb_private::operator == (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() == rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator==(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() == + rhs.GetAsNanoSecondsSinceJan1_1970(); } -bool -lldb_private::operator != (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() != rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator!=(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() != + rhs.GetAsNanoSecondsSinceJan1_1970(); } -bool -lldb_private::operator < (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() < rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator<(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() < + rhs.GetAsNanoSecondsSinceJan1_1970(); } -bool -lldb_private::operator <= (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() <= rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator<=(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() <= + rhs.GetAsNanoSecondsSinceJan1_1970(); } -bool -lldb_private::operator > (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() > rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator>(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() > + rhs.GetAsNanoSecondsSinceJan1_1970(); } -bool -lldb_private::operator >= (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() >= rhs.GetAsNanoSecondsSinceJan1_1970(); +bool lldb_private::operator>=(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() >= + rhs.GetAsNanoSecondsSinceJan1_1970(); } -uint64_t -lldb_private::operator - (const TimeValue &lhs, const TimeValue &rhs) -{ - return lhs.GetAsNanoSecondsSinceJan1_1970() - rhs.GetAsNanoSecondsSinceJan1_1970(); +uint64_t lldb_private::operator-(const TimeValue &lhs, const TimeValue &rhs) { + return lhs.GetAsNanoSecondsSinceJan1_1970() - + rhs.GetAsNanoSecondsSinceJan1_1970(); } - - diff --git a/lldb/source/Host/common/UDPSocket.cpp b/lldb/source/Host/common/UDPSocket.cpp index 9a2028e..7cb1b37 100644 --- a/lldb/source/Host/common/UDPSocket.cpp +++ b/lldb/source/Host/common/UDPSocket.cpp @@ -25,134 +25,109 @@ using namespace lldb_private; namespace { const int kDomain = AF_INET; -const int kType = SOCK_DGRAM; +const int kType = SOCK_DGRAM; static const char *g_not_supported_error = "Not supported"; - } -UDPSocket::UDPSocket(NativeSocket socket) - : Socket(socket, ProtocolUdp, true) -{ -} +UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {} UDPSocket::UDPSocket(bool child_processes_inherit, Error &error) - : UDPSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) -{ -} + : UDPSocket( + CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} -size_t -UDPSocket::Send(const void *buf, const size_t num_bytes) -{ - return ::sendto (m_socket, - static_cast<const char*>(buf), - num_bytes, - 0, - m_send_sockaddr, - m_send_sockaddr.GetLength()); +size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { + return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0, + m_send_sockaddr, m_send_sockaddr.GetLength()); } -Error -UDPSocket::Connect(llvm::StringRef name) -{ - return Error("%s", g_not_supported_error); +Error UDPSocket::Connect(llvm::StringRef name) { + return Error("%s", g_not_supported_error); } -Error -UDPSocket::Listen(llvm::StringRef name, int backlog) -{ - return Error("%s", g_not_supported_error); +Error UDPSocket::Listen(llvm::StringRef name, int backlog) { + return Error("%s", g_not_supported_error); } -Error -UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - return Error("%s", g_not_supported_error); +Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { + return Error("%s", g_not_supported_error); } -Error -UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) -{ - std::unique_ptr<UDPSocket> final_send_socket; - std::unique_ptr<UDPSocket> final_recv_socket; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); - - Error error; - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) - return error; - - // Setup the receiving end of the UDP connection on this localhost - // on port zero. After we bind to port zero we can read the port. - final_recv_socket.reset(new UDPSocket(child_processes_inherit, error)); - if (error.Success()) - { - // Socket was created, now lets bind to the requested port - SocketAddress addr; - addr.SetToAnyAddress (AF_INET, 0); - - if (::bind (final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -1) - { - // Bind failed... - SetLastError (error); - } - } +Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, + Socket *&send_socket, Socket *&recv_socket) { + std::unique_ptr<UDPSocket> final_send_socket; + std::unique_ptr<UDPSocket> final_recv_socket; - assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); - if (error.Fail()) - return error; - - // At this point we have setup the receive port, now we need to - // setup the UDP send socket - - struct addrinfo hints; - struct addrinfo *service_info_list = nullptr; - - ::memset (&hints, 0, sizeof(hints)); - hints.ai_family = kDomain; - hints.ai_socktype = kType; - int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list); - if (err != 0) - { - error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", - host_str.c_str(), - port_str.c_str(), - err, - gai_strerror(err)); - return error; - } + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); - for (struct addrinfo *service_info_ptr = service_info_list; - service_info_ptr != nullptr; - service_info_ptr = service_info_ptr->ai_next) - { - auto send_fd = CreateSocket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, - child_processes_inherit, - error); - if (error.Success()) - { - final_send_socket.reset(new UDPSocket(send_fd)); - final_send_socket->m_send_sockaddr = service_info_ptr; - break; - } - else - continue; - } + Error error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + return error; - :: freeaddrinfo (service_info_list); + // Setup the receiving end of the UDP connection on this localhost + // on port zero. After we bind to port zero we can read the port. + final_recv_socket.reset(new UDPSocket(child_processes_inherit, error)); + if (error.Success()) { + // Socket was created, now lets bind to the requested port + SocketAddress addr; + addr.SetToAnyAddress(AF_INET, 0); + + if (::bind(final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == + -1) { + // Bind failed... + SetLastError(error); + } + } - if (!final_send_socket) - return error; + assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); + if (error.Fail()) + return error; - send_socket = final_send_socket.release(); - recv_socket = final_recv_socket.release(); - error.Clear(); + // 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; + + ::memset(&hints, 0, sizeof(hints)); + hints.ai_family = kDomain; + hints.ai_socktype = kType; + int err = ::getaddrinfo(host_str.c_str(), port_str.c_str(), &hints, + &service_info_list); + if (err != 0) { + error.SetErrorStringWithFormat( + "getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", + host_str.c_str(), port_str.c_str(), err, gai_strerror(err)); return error; + } + + for (struct addrinfo *service_info_ptr = service_info_list; + service_info_ptr != nullptr; + service_info_ptr = service_info_ptr->ai_next) { + auto send_fd = CreateSocket( + service_info_ptr->ai_family, service_info_ptr->ai_socktype, + service_info_ptr->ai_protocol, child_processes_inherit, error); + if (error.Success()) { + final_send_socket.reset(new UDPSocket(send_fd)); + final_send_socket->m_send_sockaddr = service_info_ptr; + break; + } else + continue; + } + + ::freeaddrinfo(service_info_list); + + if (!final_send_socket) + return error; + + send_socket = final_send_socket.release(); + recv_socket = final_recv_socket.release(); + error.Clear(); + return error; } diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp index dc9cb0b..39a0323 100644 --- a/lldb/source/Host/common/XML.cpp +++ b/lldb/source/Host/common/XML.cpp @@ -7,685 +7,527 @@ // //===----------------------------------------------------------------------===// -#include <stdlib.h> /* atof */ +#include <stdlib.h> /* atof */ -#include "lldb/Host/XML.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Host/XML.h" using namespace lldb; using namespace lldb_private; +#pragma mark-- XMLDocument -#pragma mark -- XMLDocument - -XMLDocument::XMLDocument () : - m_document (nullptr) -{ -} +XMLDocument::XMLDocument() : m_document(nullptr) {} -XMLDocument::~XMLDocument () -{ - Clear(); -} +XMLDocument::~XMLDocument() { Clear(); } -void -XMLDocument::Clear() -{ -#if defined( LIBXML2_DEFINED ) - if (m_document) - { - xmlDocPtr doc = m_document; - m_document = nullptr; - xmlFreeDoc(doc); - } +void XMLDocument::Clear() { +#if defined(LIBXML2_DEFINED) + if (m_document) { + xmlDocPtr doc = m_document; + m_document = nullptr; + xmlFreeDoc(doc); + } #endif } -bool -XMLDocument::IsValid() const -{ - return m_document != nullptr; -} +bool XMLDocument::IsValid() const { return m_document != nullptr; } -void -XMLDocument::ErrorCallback (void *ctx, const char *format, ...) -{ - XMLDocument *document = (XMLDocument *)ctx; - va_list args; - va_start (args, format); - document->m_errors.PrintfVarArg(format, args); - document->m_errors.EOL(); - va_end (args); +void XMLDocument::ErrorCallback(void *ctx, const char *format, ...) { + XMLDocument *document = (XMLDocument *)ctx; + va_list args; + va_start(args, format); + document->m_errors.PrintfVarArg(format, args); + document->m_errors.EOL(); + va_end(args); } -bool -XMLDocument::ParseFile (const char *path) -{ -#if defined( LIBXML2_DEFINED ) - Clear(); - xmlSetGenericErrorFunc( (void *)this, XMLDocument::ErrorCallback ); - m_document = xmlParseFile(path); - xmlSetGenericErrorFunc(nullptr, nullptr); +bool XMLDocument::ParseFile(const char *path) { +#if defined(LIBXML2_DEFINED) + Clear(); + xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback); + m_document = xmlParseFile(path); + xmlSetGenericErrorFunc(nullptr, nullptr); #endif - return IsValid(); + return IsValid(); } -bool -XMLDocument::ParseMemory (const char *xml, size_t xml_length, const char *url) -{ -#if defined( LIBXML2_DEFINED ) - Clear(); - xmlSetGenericErrorFunc( (void *)this, XMLDocument::ErrorCallback ); - m_document = xmlReadMemory(xml, (int)xml_length, url, nullptr, 0); - xmlSetGenericErrorFunc(nullptr, nullptr); +bool XMLDocument::ParseMemory(const char *xml, size_t xml_length, + const char *url) { +#if defined(LIBXML2_DEFINED) + Clear(); + xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback); + m_document = xmlReadMemory(xml, (int)xml_length, url, nullptr, 0); + xmlSetGenericErrorFunc(nullptr, nullptr); #endif - return IsValid(); - -} - -XMLNode -XMLDocument::GetRootElement(const char *required_name) -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - XMLNode root_node(xmlDocGetRootElement(m_document)); - if (required_name) - { - llvm::StringRef actual_name = root_node.GetName(); - if (actual_name == required_name) - return root_node; - } - else - { - return root_node; - } + return IsValid(); +} + +XMLNode XMLDocument::GetRootElement(const char *required_name) { +#if defined(LIBXML2_DEFINED) + if (IsValid()) { + XMLNode root_node(xmlDocGetRootElement(m_document)); + if (required_name) { + llvm::StringRef actual_name = root_node.GetName(); + if (actual_name == required_name) + return root_node; + } else { + return root_node; } + } #endif - return XMLNode(); + return XMLNode(); } -const std::string & -XMLDocument::GetErrors() const -{ - return m_errors.GetString(); +const std::string &XMLDocument::GetErrors() const { + return m_errors.GetString(); } -bool -XMLDocument::XMLEnabled () -{ -#if defined( LIBXML2_DEFINED ) - return true; +bool XMLDocument::XMLEnabled() { +#if defined(LIBXML2_DEFINED) + return true; #else - return false; + return false; #endif } -#pragma mark -- XMLNode +#pragma mark-- XMLNode -XMLNode::XMLNode() : - m_node(nullptr) -{ -} +XMLNode::XMLNode() : m_node(nullptr) {} -XMLNode::XMLNode(XMLNodeImpl node) : - m_node(node) -{ -} +XMLNode::XMLNode(XMLNodeImpl node) : m_node(node) {} -XMLNode::~XMLNode() -{ - -} +XMLNode::~XMLNode() {} -void -XMLNode::Clear() -{ - m_node = nullptr; -} +void XMLNode::Clear() { m_node = nullptr; } -XMLNode -XMLNode::GetParent() const -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - return XMLNode(m_node->parent); - else - return XMLNode(); -#else +XMLNode XMLNode::GetParent() const { +#if defined(LIBXML2_DEFINED) + if (IsValid()) + return XMLNode(m_node->parent); + else return XMLNode(); +#else + return XMLNode(); #endif - } -XMLNode -XMLNode::GetSibling() const -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - return XMLNode(m_node->next); - else - return XMLNode(); -#else +XMLNode XMLNode::GetSibling() const { +#if defined(LIBXML2_DEFINED) + if (IsValid()) + return XMLNode(m_node->next); + else return XMLNode(); +#else + return XMLNode(); #endif - } -XMLNode -XMLNode::GetChild () const -{ -#if defined( LIBXML2_DEFINED ) +XMLNode XMLNode::GetChild() const { +#if defined(LIBXML2_DEFINED) - if (IsValid()) - return XMLNode(m_node->children); - else - return XMLNode(); -#else + if (IsValid()) + return XMLNode(m_node->children); + else return XMLNode(); +#else + return XMLNode(); #endif - } -llvm::StringRef -XMLNode::GetAttributeValue(const char *name, const char *fail_value) const -{ - const char *attr_value = NULL; -#if defined( LIBXML2_DEFINED ) +llvm::StringRef XMLNode::GetAttributeValue(const char *name, + const char *fail_value) const { + const char *attr_value = NULL; +#if defined(LIBXML2_DEFINED) - if (IsValid()) - attr_value = (const char *)xmlGetProp(m_node, (const xmlChar *)name); - else - attr_value = fail_value; -#else + if (IsValid()) + attr_value = (const char *)xmlGetProp(m_node, (const xmlChar *)name); + else attr_value = fail_value; +#else + attr_value = fail_value; #endif - if (attr_value) - return llvm::StringRef(attr_value); - else - return llvm::StringRef(); + if (attr_value) + return llvm::StringRef(attr_value); + else + return llvm::StringRef(); } - - - -void -XMLNode::ForEachChildNode (NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - GetChild().ForEachSiblingNode(callback); +void XMLNode::ForEachChildNode(NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) + if (IsValid()) + GetChild().ForEachSiblingNode(callback); #endif } -void -XMLNode::ForEachChildElement (NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - XMLNode child = GetChild(); - if (child) - child.ForEachSiblingElement(callback); +void XMLNode::ForEachChildElement(NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) + XMLNode child = GetChild(); + if (child) + child.ForEachSiblingElement(callback); #endif } -void -XMLNode::ForEachChildElementWithName (const char *name, NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - XMLNode child = GetChild(); - if (child) - child.ForEachSiblingElementWithName(name, callback); +void XMLNode::ForEachChildElementWithName(const char *name, + NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) + XMLNode child = GetChild(); + if (child) + child.ForEachSiblingElementWithName(name, callback); #endif } -void -XMLNode::ForEachAttribute (AttributeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - for (xmlAttrPtr attr = m_node->properties; attr != nullptr; attr=attr->next) - { - // check if name matches - if (attr->name) - { - // check child is a text node - xmlNodePtr child = attr->children; - if (child->type == XML_TEXT_NODE) - { - llvm::StringRef attr_value; - if (child->content) - attr_value = llvm::StringRef((const char *)child->content); - if (callback(llvm::StringRef((const char *)attr->name), attr_value) == false) - return; - } - } +void XMLNode::ForEachAttribute(AttributeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) + + if (IsValid()) { + for (xmlAttrPtr attr = m_node->properties; attr != nullptr; + attr = attr->next) { + // check if name matches + if (attr->name) { + // check child is a text node + xmlNodePtr child = attr->children; + if (child->type == XML_TEXT_NODE) { + llvm::StringRef attr_value; + if (child->content) + attr_value = llvm::StringRef((const char *)child->content); + if (callback(llvm::StringRef((const char *)attr->name), attr_value) == + false) + return; } + } } + } #endif } +void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) -void -XMLNode::ForEachSiblingNode (NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - // iterate through all siblings - for (xmlNodePtr node = m_node; node; node=node->next) - { - if (callback(XMLNode(node)) == false) - return; - } + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + if (callback(XMLNode(node)) == false) + return; } + } #endif } -void -XMLNode::ForEachSiblingElement (NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - // iterate through all siblings - for (xmlNodePtr node = m_node; node; node=node->next) - { - // we are looking for element nodes only - if (node->type != XML_ELEMENT_NODE) - continue; - - if (callback(XMLNode(node)) == false) - return; - } - } -#endif -} +void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) -void -XMLNode::ForEachSiblingElementWithName (const char *name, NodeCallback const &callback) const -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - // iterate through all siblings - for (xmlNodePtr node = m_node; node; node=node->next) - { - // we are looking for element nodes only - 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) - { - if (strcmp((const char *)node->name, name) != 0) - continue; // Name mismatch, ignore this one - } - else - { - if (node->name) - continue; // nullptr name specified and this element has a name, ignore this one - } - - if (callback(XMLNode(node)) == false) - return; - } - } -#endif -} + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + // we are looking for element nodes only + if (node->type != XML_ELEMENT_NODE) + continue; -llvm::StringRef -XMLNode::GetName() const -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - if (m_node->name) - return llvm::StringRef((const char *)m_node->name); + if (callback(XMLNode(node)) == false) + return; } + } #endif - return llvm::StringRef(); } -bool -XMLNode::GetElementText (std::string &text) const -{ - text.clear(); -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - bool success = false; - if (m_node->type == XML_ELEMENT_NODE) - { - // check child is a text node - for (xmlNodePtr node = m_node->children; - node != nullptr; - node = node->next) - { - if (node->type == XML_TEXT_NODE) - { - text.append((const char *)node->content); - success = true; - } - } - } - return success; +void XMLNode::ForEachSiblingElementWithName( + const char *name, NodeCallback const &callback) const { +#if defined(LIBXML2_DEFINED) + + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + // we are looking for element nodes only + 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) { + if (strcmp((const char *)node->name, name) != 0) + continue; // Name mismatch, ignore this one + } else { + if (node->name) + continue; // nullptr name specified and this element has a name, + // ignore this one + } + + if (callback(XMLNode(node)) == false) + return; } + } #endif - return false; } - -bool -XMLNode::GetElementTextAsUnsigned (uint64_t &value, uint64_t fail_value, int base) const -{ - bool success = false; -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - std::string text; - if (GetElementText(text)) - value = StringConvert::ToUInt64(text.c_str(), fail_value, base, &success); - } +llvm::StringRef XMLNode::GetName() const { +#if defined(LIBXML2_DEFINED) + if (IsValid()) { + if (m_node->name) + return llvm::StringRef((const char *)m_node->name); + } #endif - if (!success) - value = fail_value; - return success; + return llvm::StringRef(); } -bool -XMLNode::GetElementTextAsFloat (double &value, double fail_value) const -{ +bool XMLNode::GetElementText(std::string &text) const { + text.clear(); +#if defined(LIBXML2_DEFINED) + if (IsValid()) { bool success = false; -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - std::string text; - if (GetElementText(text)) - { - value = atof(text.c_str()); - success = true; + if (m_node->type == XML_ELEMENT_NODE) { + // check child is a text node + for (xmlNodePtr node = m_node->children; node != nullptr; + node = node->next) { + if (node->type == XML_TEXT_NODE) { + text.append((const char *)node->content); + success = true; } + } } -#endif - if (!success) - value = fail_value; return success; + } +#endif + return false; +} + +bool XMLNode::GetElementTextAsUnsigned(uint64_t &value, uint64_t fail_value, + int base) const { + bool success = false; +#if defined(LIBXML2_DEFINED) + if (IsValid()) { + std::string text; + if (GetElementText(text)) + value = StringConvert::ToUInt64(text.c_str(), fail_value, base, &success); + } +#endif + if (!success) + value = fail_value; + return success; +} + +bool XMLNode::GetElementTextAsFloat(double &value, double fail_value) const { + bool success = false; +#if defined(LIBXML2_DEFINED) + if (IsValid()) { + std::string text; + if (GetElementText(text)) { + value = atof(text.c_str()); + success = true; + } + } +#endif + if (!success) + value = fail_value; + return success; } +bool XMLNode::NameIs(const char *name) const { +#if defined(LIBXML2_DEFINED) - -bool -XMLNode::NameIs (const char *name) const -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - // In case we are looking for a nullptr name or an exact pointer match - if (m_node->name == (const xmlChar *)name) - return true; - if (m_node->name) - return strcmp((const char *)m_node->name, name) == 0; - } + if (IsValid()) { + // In case we are looking for a nullptr name or an exact pointer match + if (m_node->name == (const xmlChar *)name) + return true; + if (m_node->name) + return strcmp((const char *)m_node->name, name) == 0; + } #endif - return false; + return false; } -XMLNode -XMLNode::FindFirstChildElementWithName (const char *name) const -{ - XMLNode result_node; +XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const { + XMLNode result_node; -#if defined( LIBXML2_DEFINED ) - ForEachChildElementWithName(name, [&result_node, name](const XMLNode& node) -> bool { +#if defined(LIBXML2_DEFINED) + ForEachChildElementWithName( + name, [&result_node, name](const XMLNode &node) -> bool { result_node = node; // Stop iterating, we found the node we wanted return false; - }); + }); #endif - return result_node; + return result_node; } -bool -XMLNode::IsValid() const -{ - return m_node != nullptr; -} +bool XMLNode::IsValid() const { return m_node != nullptr; } -bool -XMLNode::IsElement () const -{ -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - return m_node->type == XML_ELEMENT_NODE; +bool XMLNode::IsElement() const { +#if defined(LIBXML2_DEFINED) + if (IsValid()) + return m_node->type == XML_ELEMENT_NODE; #endif - return false; -} - - -XMLNode -XMLNode::GetElementForPath (const NamePath &path) -{ -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - if (path.empty()) - return *this; - else - { - XMLNode node = FindFirstChildElementWithName(path[0].c_str()); - const size_t n = path.size(); - for (size_t i=1; node && i<n; ++i) - node = node.FindFirstChildElementWithName(path[i].c_str()); - return node; - } + return false; +} + +XMLNode XMLNode::GetElementForPath(const NamePath &path) { +#if defined(LIBXML2_DEFINED) + + if (IsValid()) { + if (path.empty()) + return *this; + else { + XMLNode node = FindFirstChildElementWithName(path[0].c_str()); + const size_t n = path.size(); + for (size_t i = 1; node && i < n; ++i) + node = node.FindFirstChildElementWithName(path[i].c_str()); + return node; } + } #endif - return XMLNode(); + return XMLNode(); } +#pragma mark-- ApplePropertyList -#pragma mark -- ApplePropertyList +ApplePropertyList::ApplePropertyList() : m_xml_doc(), m_dict_node() {} -ApplePropertyList::ApplePropertyList() : - m_xml_doc(), - m_dict_node() -{ - +ApplePropertyList::ApplePropertyList(const char *path) + : m_xml_doc(), m_dict_node() { + ParseFile(path); } -ApplePropertyList::ApplePropertyList (const char *path) : - m_xml_doc(), - m_dict_node() -{ - ParseFile(path); -} - -ApplePropertyList::~ApplePropertyList() -{ -} +ApplePropertyList::~ApplePropertyList() {} -const std::string & -ApplePropertyList::GetErrors() const -{ - return m_xml_doc.GetErrors(); +const std::string &ApplePropertyList::GetErrors() const { + return m_xml_doc.GetErrors(); } - -bool -ApplePropertyList::ParseFile (const char *path) -{ - if (m_xml_doc.ParseFile(path)) - { - XMLNode plist = m_xml_doc.GetRootElement("plist"); - if (plist) - { - plist.ForEachChildElementWithName("dict", [this](const XMLNode &dict) -> bool { - this->m_dict_node = dict; - return false; // Stop iterating - }); - return (bool)m_dict_node; - } +bool ApplePropertyList::ParseFile(const char *path) { + if (m_xml_doc.ParseFile(path)) { + XMLNode plist = m_xml_doc.GetRootElement("plist"); + if (plist) { + plist.ForEachChildElementWithName("dict", + [this](const XMLNode &dict) -> bool { + this->m_dict_node = dict; + return false; // Stop iterating + }); + return (bool)m_dict_node; } - return false; -} - -bool -ApplePropertyList::IsValid() const -{ - return (bool)m_dict_node; -} - -bool -ApplePropertyList::GetValueAsString (const char *key, std::string &value) const -{ - XMLNode value_node = GetValueNode (key); - if (value_node) - return ApplePropertyList::ExtractStringFromValueNode(value_node, value); - return false; -} - -XMLNode -ApplePropertyList::GetValueNode (const char *key) const -{ - XMLNode value_node; -#if defined( LIBXML2_DEFINED ) - - if (IsValid()) - { - m_dict_node.ForEachChildElementWithName("key", [key, &value_node](const XMLNode &key_node) -> bool { - std::string key_name; - if (key_node.GetElementText(key_name)) - { - if (key_name.compare(key) == 0) - { - value_node = key_node.GetSibling(); - while (value_node && !value_node.IsElement()) - value_node = value_node.GetSibling(); - return false; // Stop iterating - } + } + return false; +} + +bool ApplePropertyList::IsValid() const { return (bool)m_dict_node; } + +bool ApplePropertyList::GetValueAsString(const char *key, + std::string &value) const { + XMLNode value_node = GetValueNode(key); + if (value_node) + return ApplePropertyList::ExtractStringFromValueNode(value_node, value); + return false; +} + +XMLNode ApplePropertyList::GetValueNode(const char *key) const { + XMLNode value_node; +#if defined(LIBXML2_DEFINED) + + if (IsValid()) { + m_dict_node.ForEachChildElementWithName( + "key", [key, &value_node](const XMLNode &key_node) -> bool { + std::string key_name; + if (key_node.GetElementText(key_name)) { + if (key_name.compare(key) == 0) { + value_node = key_node.GetSibling(); + while (value_node && !value_node.IsElement()) + value_node = value_node.GetSibling(); + return false; // Stop iterating } - return true; // Keep iterating + } + return true; // Keep iterating }); - } + } #endif - return value_node; -} - -bool -ApplePropertyList::ExtractStringFromValueNode (const XMLNode &node, std::string &value) -{ - value.clear(); -#if defined( LIBXML2_DEFINED ) - if (node.IsValid()) - { - llvm::StringRef element_name = node.GetName(); - if (element_name == "true" || element_name == "false") - { - // The text value _is_ the element name itself... - value = element_name.str(); - return true; - } - else if (element_name == "dict" || element_name == "array") - return false; // dictionaries and arrays have no text value, so we fail - else - return node.GetElementText(value); - } + return value_node; +} + +bool ApplePropertyList::ExtractStringFromValueNode(const XMLNode &node, + std::string &value) { + value.clear(); +#if defined(LIBXML2_DEFINED) + if (node.IsValid()) { + llvm::StringRef element_name = node.GetName(); + if (element_name == "true" || element_name == "false") { + // The text value _is_ the element name itself... + value = element_name.str(); + return true; + } else if (element_name == "dict" || element_name == "array") + return false; // dictionaries and arrays have no text value, so we fail + else + return node.GetElementText(value); + } #endif - return false; + return false; } -#if defined( LIBXML2_DEFINED ) +#if defined(LIBXML2_DEFINED) namespace { - StructuredData::ObjectSP - CreatePlistValue (XMLNode node) - { - llvm::StringRef element_name = node.GetName(); - if (element_name == "array") - { - std::shared_ptr<StructuredData::Array> array_sp(new StructuredData::Array()); - node.ForEachChildElement([&array_sp](const XMLNode &node) -> bool { - array_sp->AddItem(CreatePlistValue(node)); - return true; // Keep iterating through all child elements of the array - }); - return array_sp; - } - else if (element_name == "dict") - { - XMLNode key_node; - std::shared_ptr<StructuredData::Dictionary> dict_sp(new StructuredData::Dictionary()); - node.ForEachChildElement([&key_node, &dict_sp](const XMLNode &node) -> bool { - if (node.NameIs("key")) - { - // This is a "key" element node - key_node = node; - } - else - { - // This is a value node - if (key_node) - { - std::string key_name; - key_node.GetElementText(key_name); - dict_sp->AddItem(key_name, CreatePlistValue(node)); - key_node.Clear(); - } - } - return true; // Keep iterating through all child elements of the dictionary - }); - return dict_sp; - } - else if (element_name == "real") - { - double value = 0.0; - node.GetElementTextAsFloat(value); - return StructuredData::ObjectSP(new StructuredData::Float(value)); - } - else if (element_name == "integer") - { - uint64_t value = 0; - node.GetElementTextAsUnsigned(value, 0, 0); - return StructuredData::ObjectSP(new StructuredData::Integer(value)); - } - else if ((element_name == "string") || (element_name == "data") || (element_name == "date")) - { - std::string text; - node.GetElementText(text); - return StructuredData::ObjectSP(new StructuredData::String(std::move(text))); - } - else if (element_name == "true") - { - return StructuredData::ObjectSP(new StructuredData::Boolean(true)); - } - else if (element_name == "false") - { - return StructuredData::ObjectSP(new StructuredData::Boolean(false)); - } - return StructuredData::ObjectSP(new StructuredData::Null()); - } +StructuredData::ObjectSP CreatePlistValue(XMLNode node) { + llvm::StringRef element_name = node.GetName(); + if (element_name == "array") { + std::shared_ptr<StructuredData::Array> array_sp( + new StructuredData::Array()); + node.ForEachChildElement([&array_sp](const XMLNode &node) -> bool { + array_sp->AddItem(CreatePlistValue(node)); + return true; // Keep iterating through all child elements of the array + }); + return array_sp; + } else if (element_name == "dict") { + XMLNode key_node; + std::shared_ptr<StructuredData::Dictionary> dict_sp( + new StructuredData::Dictionary()); + node.ForEachChildElement( + [&key_node, &dict_sp](const XMLNode &node) -> bool { + if (node.NameIs("key")) { + // This is a "key" element node + key_node = node; + } else { + // This is a value node + if (key_node) { + std::string key_name; + key_node.GetElementText(key_name); + dict_sp->AddItem(key_name, CreatePlistValue(node)); + key_node.Clear(); + } + } + return true; // Keep iterating through all child elements of the + // dictionary + }); + return dict_sp; + } else if (element_name == "real") { + double value = 0.0; + node.GetElementTextAsFloat(value); + return StructuredData::ObjectSP(new StructuredData::Float(value)); + } else if (element_name == "integer") { + uint64_t value = 0; + node.GetElementTextAsUnsigned(value, 0, 0); + return StructuredData::ObjectSP(new StructuredData::Integer(value)); + } else if ((element_name == "string") || (element_name == "data") || + (element_name == "date")) { + std::string text; + node.GetElementText(text); + return StructuredData::ObjectSP( + new StructuredData::String(std::move(text))); + } else if (element_name == "true") { + return StructuredData::ObjectSP(new StructuredData::Boolean(true)); + } else if (element_name == "false") { + return StructuredData::ObjectSP(new StructuredData::Boolean(false)); + } + return StructuredData::ObjectSP(new StructuredData::Null()); +} } #endif -StructuredData::ObjectSP -ApplePropertyList::GetStructuredData() -{ - StructuredData::ObjectSP root_sp; -#if defined( LIBXML2_DEFINED ) - if (IsValid()) - { - return CreatePlistValue(m_dict_node); - } +StructuredData::ObjectSP ApplePropertyList::GetStructuredData() { + StructuredData::ObjectSP root_sp; +#if defined(LIBXML2_DEFINED) + if (IsValid()) { + return CreatePlistValue(m_dict_node); + } #endif - return root_sp; + return root_sp; } diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp index cf53cda..5b15762 100644 --- a/lldb/source/Host/freebsd/Host.cpp +++ b/lldb/source/Host/freebsd/Host.cpp @@ -1,4 +1,5 @@ -//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ -*-===// +//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -8,32 +9,32 @@ //===----------------------------------------------------------------------===// // C Includes -#include <stdio.h> #include <dlfcn.h> #include <execinfo.h> +#include <stdio.h> +#include <sys/proc.h> +#include <sys/sysctl.h> #include <sys/types.h> #include <sys/user.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#include <sys/ptrace.h> -#include <sys/exec.h> #include <machine/elf.h> +#include <sys/exec.h> +#include <sys/ptrace.h> // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" -#include "lldb/Host/Endian.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" +#include "lldb/Host/Endian.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" @@ -43,241 +44,220 @@ #include "llvm/Support/Host.h" extern "C" { - extern char **environ; +extern char **environ; } using namespace lldb; using namespace lldb_private; -size_t -Host::GetEnvironment (StringList &env) -{ - char *v; - char **var = environ; - for (; var != NULL && *var != NULL; ++var) - { - v = strchr(*var, (int)'-'); - if (v == NULL) - continue; - env.AppendString(v); - } - return env.GetSize(); +size_t Host::GetEnvironment(StringList &env) { + char *v; + char **var = environ; + for (; var != NULL && *var != NULL; ++var) { + v = strchr(*var, (int)'-'); + if (v == NULL) + continue; + env.AppendString(v); + } + return env.GetSize(); } static bool -GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, - ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; - - char arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) - { - DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); - lldb::offset_t offset = 0; - const char *cstr; - - cstr = data.GetCStr (&offset); - if (cstr) - { - process_info.GetExecutableFile().SetFile(cstr, false); - - if (!(match_info_ptr == NULL || - NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), - match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName()))) - return false; - - Args &proc_args = process_info.GetArguments(); - while (1) - { - const uint8_t *p = data.PeekData(offset, 1); - while ((p != NULL) && (*p == '\0') && offset < arg_data_size) - { - ++offset; - p = data.PeekData(offset, 1); - } - if (p == NULL || offset >= arg_data_size) - return true; - - cstr = data.GetCStr(&offset); - if (cstr) - proc_args.AppendArgument(cstr); - else - return true; - } - } +GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, + ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, + (int)process_info.GetProcessID()}; + + char arg_data[8192]; + size_t arg_data_size = sizeof(arg_data); + if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) { + DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(), + sizeof(void *)); + lldb::offset_t offset = 0; + const char *cstr; + + cstr = data.GetCStr(&offset); + if (cstr) { + process_info.GetExecutableFile().SetFile(cstr, false); + + if (!(match_info_ptr == NULL || + NameMatches( + process_info.GetExecutableFile().GetFilename().GetCString(), + match_info_ptr->GetNameMatchType(), + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) { + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { + ++offset; + p = data.PeekData(offset, 1); + } + if (p == NULL || offset >= arg_data_size) + return true; + + cstr = data.GetCStr(&offset); + if (cstr) + proc_args.AppendArgument(cstr); + else + return true; } + } } - return false; + } + return false; } -static bool -GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - return true; - } - process_info.GetArchitecture().Clear(); - return false; +static bool GetFreeBSDProcessCPUType(ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + process_info.GetArchitecture() = + HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + return true; + } + process_info.GetArchitecture().Clear(); + return false; } -static bool -GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) -{ - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size; - - if (process_info.ProcessIDIsValid()) - { - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, - (int)process_info.GetProcessID() }; - proc_kinfo_size = sizeof(struct kinfo_proc); - - if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) - { - if (proc_kinfo_size > 0) - { - process_info.SetParentProcessID (proc_kinfo.ki_ppid); - process_info.SetUserID (proc_kinfo.ki_ruid); - process_info.SetGroupID (proc_kinfo.ki_rgid); - process_info.SetEffectiveUserID (proc_kinfo.ki_uid); - if (proc_kinfo.ki_ngroups > 0) - process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); - else - process_info.SetEffectiveGroupID (UINT32_MAX); - return true; - } - } +static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { + struct kinfo_proc proc_kinfo; + size_t proc_kinfo_size; + + if (process_info.ProcessIDIsValid()) { + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, + (int)process_info.GetProcessID()}; + proc_kinfo_size = sizeof(struct kinfo_proc); + + if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { + if (proc_kinfo_size > 0) { + process_info.SetParentProcessID(proc_kinfo.ki_ppid); + process_info.SetUserID(proc_kinfo.ki_ruid); + process_info.SetGroupID(proc_kinfo.ki_rgid); + process_info.SetEffectiveUserID(proc_kinfo.ki_uid); + if (proc_kinfo.ki_ngroups > 0) + process_info.SetEffectiveGroupID(proc_kinfo.ki_groups[0]); + else + process_info.SetEffectiveGroupID(UINT32_MAX); + return true; + } } - process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); - process_info.SetUserID (UINT32_MAX); - process_info.SetGroupID (UINT32_MAX); - process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); - return false; + } + process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID); + process_info.SetUserID(UINT32_MAX); + process_info.SetGroupID(UINT32_MAX); + process_info.SetEffectiveUserID(UINT32_MAX); + process_info.SetEffectiveGroupID(UINT32_MAX); + return false; } -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - std::vector<struct kinfo_proc> kinfos; - - int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - - size_t pid_data_size = 0; - if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0) - return 0; - - // Add a few extra in case a few more show up - const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; - - kinfos.resize (estimated_pid_count); - pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); - - if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) - return 0; - - const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); - - bool all_users = match_info.GetMatchAllUsers(); - const ::pid_t our_pid = getpid(); - const uid_t our_uid = getuid(); - for (size_t i = 0; i < actual_pid_count; i++) - { - const struct kinfo_proc &kinfo = kinfos[i]; - const bool kinfo_user_matches = (all_users || - (kinfo.ki_ruid == our_uid) || - // Special case, if lldb is being run as root we can attach to anything. - (our_uid == 0) - ); - - if (kinfo_user_matches == false || // Make sure the user is acceptable - kinfo.ki_pid == our_pid || // Skip this process - kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) - kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... - kinfo.ki_flag & P_TRACED || // Being debugged? - kinfo.ki_flag & P_WEXIT) // Working on exiting - 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. - bool already_registered = false; - for (uint32_t pi = 0; - !already_registered && - (const int)kinfo.ki_numthreads > 1 && - pi < (const uint32_t)process_infos.GetSize(); pi++) - already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); - - if (already_registered) - continue; - - ProcessInstanceInfo process_info; - process_info.SetProcessID (kinfo.ki_pid); - process_info.SetParentProcessID (kinfo.ki_ppid); - process_info.SetUserID (kinfo.ki_ruid); - process_info.SetGroupID (kinfo.ki_rgid); - process_info.SetEffectiveUserID (kinfo.ki_svuid); - process_info.SetEffectiveGroupID (kinfo.ki_svgid); - - // Make sure our info matches before we go fetch the name and cpu type - if (match_info.Matches (process_info) && - GetFreeBSDProcessArgs (&match_info, process_info)) - { - GetFreeBSDProcessCPUType (process_info); - if (match_info.Matches (process_info)) - process_infos.Append (process_info); - } +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + std::vector<struct kinfo_proc> kinfos; + + int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + + size_t pid_data_size = 0; + if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0) + return 0; + + // Add a few extra in case a few more show up + const size_t estimated_pid_count = + (pid_data_size / sizeof(struct kinfo_proc)) + 10; + + kinfos.resize(estimated_pid_count); + pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); + + if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) + return 0; + + const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); + + bool all_users = match_info.GetMatchAllUsers(); + const ::pid_t our_pid = getpid(); + const uid_t our_uid = getuid(); + for (size_t i = 0; i < actual_pid_count; i++) { + const struct kinfo_proc &kinfo = kinfos[i]; + const bool kinfo_user_matches = (all_users || (kinfo.ki_ruid == our_uid) || + // Special case, if lldb is being run as + // root we can attach to anything. + (our_uid == 0)); + + if (kinfo_user_matches == false || // Make sure the user is acceptable + kinfo.ki_pid == our_pid || // Skip this process + kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) + kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... + kinfo.ki_flag & P_TRACED || // Being debugged? + kinfo.ki_flag & P_WEXIT) // Working on exiting + 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. + bool already_registered = false; + for (uint32_t pi = 0; + !already_registered && (const int)kinfo.ki_numthreads > 1 && + pi < (const uint32_t)process_infos.GetSize(); + pi++) + already_registered = + (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); + + if (already_registered) + continue; + + ProcessInstanceInfo process_info; + process_info.SetProcessID(kinfo.ki_pid); + process_info.SetParentProcessID(kinfo.ki_ppid); + process_info.SetUserID(kinfo.ki_ruid); + process_info.SetGroupID(kinfo.ki_rgid); + process_info.SetEffectiveUserID(kinfo.ki_svuid); + process_info.SetEffectiveGroupID(kinfo.ki_svgid); + + // Make sure our info matches before we go fetch the name and cpu type + if (match_info.Matches(process_info) && + GetFreeBSDProcessArgs(&match_info, process_info)) { + GetFreeBSDProcessCPUType(process_info); + if (match_info.Matches(process_info)) + process_infos.Append(process_info); } + } - return process_infos.GetSize(); + return process_infos.GetSize(); } -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.SetProcessID(pid); +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.SetProcessID(pid); - if (GetFreeBSDProcessArgs(NULL, process_info)) - { - // should use libprocstat instead of going right into sysctl? - GetFreeBSDProcessCPUType(process_info); - GetFreeBSDProcessUserAndGroup(process_info); - return true; - } + if (GetFreeBSDProcessArgs(NULL, process_info)) { + // should use libprocstat instead of going right into sysctl? + GetFreeBSDProcessCPUType(process_info); + GetFreeBSDProcessUserAndGroup(process_info); + return true; + } - process_info.Clear(); - return false; + process_info.Clear(); + return false; } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_AUXV, 0 }; - size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); - DataBufferSP buf_sp; +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, 0}; + size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); + DataBufferSP buf_sp; - std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(auxv_size, 0)); + std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(auxv_size, 0)); - mib[3] = process->GetID(); - if (::sysctl(mib, 4, buf_ap->GetBytes(), &auxv_size, NULL, 0) == 0) { - buf_sp.reset(buf_ap.release()); - } else { - perror("sysctl failed on auxv"); - } + mib[3] = process->GetID(); + if (::sysctl(mib, 4, buf_ap->GetBytes(), &auxv_size, NULL, 0) == 0) { + buf_sp.reset(buf_ap.release()); + } else { + perror("sysctl failed on auxv"); + } - return buf_sp; + return buf_sp; } -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - return Error("unimplemented"); +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + return Error("unimplemented"); } - diff --git a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp index d511093..fb9d866 100644 --- a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -11,81 +11,67 @@ #include <stdio.h> #include <string.h> -#include <sys/types.h> #include <sys/sysctl.h> +#include <sys/types.h> #include <sys/utsname.h> using namespace lldb_private; -uint32_t -HostInfoFreeBSD::GetMaxThreadNameLength() -{ - return 16; -} +uint32_t HostInfoFreeBSD::GetMaxThreadNameLength() { return 16; } -bool -HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) -{ - struct utsname un; +bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - if (uname(&un) < 0) - return false; + ::memset(&un, 0, sizeof(utsname)); + if (uname(&un) < 0) + return false; - int status = sscanf(un.release, "%u.%u", &major, &minor); - return status == 2; + int status = sscanf(un.release, "%u.%u", &major, &minor); + return status == 2; } -bool -HostInfoFreeBSD::GetOSBuildString(std::string &s) -{ - int mib[2] = {CTL_KERN, KERN_OSREV}; - char osrev_str[12]; - uint32_t osrev = 0; - size_t osrev_len = sizeof(osrev); - - if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) - { - ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev); - s.assign(osrev_str); - return true; - } +bool HostInfoFreeBSD::GetOSBuildString(std::string &s) { + int mib[2] = {CTL_KERN, KERN_OSREV}; + char osrev_str[12]; + uint32_t osrev = 0; + size_t osrev_len = sizeof(osrev); - s.clear(); - return false; + if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) { + ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev); + s.assign(osrev_str); + return true; + } + + s.clear(); + return false; } -bool -HostInfoFreeBSD::GetOSKernelDescription(std::string &s) -{ - struct utsname un; +bool HostInfoFreeBSD::GetOSKernelDescription(std::string &s) { + struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - s.clear(); + ::memset(&un, 0, sizeof(utsname)); + s.clear(); - if (uname(&un) < 0) - return false; + if (uname(&un) < 0) + return false; - s.assign(un.version); + s.assign(un.version); - return true; + return true; } -FileSpec -HostInfoFreeBSD::GetProgramFileSpec() -{ - static FileSpec g_program_filespec; - if (!g_program_filespec) - { - int exe_path_mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid()}; - size_t exe_path_size; - 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); - delete[] exe_path; - } +FileSpec HostInfoFreeBSD::GetProgramFileSpec() { + static FileSpec g_program_filespec; + if (!g_program_filespec) { + int exe_path_mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid()}; + size_t exe_path_size; + 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); + delete[] exe_path; } - return g_program_filespec; + } + return g_program_filespec; }
\ No newline at end of file diff --git a/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp b/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp index a4302a9e..97d4d9d 100644 --- a/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp +++ b/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp @@ -14,7 +14,7 @@ // C includes #include <errno.h> #include <pthread.h> -#if defined (__FreeBSD__) +#if defined(__FreeBSD__) #include <pthread_np.h> #endif #include <stdlib.h> @@ -26,54 +26,45 @@ using namespace lldb_private; -HostThreadFreeBSD::HostThreadFreeBSD() -{ -} +HostThreadFreeBSD::HostThreadFreeBSD() {} HostThreadFreeBSD::HostThreadFreeBSD(lldb::thread_t thread) - : HostThreadPosix(thread) -{ -} + : HostThreadPosix(thread) {} -void -HostThreadFreeBSD::GetName(lldb::tid_t tid, llvm::SmallVectorImpl<char> &name) -{ - name.clear(); - int pid = Host::GetCurrentProcessID(); +void HostThreadFreeBSD::GetName(lldb::tid_t tid, + llvm::SmallVectorImpl<char> &name) { + name.clear(); + int pid = Host::GetCurrentProcessID(); - struct kinfo_proc *kp = nullptr, *nkp; - size_t len = 0; - int error; - int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid}; + struct kinfo_proc *kp = nullptr, *nkp; + size_t len = 0; + int error; + int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, + (int)pid}; - while (1) - { - error = sysctl(ctl, 4, kp, &len, nullptr, 0); - if (kp == nullptr || (error != 0 && errno == ENOMEM)) - { - // Add extra space in case threads are added before next call. - len += sizeof(*kp) + len / 10; - nkp = (struct kinfo_proc *)realloc(kp, len); - if (nkp == nullptr) - { - free(kp); - return; - } - kp = nkp; - continue; - } - if (error != 0) - len = 0; - break; + while (1) { + error = sysctl(ctl, 4, kp, &len, nullptr, 0); + if (kp == nullptr || (error != 0 && errno == ENOMEM)) { + // Add extra space in case threads are added before next call. + len += sizeof(*kp) + len / 10; + nkp = (struct kinfo_proc *)realloc(kp, len); + if (nkp == nullptr) { + free(kp); + return; + } + kp = nkp; + continue; } + if (error != 0) + len = 0; + break; + } - for (size_t i = 0; i < len / sizeof(*kp); i++) - { - if (kp[i].ki_tid == (lwpid_t)tid) - { - name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname)); - break; - } + for (size_t i = 0; i < len / sizeof(*kp); i++) { + if (kp[i].ki_tid == (lwpid_t)tid) { + name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname)); + break; } - free(kp); + } + free(kp); } diff --git a/lldb/source/Host/freebsd/ThisThread.cpp b/lldb/source/Host/freebsd/ThisThread.cpp index e524fd4..da0f237 100644 --- a/lldb/source/Host/freebsd/ThisThread.cpp +++ b/lldb/source/Host/freebsd/ThisThread.cpp @@ -7,33 +7,29 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/ThisThread.h" +#include "lldb/Host/HostNativeThread.h" #include "llvm/ADT/SmallVector.h" #include <pthread.h> -#if defined (__FreeBSD__) +#if defined(__FreeBSD__) #include <pthread_np.h> #endif using namespace lldb_private; -void -ThisThread::SetName(llvm::StringRef name) -{ -#if defined (__FreeBSD__) // Kfreebsd does not have a simple alternative - ::pthread_set_name_np(::pthread_self(), name.data()); +void ThisThread::SetName(llvm::StringRef name) { +#if defined(__FreeBSD__) // Kfreebsd does not have a simple alternative + ::pthread_set_name_np(::pthread_self(), name.data()); #endif } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ -#if defined (__FreeBSD__) - HostNativeThread::GetName(::pthread_getthreadid_np(), name); +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { +#if defined(__FreeBSD__) + HostNativeThread::GetName(::pthread_getthreadid_np(), name); #else -// Kfreebsd - HostNativeThread::GetName((unsigned)pthread_self(), name); + // Kfreebsd + HostNativeThread::GetName((unsigned)pthread_self(), name); #endif } diff --git a/lldb/source/Host/linux/AbstractSocket.cpp b/lldb/source/Host/linux/AbstractSocket.cpp index 8ac0107..b6b59ae 100644 --- a/lldb/source/Host/linux/AbstractSocket.cpp +++ b/lldb/source/Host/linux/AbstractSocket.cpp @@ -15,17 +15,8 @@ using namespace lldb; using namespace lldb_private; AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error) - : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) -{ -} + : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) {} -size_t -AbstractSocket::GetNameOffset() const -{ - return 1; -} +size_t AbstractSocket::GetNameOffset() const { return 1; } -void -AbstractSocket::DeleteSocketFile(llvm::StringRef name) -{ -} +void AbstractSocket::DeleteSocketFile(llvm::StringRef name) {} diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp index 53d74d5..ca2084d 100644 --- a/lldb/source/Host/linux/Host.cpp +++ b/lldb/source/Host/linux/Host.cpp @@ -25,379 +25,353 @@ #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "Plugins/Process/Linux/ProcFileReader.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Symbol/ObjectFile.h" -#include "Plugins/Process/Linux/ProcFileReader.h" using namespace lldb; using namespace lldb_private; -typedef enum ProcessStateFlags -{ - eProcessStateRunning = (1u << 0), // Running - eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait - eProcessStateWaiting = (1u << 2), // Waiting in an uninterruptible disk sleep - eProcessStateZombie = (1u << 3), // Zombie - eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal) - eProcessStatePaging = (1u << 5) // Paging +typedef enum ProcessStateFlags { + eProcessStateRunning = (1u << 0), // Running + eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait + eProcessStateWaiting = (1u << 2), // Waiting in an uninterruptible disk sleep + eProcessStateZombie = (1u << 3), // Zombie + eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal) + eProcessStatePaging = (1u << 5) // Paging } ProcessStateFlags; -typedef struct ProcessStatInfo -{ - lldb::pid_t ppid; // Parent Process ID - uint32_t fProcessState; // ProcessStateFlags +typedef struct ProcessStatInfo { + lldb::pid_t ppid; // Parent Process ID + uint32_t fProcessState; // ProcessStateFlags } ProcessStatInfo; -// Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid). -static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid); - -static bool -ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info) -{ - // Read the /proc/$PID/stat file. - lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "stat"); - - // The filename of the executable is stored in parenthesis right after the pid. We look for the closing - // parenthesis for the filename and work from there in case the name has something funky like ')' in it. - const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')'); - if (filename_end) - { - char state = '\0'; - int ppid = LLDB_INVALID_PROCESS_ID; - - // Read state and ppid. - sscanf (filename_end + 1, " %c %d", &state, &ppid); - - stat_info.ppid = ppid; - - switch (state) - { - case 'R': - stat_info.fProcessState |= eProcessStateRunning; - break; - case 'S': - stat_info.fProcessState |= eProcessStateSleeping; - break; - case 'D': - stat_info.fProcessState |= eProcessStateWaiting; - break; - case 'Z': - stat_info.fProcessState |= eProcessStateZombie; - break; - case 'T': - stat_info.fProcessState |= eProcessStateTracedOrStopped; - break; - case 'W': - stat_info.fProcessState |= eProcessStatePaging; - break; - } - - return true; +// Get the process info with additional information from /proc/$PID/stat (like +// process state, and tracer pid). +static bool GetProcessAndStatInfo(lldb::pid_t pid, + ProcessInstanceInfo &process_info, + ProcessStatInfo &stat_info, + lldb::pid_t &tracerpid); + +static bool ReadProcPseudoFileStat(lldb::pid_t pid, + ProcessStatInfo &stat_info) { + // Read the /proc/$PID/stat file. + lldb::DataBufferSP buf_sp = + process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "stat"); + + // The filename of the executable is stored in parenthesis right after the + // pid. We look for the closing + // parenthesis for the filename and work from there in case the name has + // something funky like ')' in it. + const char *filename_end = strrchr((const char *)buf_sp->GetBytes(), ')'); + if (filename_end) { + char state = '\0'; + int ppid = LLDB_INVALID_PROCESS_ID; + + // Read state and ppid. + sscanf(filename_end + 1, " %c %d", &state, &ppid); + + stat_info.ppid = ppid; + + switch (state) { + case 'R': + stat_info.fProcessState |= eProcessStateRunning; + break; + case 'S': + stat_info.fProcessState |= eProcessStateSleeping; + break; + case 'D': + stat_info.fProcessState |= eProcessStateWaiting; + break; + case 'Z': + stat_info.fProcessState |= eProcessStateZombie; + break; + case 'T': + stat_info.fProcessState |= eProcessStateTracedOrStopped; + break; + case 'W': + stat_info.fProcessState |= eProcessStatePaging; + break; } - return false; -} - -static void -GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid) -{ - tracerpid = 0; - uint32_t rUid = UINT32_MAX; // Real User ID - uint32_t eUid = UINT32_MAX; // Effective User ID - uint32_t rGid = UINT32_MAX; // Real Group ID - uint32_t eGid = UINT32_MAX; // Effective Group ID - - // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields. - lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "status"); - - static const char uid_token[] = "Uid:"; - char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token); - if (buf_uid) - { - // Real, effective, saved set, and file system UIDs. Read the first two. - buf_uid += sizeof(uid_token); - rUid = strtol (buf_uid, &buf_uid, 10); - eUid = strtol (buf_uid, &buf_uid, 10); - } - - static const char gid_token[] = "Gid:"; - char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token); - if (buf_gid) - { - // Real, effective, saved set, and file system GIDs. Read the first two. - buf_gid += sizeof(gid_token); - rGid = strtol (buf_gid, &buf_gid, 10); - eGid = strtol (buf_gid, &buf_gid, 10); - } - - static const char tracerpid_token[] = "TracerPid:"; - char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token); - if (buf_tracerpid) - { - // Tracer PID. 0 if we're not being debugged. - buf_tracerpid += sizeof(tracerpid_token); - tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10); - } + return true; + } - process_info.SetUserID (rUid); - process_info.SetEffectiveUserID (eUid); - process_info.SetGroupID (rGid); - process_info.SetEffectiveGroupID (eGid); + return false; } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - return process_linux::ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv"); +static void GetLinuxProcessUserAndGroup(lldb::pid_t pid, + ProcessInstanceInfo &process_info, + lldb::pid_t &tracerpid) { + tracerpid = 0; + uint32_t rUid = UINT32_MAX; // Real User ID + uint32_t eUid = UINT32_MAX; // Effective User ID + uint32_t rGid = UINT32_MAX; // Real Group ID + uint32_t eGid = UINT32_MAX; // Effective Group ID + + // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: + // fields. + lldb::DataBufferSP buf_sp = + process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "status"); + + static const char uid_token[] = "Uid:"; + char *buf_uid = strstr((char *)buf_sp->GetBytes(), uid_token); + if (buf_uid) { + // Real, effective, saved set, and file system UIDs. Read the first two. + buf_uid += sizeof(uid_token); + rUid = strtol(buf_uid, &buf_uid, 10); + eUid = strtol(buf_uid, &buf_uid, 10); + } + + static const char gid_token[] = "Gid:"; + char *buf_gid = strstr((char *)buf_sp->GetBytes(), gid_token); + if (buf_gid) { + // Real, effective, saved set, and file system GIDs. Read the first two. + buf_gid += sizeof(gid_token); + rGid = strtol(buf_gid, &buf_gid, 10); + eGid = strtol(buf_gid, &buf_gid, 10); + } + + static const char tracerpid_token[] = "TracerPid:"; + char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token); + if (buf_tracerpid) { + // Tracer PID. 0 if we're not being debugged. + buf_tracerpid += sizeof(tracerpid_token); + tracerpid = strtol(buf_tracerpid, &buf_tracerpid, 10); + } + + process_info.SetUserID(rUid); + process_info.SetEffectiveUserID(eUid); + process_info.SetGroupID(rGid); + process_info.SetEffectiveGroupID(eGid); } -lldb::DataBufferSP -Host::GetAuxvData (lldb::pid_t pid) -{ - return process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "auxv"); +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + return process_linux::ProcFileReader::ReadIntoDataBuffer(process->GetID(), + "auxv"); } -static bool -IsDirNumeric(const char *dname) -{ - for (; *dname; dname++) - { - if (!isdigit (*dname)) - return false; - } - return true; +lldb::DataBufferSP Host::GetAuxvData(lldb::pid_t pid) { + return process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "auxv"); } -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - static const char procdir[] = "/proc/"; +static bool IsDirNumeric(const char *dname) { + for (; *dname; dname++) { + if (!isdigit(*dname)) + return false; + } + return true; +} - DIR *dirproc = opendir (procdir); - if (dirproc) - { - struct dirent *direntry = NULL; - const uid_t our_uid = getuid(); - const lldb::pid_t our_pid = getpid(); - bool all_users = match_info.GetMatchAllUsers(); +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + static const char procdir[] = "/proc/"; - while ((direntry = readdir (dirproc)) != NULL) - { - if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name)) - continue; + DIR *dirproc = opendir(procdir); + if (dirproc) { + struct dirent *direntry = NULL; + const uid_t our_uid = getuid(); + const lldb::pid_t our_pid = getpid(); + bool all_users = match_info.GetMatchAllUsers(); - lldb::pid_t pid = atoi (direntry->d_name); + while ((direntry = readdir(dirproc)) != NULL) { + if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) + continue; - // Skip this process. - if (pid == our_pid) - continue; + lldb::pid_t pid = atoi(direntry->d_name); - lldb::pid_t tracerpid; - ProcessStatInfo stat_info; - ProcessInstanceInfo process_info; + // Skip this process. + if (pid == our_pid) + continue; - if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid)) - continue; + lldb::pid_t tracerpid; + ProcessStatInfo stat_info; + ProcessInstanceInfo process_info; - // Skip if process is being debugged. - if (tracerpid != 0) - continue; + if (!GetProcessAndStatInfo(pid, process_info, stat_info, tracerpid)) + continue; - // Skip zombies. - if (stat_info.fProcessState & eProcessStateZombie) - continue; + // Skip if process is being debugged. + if (tracerpid != 0) + continue; - // 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; + // Skip zombies. + if (stat_info.fProcessState & eProcessStateZombie) + continue; - if (match_info.Matches (process_info)) - { - process_infos.Append (process_info); - } - } + // 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; - closedir (dirproc); + if (match_info.Matches(process_info)) { + process_infos.Append(process_info); + } } - return process_infos.GetSize(); + closedir(dirproc); + } + + return process_infos.GetSize(); } -bool -Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) -{ - bool tids_changed = false; - static const char procdir[] = "/proc/"; - static const char taskdir[] = "/task/"; - std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir; - DIR *dirproc = opendir (process_task_dir.c_str()); - - if (dirproc) - { - struct dirent *direntry = NULL; - while ((direntry = readdir (dirproc)) != NULL) - { - if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name)) - continue; - - lldb::tid_t tid = atoi(direntry->d_name); - TidMap::iterator it = tids_to_attach.find(tid); - if (it == tids_to_attach.end()) - { - tids_to_attach.insert(TidPair(tid, false)); - tids_changed = true; - } - } - closedir (dirproc); +bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { + bool tids_changed = false; + static const char procdir[] = "/proc/"; + static const char taskdir[] = "/task/"; + std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir; + DIR *dirproc = opendir(process_task_dir.c_str()); + + if (dirproc) { + struct dirent *direntry = NULL; + while ((direntry = readdir(dirproc)) != NULL) { + if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) + continue; + + lldb::tid_t tid = atoi(direntry->d_name); + TidMap::iterator it = tids_to_attach.find(tid); + if (it == tids_to_attach.end()) { + tids_to_attach.insert(TidPair(tid, false)); + tids_changed = true; + } } + closedir(dirproc); + } - return tids_changed; + return tids_changed; } -static bool -GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info) -{ - // Clear the architecture. - process_info.GetArchitecture().Clear(); - - ModuleSpecList specs; - FileSpec filespec (exe_path, false); - const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, 0, specs); - // GetModuleSpecifications() could fail if the executable has been deleted or is locked. - // But it shouldn't return more than 1 architecture. - assert(num_specs <= 1 && "Linux plugin supports only a single architecture"); - if (num_specs == 1) - { - ModuleSpec module_spec; - if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid()) - { - process_info.GetArchitecture () = module_spec.GetArchitecture(); - return true; - } +static bool GetELFProcessCPUType(const char *exe_path, + ProcessInstanceInfo &process_info) { + // Clear the architecture. + process_info.GetArchitecture().Clear(); + + ModuleSpecList specs; + FileSpec filespec(exe_path, false); + const size_t num_specs = + ObjectFile::GetModuleSpecifications(filespec, 0, 0, specs); + // GetModuleSpecifications() could fail if the executable has been deleted or + // is locked. + // But it shouldn't return more than 1 architecture. + assert(num_specs <= 1 && "Linux plugin supports only a single architecture"); + if (num_specs == 1) { + ModuleSpec module_spec; + if (specs.GetModuleSpecAtIndex(0, module_spec) && + module_spec.GetArchitecture().IsValid()) { + process_info.GetArchitecture() = module_spec.GetArchitecture(); + return true; } - return false; + } + return false; } -static bool -GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid) -{ - tracerpid = 0; - process_info.Clear(); - ::memset (&stat_info, 0, sizeof(stat_info)); - stat_info.ppid = LLDB_INVALID_PROCESS_ID; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Use special code here because proc/[pid]/exe is a symbolic link. - char link_path[PATH_MAX]; - char exe_path[PATH_MAX] = ""; - if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) - { - if (log) - log->Printf("%s: failed to sprintf pid %" PRIu64, __FUNCTION__, pid); - return false; - } - - ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1); - if (len <= 0) - { - if (log) - log->Printf("%s: failed to read link %s: %s", __FUNCTION__, link_path, strerror(errno)); - return false; - } - - // readlink does not append a null byte. - exe_path[len] = 0; - - // If the binary has been deleted, the link name has " (deleted)" appended. - // Remove if there. - static const ssize_t deleted_len = strlen(" (deleted)"); - if (len > deleted_len && - !strcmp(exe_path + len - deleted_len, " (deleted)")) - { - exe_path[len - deleted_len] = 0; - } - else - { - GetELFProcessCPUType (exe_path, process_info); - } - - process_info.SetProcessID(pid); - process_info.GetExecutableFile().SetFile(exe_path, false); - process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture()); - - lldb::DataBufferSP buf_sp; - - // Get the process environment. - buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ"); - Args &info_env = process_info.GetEnvironmentEntries(); - char *next_var = (char *)buf_sp->GetBytes(); - char *end_buf = next_var + buf_sp->GetByteSize(); - while (next_var < end_buf && 0 != *next_var) - { - info_env.AppendArgument(next_var); - next_var += strlen(next_var) + 1; - } +static bool GetProcessAndStatInfo(lldb::pid_t pid, + ProcessInstanceInfo &process_info, + ProcessStatInfo &stat_info, + lldb::pid_t &tracerpid) { + tracerpid = 0; + process_info.Clear(); + ::memset(&stat_info, 0, sizeof(stat_info)); + stat_info.ppid = LLDB_INVALID_PROCESS_ID; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Use special code here because proc/[pid]/exe is a symbolic link. + char link_path[PATH_MAX]; + char exe_path[PATH_MAX] = ""; + if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) { + if (log) + log->Printf("%s: failed to sprintf pid %" PRIu64, __FUNCTION__, pid); + return false; + } - // Get the command line used to start the process. - buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline"); - - // Grab Arg0 first, if there is one. - char *cmd = (char *)buf_sp->GetBytes(); - if (cmd) - { - process_info.SetArg0(cmd); - - // Now process any remaining arguments. - Args &info_args = process_info.GetArguments(); - char *next_arg = cmd + strlen(cmd) + 1; - end_buf = cmd + buf_sp->GetByteSize(); - while (next_arg < end_buf && 0 != *next_arg) - { - info_args.AppendArgument(next_arg); - next_arg += strlen(next_arg) + 1; - } + ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1); + if (len <= 0) { + if (log) + log->Printf("%s: failed to read link %s: %s", __FUNCTION__, link_path, + strerror(errno)); + return false; + } + + // readlink does not append a null byte. + exe_path[len] = 0; + + // If the binary has been deleted, the link name has " (deleted)" appended. + // Remove if there. + static const ssize_t deleted_len = strlen(" (deleted)"); + if (len > deleted_len && + !strcmp(exe_path + len - deleted_len, " (deleted)")) { + exe_path[len - deleted_len] = 0; + } else { + GetELFProcessCPUType(exe_path, process_info); + } + + process_info.SetProcessID(pid); + process_info.GetExecutableFile().SetFile(exe_path, false); + process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture()); + + lldb::DataBufferSP buf_sp; + + // Get the process environment. + buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ"); + Args &info_env = process_info.GetEnvironmentEntries(); + char *next_var = (char *)buf_sp->GetBytes(); + char *end_buf = next_var + buf_sp->GetByteSize(); + while (next_var < end_buf && 0 != *next_var) { + info_env.AppendArgument(next_var); + next_var += strlen(next_var) + 1; + } + + // Get the command line used to start the process. + buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline"); + + // Grab Arg0 first, if there is one. + char *cmd = (char *)buf_sp->GetBytes(); + if (cmd) { + process_info.SetArg0(cmd); + + // Now process any remaining arguments. + Args &info_args = process_info.GetArguments(); + char *next_arg = cmd + strlen(cmd) + 1; + end_buf = cmd + buf_sp->GetByteSize(); + while (next_arg < end_buf && 0 != *next_arg) { + info_args.AppendArgument(next_arg); + next_arg += strlen(next_arg) + 1; } + } - // Read /proc/$PID/stat to get our parent pid. - if (ReadProcPseudoFileStat (pid, stat_info)) - { - process_info.SetParentProcessID (stat_info.ppid); - } + // Read /proc/$PID/stat to get our parent pid. + if (ReadProcPseudoFileStat(pid, stat_info)) { + process_info.SetParentProcessID(stat_info.ppid); + } - // Get User and Group IDs and get tracer pid. - GetLinuxProcessUserAndGroup (pid, process_info, tracerpid); + // Get User and Group IDs and get tracer pid. + GetLinuxProcessUserAndGroup(pid, process_info, tracerpid); - return true; + return true; } -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - lldb::pid_t tracerpid; - ProcessStatInfo stat_info; +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + lldb::pid_t tracerpid; + ProcessStatInfo stat_info; - return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid); + return GetProcessAndStatInfo(pid, process_info, stat_info, 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; +size_t Host::GetEnvironment(StringList &env) { + char **host_env = environ; + char *env_entry; + size_t i; + for (i = 0; (env_entry = host_env[i]) != NULL; ++i) + env.AppendString(env_entry); + return i; } -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - return Error("unimplemented"); +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + return Error("unimplemented"); } diff --git a/lldb/source/Host/linux/HostInfoLinux.cpp b/lldb/source/Host/linux/HostInfoLinux.cpp index 0d0ba33..0f2ab7922 100644 --- a/lldb/source/Host/linux/HostInfoLinux.cpp +++ b/lldb/source/Host/linux/HostInfoLinux.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Log.h" #include "lldb/Host/linux/HostInfoLinux.h" +#include "lldb/Core/Log.h" #include <limits.h> #include <stdio.h> @@ -20,263 +20,224 @@ using namespace lldb_private; -namespace -{ -struct HostInfoLinuxFields -{ - HostInfoLinuxFields() - : m_os_major(0) - , m_os_minor(0) - , m_os_update(0) - { - } +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; + std::string m_distribution_id; + uint32_t m_os_major; + uint32_t m_os_minor; + uint32_t m_os_update; }; HostInfoLinuxFields *g_fields = nullptr; } -void -HostInfoLinux::Initialize() -{ - HostInfoPosix::Initialize(); +void HostInfoLinux::Initialize() { + HostInfoPosix::Initialize(); - g_fields = new HostInfoLinuxFields(); + g_fields = new HostInfoLinuxFields(); } -uint32_t -HostInfoLinux::GetMaxThreadNameLength() -{ - return 16; -} +uint32_t HostInfoLinux::GetMaxThreadNameLength() { return 16; } -bool -HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) -{ - static bool success = false; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - - 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; - } - } - }); +bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + static bool success = false; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + 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; + } + } + }); - major = g_fields->m_os_major; - minor = g_fields->m_os_minor; - update = g_fields->m_os_update; - return success; + major = g_fields->m_os_major; + minor = g_fields->m_os_minor; + update = g_fields->m_os_update; + return success; } -bool -HostInfoLinux::GetOSBuildString(std::string &s) -{ - struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - s.clear(); +bool HostInfoLinux::GetOSBuildString(std::string &s) { + struct utsname un; + ::memset(&un, 0, sizeof(utsname)); + s.clear(); - if (uname(&un) < 0) - return false; + if (uname(&un) < 0) + return false; - s.assign(un.release); - return true; + s.assign(un.release); + return true; } -bool -HostInfoLinux::GetOSKernelDescription(std::string &s) -{ - struct utsname un; +bool HostInfoLinux::GetOSKernelDescription(std::string &s) { + struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - s.clear(); + ::memset(&un, 0, sizeof(utsname)); + s.clear(); - if (uname(&un) < 0) - return false; + if (uname(&un) < 0) + return false; - s.assign(un.version); - return true; + s.assign(un.version); + return true; } -llvm::StringRef -HostInfoLinux::GetDistributionId() -{ - // Try to run 'lbs_release -i', and use that response - // for the distribution id. - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST)); +llvm::StringRef HostInfoLinux::GetDistributionId() { + // Try to run 'lbs_release -i', and use that response + // for the distribution id. + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST)); + if (log) + log->Printf("attempting to determine Linux distribution..."); + + // 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"}; + + for (size_t exe_index = 0; + exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) { + const char *const get_distribution_info_exe = exe_paths[exe_index]; + if (access(get_distribution_info_exe, F_OK)) { + // this exe doesn't exist, move on to next exe if (log) - log->Printf("attempting to determine Linux distribution..."); - - // 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"}; - - for (size_t exe_index = 0; exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) - { - const char *const get_distribution_info_exe = exe_paths[exe_index]; - if (access(get_distribution_info_exe, F_OK)) - { - // this exe doesn't exist, move on to next exe - if (log) - log->Printf("executable doesn't exist: %s", get_distribution_info_exe); - continue; - } - - // execute the distribution-retrieval command, read output - std::string get_distribution_id_command(get_distribution_info_exe); - get_distribution_id_command += " -i"; - - FILE *file = popen(get_distribution_id_command.c_str(), "r"); - if (!file) - { - if (log) - log->Printf("failed to run command: \"%s\", cannot retrieve " - "platform information", - get_distribution_id_command.c_str()); - break; - } - - // retrieve the distribution id string. - char distribution_id[256] = {'\0'}; - if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != NULL) - { - if (log) - log->Printf("distribution id command returned \"%s\"", distribution_id); - - const char *const distributor_id_key = "Distributor ID:\t"; - if (strstr(distribution_id, distributor_id_key)) - { - // strip newlines - std::string id_string(distribution_id + strlen(distributor_id_key)); - id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'), id_string.end()); - - // lower case it and convert whitespace to underscores - std::transform(id_string.begin(), id_string.end(), id_string.begin(), [](char ch) - { - return tolower(isspace(ch) ? '_' : ch); - }); - - g_fields->m_distribution_id = id_string; - if (log) - log->Printf("distribution id set to \"%s\"", g_fields->m_distribution_id.c_str()); - } - else - { - if (log) - log->Printf("failed to find \"%s\" field in \"%s\"", distributor_id_key, distribution_id); - } - } - else - { - if (log) - log->Printf("failed to retrieve distribution id, \"%s\" returned no" - " lines", - get_distribution_id_command.c_str()); - } - - // clean up the file - pclose(file); - } - }); + log->Printf("executable doesn't exist: %s", + get_distribution_info_exe); + continue; + } - return g_fields->m_distribution_id.c_str(); -} + // execute the distribution-retrieval command, read output + std::string get_distribution_id_command(get_distribution_info_exe); + get_distribution_id_command += " -i"; -FileSpec -HostInfoLinux::GetProgramFileSpec() -{ - static FileSpec g_program_filespec; - - if (!g_program_filespec) - { - char exe_path[PATH_MAX]; - 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); + FILE *file = popen(get_distribution_id_command.c_str(), "r"); + if (!file) { + if (log) + log->Printf("failed to run command: \"%s\", cannot retrieve " + "platform information", + get_distribution_id_command.c_str()); + break; + } + + // retrieve the distribution id string. + char distribution_id[256] = {'\0'}; + if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != NULL) { + if (log) + log->Printf("distribution id command returned \"%s\"", + distribution_id); + + const char *const distributor_id_key = "Distributor ID:\t"; + if (strstr(distribution_id, distributor_id_key)) { + // strip newlines + std::string id_string(distribution_id + strlen(distributor_id_key)); + id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'), + id_string.end()); + + // lower case it and convert whitespace to underscores + std::transform( + id_string.begin(), id_string.end(), id_string.begin(), + [](char ch) { return tolower(isspace(ch) ? '_' : ch); }); + + g_fields->m_distribution_id = id_string; + if (log) + log->Printf("distribution id set to \"%s\"", + g_fields->m_distribution_id.c_str()); + } else { + if (log) + log->Printf("failed to find \"%s\" field in \"%s\"", + distributor_id_key, distribution_id); } + } else { + if (log) + log->Printf("failed to retrieve distribution id, \"%s\" returned no" + " lines", + get_distribution_id_command.c_str()); + } + + // clean up the file + pclose(file); } + }); - return g_program_filespec; + return g_fields->m_distribution_id.c_str(); } -bool -HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && - file_spec.IsAbsolute() && - file_spec.Exists()) - return true; - file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory(); - return !file_spec.GetDirectory().IsEmpty(); -} +FileSpec HostInfoLinux::GetProgramFileSpec() { + static FileSpec g_program_filespec; -bool -HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) -{ - FileSpec temp_file("/usr/lib/lldb/plugins", true); - file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); - return true; + if (!g_program_filespec) { + char exe_path[PATH_MAX]; + 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); + } + } + + return g_program_filespec; } -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. - 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); - user_plugin_dir += "/lldb"; - file_spec.GetDirectory().SetCString(user_plugin_dir.c_str()); - } - else - file_spec.GetDirectory().SetCString("~/.local/share/lldb"); +bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) { + if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && + file_spec.IsAbsolute() && file_spec.Exists()) return true; + file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory(); + return !file_spec.GetDirectory().IsEmpty(); } -void -HostInfoLinux::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64); +bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) { + FileSpec temp_file("/usr/lib/lldb/plugins", true); + file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); + return true; +} - const char *distribution_id = GetDistributionId().data(); +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. + 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); + user_plugin_dir += "/lldb"; + file_spec.GetDirectory().SetCString(user_plugin_dir.c_str()); + } else + file_spec.GetDirectory().SetCString("~/.local/share/lldb"); + return true; +} - // On Linux, "unknown" in the vendor slot isn't what we want for the default - // triple. It's probably an artifact of config.guess. - if (arch_32.IsValid()) - { - arch_32.SetDistributionId(distribution_id); - if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor) - arch_32.GetTriple().setVendorName(llvm::StringRef()); - } - if (arch_64.IsValid()) - { - arch_64.SetDistributionId(distribution_id); - if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor) - arch_64.GetTriple().setVendorName(llvm::StringRef()); - } +void HostInfoLinux::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64); + + const char *distribution_id = GetDistributionId().data(); + + // On Linux, "unknown" in the vendor slot isn't what we want for the default + // triple. It's probably an artifact of config.guess. + if (arch_32.IsValid()) { + arch_32.SetDistributionId(distribution_id); + if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor) + arch_32.GetTriple().setVendorName(llvm::StringRef()); + } + if (arch_64.IsValid()) { + arch_64.SetDistributionId(distribution_id); + if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor) + arch_64.GetTriple().setVendorName(llvm::StringRef()); + } } diff --git a/lldb/source/Host/linux/HostThreadLinux.cpp b/lldb/source/Host/linux/HostThreadLinux.cpp index 2312ced..625f05d 100644 --- a/lldb/source/Host/linux/HostThreadLinux.cpp +++ b/lldb/source/Host/linux/HostThreadLinux.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataBuffer.h" #include "lldb/Host/linux/HostThreadLinux.h" #include "Plugins/Process/Linux/ProcFileReader.h" +#include "lldb/Core/DataBuffer.h" #include "llvm/ADT/SmallVector.h" @@ -17,36 +17,29 @@ using namespace lldb_private; -HostThreadLinux::HostThreadLinux() - : HostThreadPosix() -{ -} +HostThreadLinux::HostThreadLinux() : HostThreadPosix() {} HostThreadLinux::HostThreadLinux(lldb::thread_t thread) - : HostThreadPosix(thread) -{ -} + : HostThreadPosix(thread) {} -void -HostThreadLinux::SetName(lldb::thread_t thread, llvm::StringRef name) -{ +void HostThreadLinux::SetName(lldb::thread_t thread, llvm::StringRef name) { #if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__) - ::pthread_setname_np(thread, name.data()); + ::pthread_setname_np(thread, name.data()); #else - (void) thread; - (void) name; + (void)thread; + (void)name; #endif } -void -HostThreadLinux::GetName(lldb::thread_t thread, llvm::SmallVectorImpl<char> &name) -{ - // Read /proc/$TID/comm file. - lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(thread, "comm"); - const char *comm_str = (const char *)buf_sp->GetBytes(); - const char *cr_str = ::strchr(comm_str, '\n'); - size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); - - name.clear(); - name.append(comm_str, comm_str + length); +void HostThreadLinux::GetName(lldb::thread_t thread, + llvm::SmallVectorImpl<char> &name) { + // Read /proc/$TID/comm file. + lldb::DataBufferSP buf_sp = + process_linux::ProcFileReader::ReadIntoDataBuffer(thread, "comm"); + const char *comm_str = (const char *)buf_sp->GetBytes(); + const char *cr_str = ::strchr(comm_str, '\n'); + size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); + + name.clear(); + name.append(comm_str, comm_str + length); } diff --git a/lldb/source/Host/linux/LibcGlue.cpp b/lldb/source/Host/linux/LibcGlue.cpp index 63d026f..c036bb2 100644 --- a/lldb/source/Host/linux/LibcGlue.cpp +++ b/lldb/source/Host/linux/LibcGlue.cpp @@ -9,22 +9,23 @@ // This file adds functions missing from libc on older versions of linux -#include <unistd.h> -#include <sys/syscall.h> -#include <lldb/Host/linux/Uio.h> #include <cerrno> +#include <lldb/Host/linux/Uio.h> +#include <sys/syscall.h> +#include <unistd.h> -#ifndef HAVE_PROCESS_VM_READV // If the syscall wrapper is not available, provide one. -ssize_t process_vm_readv(::pid_t pid, - const struct iovec *local_iov, unsigned long liovcnt, - const struct iovec *remote_iov, unsigned long riovcnt, - unsigned long flags) -{ -#ifdef HAVE_NR_PROCESS_VM_READV // If we have the syscall number, we can issue the syscall ourselves. - return syscall(__NR_process_vm_readv, pid, local_iov, liovcnt, remote_iov, riovcnt, flags); +#ifndef HAVE_PROCESS_VM_READV // If the syscall wrapper is not available, + // provide one. +ssize_t process_vm_readv(::pid_t pid, const struct iovec *local_iov, + unsigned long liovcnt, const struct iovec *remote_iov, + unsigned long riovcnt, unsigned long flags) { +#ifdef HAVE_NR_PROCESS_VM_READV // If we have the syscall number, we can issue + // the syscall ourselves. + return syscall(__NR_process_vm_readv, pid, local_iov, liovcnt, remote_iov, + riovcnt, flags); #else // If not, let's pretend the syscall is not present. - errno = ENOSYS; - return -1; + errno = ENOSYS; + return -1; #endif } #endif diff --git a/lldb/source/Host/linux/ProcessLauncherLinux.cpp b/lldb/source/Host/linux/ProcessLauncherLinux.cpp index 2e5f4e5..444a8fd 100644 --- a/lldb/source/Host/linux/ProcessLauncherLinux.cpp +++ b/lldb/source/Host/linux/ProcessLauncherLinux.cpp @@ -25,189 +25,193 @@ using namespace lldb; using namespace lldb_private; -static void -FixupEnvironment(Args &env) -{ +static void FixupEnvironment(Args &env) { #ifdef __ANDROID_NDK__ - // 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="; - static const int path_len = ::strlen(path); - for (const char **args = env.GetConstArgumentVector(); *args; ++args) - if (::strncmp(path, *args, path_len) == 0) - return; - env.AppendArgument("PATH=/system/bin"); + // 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="; + static const int path_len = ::strlen(path); + for (const char **args = env.GetConstArgumentVector(); *args; ++args) + if (::strncmp(path, *args, path_len) == 0) + return; + env.AppendArgument("PATH=/system/bin"); #endif } -static void LLVM_ATTRIBUTE_NORETURN -ExitWithError(int error_fd, const char *operation) -{ - std::ostringstream os; - os << operation << " failed: " << strerror(errno); - write(error_fd, os.str().data(), os.str().size()); - close(error_fd); - _exit(1); +static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd, + const char *operation) { + std::ostringstream os; + os << operation << " failed: " << strerror(errno); + write(error_fd, os.str().data(), os.str().size()); + close(error_fd); + _exit(1); } -static void -DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, int flags) -{ - int target_fd = ::open(file_spec.GetCString(), flags, 0666); +static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, + int flags) { + int target_fd = ::open(file_spec.GetCString(), flags, 0666); - if (target_fd == -1) - ExitWithError(error_fd, "DupDescriptor-open"); + if (target_fd == -1) + ExitWithError(error_fd, "DupDescriptor-open"); - if (target_fd == fd) - return; - - if (::dup2(target_fd, fd) == -1) - ExitWithError(error_fd, "DupDescriptor-dup2"); - - ::close(target_fd); + if (target_fd == fd) return; -} - -static void LLVM_ATTRIBUTE_NORETURN -ChildFunc(int error_fd, const ProcessLaunchInfo &info) -{ - // First, make sure we disable all logging. If we are logging to stdout, our logs can be - // mistaken for inferior output. - Log::DisableAllLogChannels(nullptr); - - // Do not inherit setgid powers. - if (setgid(getgid()) != 0) - ExitWithError(error_fd, "setgid"); - - if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) - { - if (setpgid(0, 0) != 0) - ExitWithError(error_fd, "setpgid"); - } - for (size_t i = 0; i < info.GetNumFileActions(); ++i) - { - const FileAction &action = *info.GetFileActionAtIndex(i); - switch (action.GetAction()) - { - case FileAction::eFileActionClose: - if (close(action.GetFD()) != 0) - ExitWithError(error_fd, "close"); - break; - case FileAction::eFileActionDuplicate: - if (dup2(action.GetFD(), action.GetActionArgument()) == -1) - ExitWithError(error_fd, "dup2"); - break; - case FileAction::eFileActionOpen: - DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(), action.GetActionArgument()); - break; - case FileAction::eFileActionNone: - break; - } - } - - const char **argv = info.GetArguments().GetConstArgumentVector(); - - // Change working directory - if (info.GetWorkingDirectory() && 0 != ::chdir(info.GetWorkingDirectory().GetCString())) - ExitWithError(error_fd, "chdir"); + if (::dup2(target_fd, fd) == -1) + ExitWithError(error_fd, "DupDescriptor-dup2"); - // Disable ASLR if requested. - if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) - { - const unsigned long personality_get_current = 0xffffffff; - int value = personality(personality_get_current); - if (value == -1) - ExitWithError(error_fd, "personality get"); - - value = personality(ADDR_NO_RANDOMIZE | value); - if (value == -1) - ExitWithError(error_fd, "personality set"); - } - - Args env = info.GetEnvironmentEntries(); - FixupEnvironment(env); - const char **envp = env.GetConstArgumentVector(); - - // Clear the signal mask to prevent the child from being affected by - // any masking done by the parent. - sigset_t set; - if (sigemptyset(&set) != 0 || pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) - ExitWithError(error_fd, "pthread_sigmask"); - - if (info.GetFlags().Test(eLaunchFlagDebug)) - { - // HACK: - // Close everything besides stdin, stdout, and stderr that has no file - // action to avoid leaking. Only do this when debugging, as elsewhere we actually rely on - // passing open descriptors to child processes. - for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) - if (!info.GetFileActionForFD(fd) && fd != error_fd) - close(fd); - - // Start tracing this child that is about to exec. - if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) - ExitWithError(error_fd, "ptrace"); - } + ::close(target_fd); + return; +} - // Execute. We should never return... - execve(argv[0], const_cast<char *const *>(argv), const_cast<char *const *>(envp)); - - if (errno == ETXTBSY) - { - // On android M and earlier we can get this error because the adb deamon can hold a write - // handle on the executable even after it has finished uploading it. This state lasts - // only a short time and happens only when there are many concurrent adb commands being - // issued, such as when running the test suite. (The file remains open when someone does - // an "adb shell" command in the fork() child before it has had a chance to exec.) Since - // this state should clear up quickly, wait a while and then give it one more go. - usleep(50000); - execve(argv[0], const_cast<char *const *>(argv), const_cast<char *const *>(envp)); +static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, + const ProcessLaunchInfo &info) { + // First, make sure we disable all logging. If we are logging to stdout, our + // logs can be + // mistaken for inferior output. + Log::DisableAllLogChannels(nullptr); + + // Do not inherit setgid powers. + if (setgid(getgid()) != 0) + ExitWithError(error_fd, "setgid"); + + if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) { + if (setpgid(0, 0) != 0) + ExitWithError(error_fd, "setpgid"); + } + + for (size_t i = 0; i < info.GetNumFileActions(); ++i) { + const FileAction &action = *info.GetFileActionAtIndex(i); + switch (action.GetAction()) { + case FileAction::eFileActionClose: + if (close(action.GetFD()) != 0) + ExitWithError(error_fd, "close"); + break; + case FileAction::eFileActionDuplicate: + if (dup2(action.GetFD(), action.GetActionArgument()) == -1) + ExitWithError(error_fd, "dup2"); + break; + case FileAction::eFileActionOpen: + DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(), + action.GetActionArgument()); + break; + case FileAction::eFileActionNone: + break; } - - // ...unless exec fails. In which case we definitely need to end the child here. - ExitWithError(error_fd, "execve"); + } + + const char **argv = info.GetArguments().GetConstArgumentVector(); + + // Change working directory + if (info.GetWorkingDirectory() && + 0 != ::chdir(info.GetWorkingDirectory().GetCString())) + ExitWithError(error_fd, "chdir"); + + // Disable ASLR if requested. + if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) { + const unsigned long personality_get_current = 0xffffffff; + int value = personality(personality_get_current); + if (value == -1) + ExitWithError(error_fd, "personality get"); + + value = personality(ADDR_NO_RANDOMIZE | value); + if (value == -1) + ExitWithError(error_fd, "personality set"); + } + + Args env = info.GetEnvironmentEntries(); + FixupEnvironment(env); + const char **envp = env.GetConstArgumentVector(); + + // Clear the signal mask to prevent the child from being affected by + // any masking done by the parent. + sigset_t set; + if (sigemptyset(&set) != 0 || + pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) + ExitWithError(error_fd, "pthread_sigmask"); + + if (info.GetFlags().Test(eLaunchFlagDebug)) { + // HACK: + // Close everything besides stdin, stdout, and stderr that has no file + // action to avoid leaking. Only do this when debugging, as elsewhere we + // actually rely on + // passing open descriptors to child processes. + for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) + if (!info.GetFileActionForFD(fd) && fd != error_fd) + close(fd); + + // Start tracing this child that is about to exec. + if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) + ExitWithError(error_fd, "ptrace"); + } + + // Execute. We should never return... + execve(argv[0], const_cast<char *const *>(argv), + const_cast<char *const *>(envp)); + + if (errno == ETXTBSY) { + // On android M and earlier we can get this error because the adb deamon can + // hold a write + // handle on the executable even after it has finished uploading it. This + // state lasts + // only a short time and happens only when there are many concurrent adb + // commands being + // issued, such as when running the test suite. (The file remains open when + // someone does + // an "adb shell" command in the fork() child before it has had a chance to + // exec.) Since + // this state should clear up quickly, wait a while and then give it one + // more go. + usleep(50000); + execve(argv[0], const_cast<char *const *>(argv), + const_cast<char *const *>(envp)); + } + + // ...unless exec fails. In which case we definitely need to end the child + // here. + ExitWithError(error_fd, "execve"); } HostProcess -ProcessLauncherLinux::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - char exe_path[PATH_MAX]; - launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - - // A pipe used by the child process to report errors. - PipePosix pipe; - const bool child_processes_inherit = false; - error = pipe.CreateNew(child_processes_inherit); - if (error.Fail()) - return HostProcess(); - - ::pid_t pid = ::fork(); - if (pid == -1) - { - // Fork failed - error.SetErrorStringWithFormat("Fork failed with error message: %s", strerror(errno)); - return HostProcess(LLDB_INVALID_PROCESS_ID); - } - if (pid == 0) - { - // child process - pipe.CloseReadFileDescriptor(); - ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info); - } +ProcessLauncherLinux::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + char exe_path[PATH_MAX]; + launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + + // A pipe used by the child process to report errors. + PipePosix pipe; + const bool child_processes_inherit = false; + error = pipe.CreateNew(child_processes_inherit); + if (error.Fail()) + return HostProcess(); - // parent process + ::pid_t pid = ::fork(); + if (pid == -1) { + // Fork failed + error.SetErrorStringWithFormat("Fork failed with error message: %s", + strerror(errno)); + return HostProcess(LLDB_INVALID_PROCESS_ID); + } + if (pid == 0) { + // child process + pipe.CloseReadFileDescriptor(); + ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info); + } - pipe.CloseWriteFileDescriptor(); - char buf[1000]; - int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf); + // parent process - if (r == 0) - return HostProcess(pid); // No error. We're done. + pipe.CloseWriteFileDescriptor(); + char buf[1000]; + int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf); - error.SetErrorString(buf); + if (r == 0) + return HostProcess(pid); // No error. We're done. - waitpid(pid, nullptr, 0); + error.SetErrorString(buf); - return HostProcess(); + waitpid(pid, nullptr, 0); + + return HostProcess(); } diff --git a/lldb/source/Host/linux/ThisThread.cpp b/lldb/source/Host/linux/ThisThread.cpp index 1c68c8b..f65440b 100644 --- a/lldb/source/Host/linux/ThisThread.cpp +++ b/lldb/source/Host/linux/ThisThread.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/ThisThread.h" +#include "lldb/Host/HostNativeThread.h" #include "llvm/ADT/SmallVector.h" @@ -16,14 +16,10 @@ using namespace lldb_private; -void -ThisThread::SetName(llvm::StringRef name) -{ - HostNativeThread::SetName(::pthread_self(), name); +void ThisThread::SetName(llvm::StringRef name) { + HostNativeThread::SetName(::pthread_self(), name); } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ - HostNativeThread::GetName(::pthread_self(), name); +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { + HostNativeThread::GetName(::pthread_self(), name); } diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index 7754bc6..01231ce 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -11,8 +11,9 @@ #include <AvailabilityMacros.h> -#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 -#define NO_XPC_SERVICES 1 +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define NO_XPC_SERVICES 1 #endif #if !defined(NO_XPC_SERVICES) @@ -21,18 +22,19 @@ #define LaunchUsingXPCRightName "com.apple.dt.Xcode.RootDebuggingXPCService" -// These XPC messaging keys are used for communication between Host.mm and the XPC service. -#define LauncherXPCServiceAuthKey "auth-key" -#define LauncherXPCServiceArgPrefxKey "arg" -#define LauncherXPCServiceEnvPrefxKey "env" -#define LauncherXPCServiceCPUTypeKey "cpuType" -#define LauncherXPCServicePosixspawnFlagsKey "posixspawnFlags" -#define LauncherXPCServiceStdInPathKeyKey "stdInPath" -#define LauncherXPCServiceStdOutPathKeyKey "stdOutPath" -#define LauncherXPCServiceStdErrPathKeyKey "stdErrPath" -#define LauncherXPCServiceChildPIDKey "childPID" -#define LauncherXPCServiceErrorTypeKey "errorType" -#define LauncherXPCServiceCodeTypeKey "errorCode" +// These XPC messaging keys are used for communication between Host.mm and the +// XPC service. +#define LauncherXPCServiceAuthKey "auth-key" +#define LauncherXPCServiceArgPrefxKey "arg" +#define LauncherXPCServiceEnvPrefxKey "env" +#define LauncherXPCServiceCPUTypeKey "cpuType" +#define LauncherXPCServicePosixspawnFlagsKey "posixspawnFlags" +#define LauncherXPCServiceStdInPathKeyKey "stdInPath" +#define LauncherXPCServiceStdOutPathKeyKey "stdOutPath" +#define LauncherXPCServiceStdErrPathKeyKey "stdErrPath" +#define LauncherXPCServiceChildPIDKey "childPID" +#define LauncherXPCServiceErrorTypeKey "errorType" +#define LauncherXPCServiceCodeTypeKey "errorCode" #endif @@ -79,132 +81,112 @@ #include "cfcpp/CFCReleaser.h" #include "cfcpp/CFCString.h" - #include <objc/objc-auto.h> #include <CoreFoundation/CoreFoundation.h> #include <Foundation/Foundation.h> #ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif -extern "C" -{ - int __pthread_chdir(const char *path); - int __pthread_fchdir (int fildes); +extern "C" { +int __pthread_chdir(const char *path); +int __pthread_fchdir(int fildes); } using namespace lldb; using namespace lldb_private; -bool -Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory) -{ -#if defined (__APPLE__) - if (file.GetFileType () == FileSpec::eFileTypeDirectory) - { - char path[PATH_MAX]; - if (file.GetPath(path, sizeof(path))) - { - CFCBundle bundle (path); - if (bundle.GetPath (path, sizeof(path))) - { - bundle_directory.SetFile (path, false); - return true; - } - } +bool Host::GetBundleDirectory(const FileSpec &file, + FileSpec &bundle_directory) { +#if defined(__APPLE__) + if (file.GetFileType() == FileSpec::eFileTypeDirectory) { + char path[PATH_MAX]; + if (file.GetPath(path, sizeof(path))) { + CFCBundle bundle(path); + if (bundle.GetPath(path, sizeof(path))) { + bundle_directory.SetFile(path, false); + return true; + } } + } #endif - bundle_directory.Clear(); - return false; + bundle_directory.Clear(); + return false; } - -bool -Host::ResolveExecutableInBundle (FileSpec &file) -{ -#if defined (__APPLE__) - if (file.GetFileType () == FileSpec::eFileTypeDirectory) - { - char path[PATH_MAX]; - if (file.GetPath(path, sizeof(path))) - { - CFCBundle bundle (path); - CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ()); - if (url.get()) - { - if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path))) - { - file.SetFile(path, false); - return true; - } - } +bool Host::ResolveExecutableInBundle(FileSpec &file) { +#if defined(__APPLE__) + if (file.GetFileType() == FileSpec::eFileTypeDirectory) { + char path[PATH_MAX]; + if (file.GetPath(path, sizeof(path))) { + CFCBundle bundle(path); + CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL()); + if (url.get()) { + if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path, + sizeof(path))) { + file.SetFile(path, false); + return true; } + } } + } #endif return false; } -static void * -AcceptPIDFromInferior (void *arg) -{ - const char *connect_url = (const char *)arg; - ConnectionFileDescriptor file_conn; - Error error; - if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) - { - char pid_str[256]; - ::memset (pid_str, 0, sizeof(pid_str)); - ConnectionStatus status; - const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); - if (pid_str_len > 0) - { - int pid = atoi (pid_str); - return (void *)(intptr_t)pid; - } +static void *AcceptPIDFromInferior(void *arg) { + const char *connect_url = (const char *)arg; + ConnectionFileDescriptor file_conn; + Error error; + if (file_conn.Connect(connect_url, &error) == eConnectionStatusSuccess) { + char pid_str[256]; + ::memset(pid_str, 0, sizeof(pid_str)); + ConnectionStatus status; + const size_t pid_str_len = + file_conn.Read(pid_str, sizeof(pid_str), 0, status, NULL); + if (pid_str_len > 0) { + int pid = atoi(pid_str); + return (void *)(intptr_t)pid; } - return NULL; + } + return NULL; } -static bool -WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) -{ - const int time_delta_usecs = 100000; - const int num_retries = timeout_in_seconds/time_delta_usecs; - for (int i=0; i<num_retries; i++) - { - struct proc_bsdinfo bsd_info; - int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, - (uint64_t) 0, - &bsd_info, - PROC_PIDTBSDINFO_SIZE); - - switch (error) - { - case EINVAL: - case ENOTSUP: - case ESRCH: - case EPERM: - return false; - - default: - break; - - case 0: - if (bsd_info.pbi_status == SSTOP) - return true; - } - ::usleep (time_delta_usecs); +static bool WaitForProcessToSIGSTOP(const lldb::pid_t pid, + const int timeout_in_seconds) { + const int time_delta_usecs = 100000; + const int num_retries = timeout_in_seconds / time_delta_usecs; + for (int i = 0; i < num_retries; i++) { + struct proc_bsdinfo bsd_info; + int error = ::proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &bsd_info, + PROC_PIDTBSDINFO_SIZE); + + switch (error) { + case EINVAL: + case ENOTSUP: + case ESRCH: + case EPERM: + return false; + + default: + break; + + case 0: + if (bsd_info.pbi_status == SSTOP) + return true; } - return false; + ::usleep(time_delta_usecs); + } + return false; } #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) -//static lldb::pid_t -//LaunchInNewTerminalWithCommandFile +// static lldb::pid_t +// LaunchInNewTerminalWithCommandFile //( -// const char **argv, +// const char **argv, // const char **envp, // const char *working_dir, // const ArchSpec *arch_spec, @@ -216,18 +198,19 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // 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()); -// +// ::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; // @@ -236,15 +219,17 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // ::strlcat (temp_file_path, ".command", sizeof (temp_file_path)); // // StreamFile command_file; -// command_file.GetFile().Open (temp_file_path, -// File::eOpenOptionWrite | File::eOpenOptionCanCreate, +// 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)) +// if (!HostInfo::GetLLDBPath (ePathTypeSupportExecutableDir, +// darwin_debug_file_spec)) // return LLDB_INVALID_PROCESS_ID; // darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); // @@ -296,7 +281,8 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // 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); +// cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), +// can_create); // } // } // } @@ -307,7 +293,8 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // app_params.argv = NULL; // app_params.environment = (CFDictionaryRef)cf_env_dict.get(); // -// CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL, +// CFCReleaser<CFURLRef> command_file_url +// (::CFURLCreateFromFileSystemRepresentation (NULL, // (const UInt8 *)temp_file_path, // strlen(temp_file_path), // false)); @@ -325,28 +312,33 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // Error 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()); +// ::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(), +// 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); +// 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 (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 +// // for the process status to be set to SSTOP which indicates +// it it // // SIGSTOP'ed at the entry point // WaitForProcessToSIGSTOP (pid, 5); // } @@ -360,12 +352,10 @@ WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) // return pid; //} -const char *applscript_in_new_tty = -"tell application \"Terminal\"\n" -" activate\n" -" do script \"%s\"\n" -"end tell\n"; - +const char *applscript_in_new_tty = "tell application \"Terminal\"\n" + " activate\n" + " do script \"%s\"\n" + "end tell\n"; const char *applscript_in_existing_tty = "\ set the_shell_script to \"%s\"\n\ @@ -386,1202 +376,1128 @@ tell application \"Terminal\"\n\ do script the_shell_script\n\ end tell\n"; - static Error -LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &launch_info) -{ - Error error; - char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; - if (::mktemp (unix_socket_name) == NULL) - { - error.SetErrorString ("failed to make temporary path for a unix socket"); - return error; - } - - StreamString command; - FileSpec darwin_debug_file_spec; - if (!HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, darwin_debug_file_spec)) - { - error.SetErrorString ("can't locate the 'darwin-debug' executable"); - return error; - } - - darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); - - if (!darwin_debug_file_spec.Exists()) - { - error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at '%s'", - darwin_debug_file_spec.GetPath().c_str()); - return error; - } - - char launcher_path[PATH_MAX]; - darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); - - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - // Only set the architecture if it is valid and if it isn't Haswell (x86_64h). - if (arch_spec.IsValid() && arch_spec.GetCore() != ArchSpec::eCore_x86_64_x86_64h) - command.Printf("arch -arch %s ", arch_spec.GetArchitectureName()); +LaunchInNewTerminalWithAppleScript(const char *exe_path, + ProcessLaunchInfo &launch_info) { + Error error; + char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; + if (::mktemp(unix_socket_name) == NULL) { + error.SetErrorString("failed to make temporary path for a unix socket"); + return error; + } - command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name); + StreamString command; + FileSpec darwin_debug_file_spec; + if (!HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, + darwin_debug_file_spec)) { + error.SetErrorString("can't locate the 'darwin-debug' executable"); + return error; + } - if (arch_spec.IsValid()) - command.Printf(" --arch=%s", arch_spec.GetArchitectureName()); + darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir) - command.Printf(" --working-dir '%s'", working_dir.GetCString()); - else - { - char cwd[PATH_MAX]; - if (getcwd(cwd, PATH_MAX)) - command.Printf(" --working-dir '%s'", cwd); - } - - if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) - 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); - - 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); - } + if (!darwin_debug_file_spec.Exists()) { + error.SetErrorStringWithFormat( + "the 'darwin-debug' executable doesn't exists at '%s'", + darwin_debug_file_spec.GetPath().c_str()); + return error; + } + + char launcher_path[PATH_MAX]; + darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); + + const ArchSpec &arch_spec = launch_info.GetArchitecture(); + // Only set the architecture if it is valid and if it isn't Haswell (x86_64h). + if (arch_spec.IsValid() && + arch_spec.GetCore() != ArchSpec::eCore_x86_64_x86_64h) + command.Printf("arch -arch %s ", arch_spec.GetArchitectureName()); + + command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name); + + if (arch_spec.IsValid()) + command.Printf(" --arch=%s", arch_spec.GetArchitectureName()); + + FileSpec working_dir{launch_info.GetWorkingDirectory()}; + if (working_dir) + command.Printf(" --working-dir '%s'", working_dir.GetCString()); + else { + char cwd[PATH_MAX]; + if (getcwd(cwd, PATH_MAX)) + command.Printf(" --working-dir '%s'", cwd); + } + + if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) + 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); + + 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); + } } + } - command.PutCString(" -- "); - - const char **argv = launch_info.GetArguments().GetConstArgumentVector (); - if (argv) - { - for (size_t i=0; argv[i] != NULL; ++i) - { - if (i==0) - command.Printf(" '%s'", exe_path); - else - command.Printf(" '%s'", argv[i]); - } - } - else - { - command.Printf(" '%s'", exe_path); - } - command.PutCString (" ; echo Process exited with status $?"); - if (launch_info.GetFlags().Test(lldb::eLaunchFlagCloseTTYOnExit)) - command.PutCString (" ; exit"); - - StreamString applescript_source; - - const char *tty_command = command.GetString().c_str(); -// 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, - tty_command); -// } + command.PutCString(" -- "); - - - const char *script_source = applescript_source.GetString().c_str(); - //puts (script_source); - NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]]; - - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - - Error lldb_error; - // Sleep and wait a bit for debugserver to start to listen... - ConnectionFileDescriptor file_conn; - char connect_url[128]; - ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); - - // Spawn a new thread to accept incoming connection on the connect_url - // so we can grab the pid from the inferior. We have to do this because we - // are sending an AppleScript that will launch a process in Terminal.app, - // in a shell and the shell will fork/exec a couple of times before we get - // to the process that we wanted to launch. So when our process actually - // gets launched, we will handshake with it and get the process ID for it. - HostThread accept_thread = ThreadLauncher::LaunchThread(unix_socket_name, AcceptPIDFromInferior, connect_url, &lldb_error); - - [applescript executeAndReturnError:nil]; - - thread_result_t accept_thread_result = NULL; - lldb_error = accept_thread.Join(&accept_thread_result); - if (lldb_error.Success() && accept_thread_result) - { - pid = (intptr_t)accept_thread_result; - - // Wait for process to be stopped at 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); + const char **argv = launch_info.GetArguments().GetConstArgumentVector(); + if (argv) { + for (size_t i = 0; argv[i] != NULL; ++i) { + if (i == 0) + command.Printf(" '%s'", exe_path); + else + command.Printf(" '%s'", argv[i]); } - - FileSystem::Unlink(FileSpec{unix_socket_name, false}); - [applescript release]; - if (pid != LLDB_INVALID_PROCESS_ID) - launch_info.SetProcessID (pid); - return error; + } else { + command.Printf(" '%s'", exe_path); + } + command.PutCString(" ; echo Process exited with status $?"); + if (launch_info.GetFlags().Test(lldb::eLaunchFlagCloseTTYOnExit)) + command.PutCString(" ; exit"); + + StreamString applescript_source; + + const char *tty_command = command.GetString().c_str(); + // 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, tty_command); + // } + + const char *script_source = applescript_source.GetString().c_str(); + // puts (script_source); + NSAppleScript *applescript = [[NSAppleScript alloc] + initWithSource:[NSString stringWithCString:script_source + encoding:NSUTF8StringEncoding]]; + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + Error lldb_error; + // Sleep and wait a bit for debugserver to start to listen... + ConnectionFileDescriptor file_conn; + char connect_url[128]; + ::snprintf(connect_url, sizeof(connect_url), "unix-accept://%s", + unix_socket_name); + + // Spawn a new thread to accept incoming connection on the connect_url + // so we can grab the pid from the inferior. We have to do this because we + // are sending an AppleScript that will launch a process in Terminal.app, + // in a shell and the shell will fork/exec a couple of times before we get + // to the process that we wanted to launch. So when our process actually + // gets launched, we will handshake with it and get the process ID for it. + HostThread accept_thread = ThreadLauncher::LaunchThread( + unix_socket_name, AcceptPIDFromInferior, connect_url, &lldb_error); + + [applescript executeAndReturnError:nil]; + + thread_result_t accept_thread_result = NULL; + lldb_error = accept_thread.Join(&accept_thread_result); + if (lldb_error.Success() && accept_thread_result) { + pid = (intptr_t)accept_thread_result; + + // Wait for process to be stopped at 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); + } + + FileSystem::Unlink(FileSpec{unix_socket_name, false}); + [applescript release]; + if (pid != LLDB_INVALID_PROCESS_ID) + launch_info.SetProcessID(pid); + return error; } #endif // #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) - // On MacOSX CrashReporter will display a string for each shared library if // the shared library has an exported symbol named "__crashreporter_info__". -static std::mutex & -GetCrashReporterMutex() -{ - static std::mutex g_mutex; - return g_mutex; +static std::mutex &GetCrashReporterMutex() { + static std::mutex g_mutex; + return g_mutex; } extern "C" { - const char *__crashreporter_info__ = NULL; +const char *__crashreporter_info__ = NULL; } asm(".desc ___crashreporter_info__, 0x10"); -void -Host::SetCrashDescriptionWithFormat (const char *format, ...) -{ - static StreamString g_crash_description; - std::lock_guard<std::mutex> guard(GetCrashReporterMutex()); - - if (format) - { - va_list args; - va_start (args, format); - g_crash_description.GetString().clear(); - g_crash_description.PrintfVarArg(format, args); - va_end (args); - __crashreporter_info__ = g_crash_description.GetData(); - } - else - { - __crashreporter_info__ = NULL; - } +void Host::SetCrashDescriptionWithFormat(const char *format, ...) { + static StreamString g_crash_description; + std::lock_guard<std::mutex> guard(GetCrashReporterMutex()); + + if (format) { + va_list args; + va_start(args, format); + g_crash_description.GetString().clear(); + g_crash_description.PrintfVarArg(format, args); + va_end(args); + __crashreporter_info__ = g_crash_description.GetData(); + } else { + __crashreporter_info__ = NULL; + } } -void -Host::SetCrashDescription (const char *cstr) -{ - std::lock_guard<std::mutex> guard(GetCrashReporterMutex()); - static std::string g_crash_description; - if (cstr) - { - g_crash_description.assign (cstr); - __crashreporter_info__ = g_crash_description.c_str(); - } - else - { - __crashreporter_info__ = NULL; - } +void Host::SetCrashDescription(const char *cstr) { + std::lock_guard<std::mutex> guard(GetCrashReporterMutex()); + static std::string g_crash_description; + if (cstr) { + g_crash_description.assign(cstr); + __crashreporter_info__ = g_crash_description.c_str(); + } else { + __crashreporter_info__ = NULL; + } } -bool -Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) -{ +bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, + uint32_t line_no) { #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - return false; + return false; #else - // We attach this to an 'odoc' event to specify a particular selection - typedef struct { - int16_t reserved0; // must be zero - int16_t fLineNumber; - int32_t fSelStart; - int32_t fSelEnd; - uint32_t reserved1; // must be zero - uint32_t reserved2; // must be zero - } BabelAESelInfo; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); - char file_path[PATH_MAX]; - file_spec.GetPath(file_path, PATH_MAX); - CFCString file_cfstr (file_path, kCFStringEncodingUTF8); - CFCReleaser<CFURLRef> file_URL (::CFURLCreateWithFileSystemPath (NULL, - file_cfstr.get(), - kCFURLPOSIXPathStyle, - false)); - + // We attach this to an 'odoc' event to specify a particular selection + typedef struct { + int16_t reserved0; // must be zero + int16_t fLineNumber; + int32_t fSelStart; + int32_t fSelEnd; + uint32_t reserved1; // must be zero + uint32_t reserved2; // must be zero + } BabelAESelInfo; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_HOST)); + char file_path[PATH_MAX]; + file_spec.GetPath(file_path, PATH_MAX); + CFCString file_cfstr(file_path, kCFStringEncodingUTF8); + CFCReleaser<CFURLRef> file_URL(::CFURLCreateWithFileSystemPath( + NULL, file_cfstr.get(), kCFURLPOSIXPathStyle, false)); + + if (log) + log->Printf( + "Sending source file: \"%s\" and line: %d to external editor.\n", + file_path, line_no); + + long error; + BabelAESelInfo file_and_line_info = { + 0, // reserved0 + (int16_t)(line_no - 1), // fLineNumber (zero based line number) + 1, // fSelStart + 1024, // fSelEnd + 0, // reserved1 + 0 // reserved2 + }; + + AEKeyDesc file_and_line_desc; + + error = ::AECreateDesc(typeUTF8Text, &file_and_line_info, + sizeof(file_and_line_info), + &(file_and_line_desc.descContent)); + + if (error != noErr) { if (log) - log->Printf("Sending source file: \"%s\" and line: %d to external editor.\n", file_path, line_no); - - long error; - BabelAESelInfo file_and_line_info = - { - 0, // reserved0 - (int16_t)(line_no - 1), // fLineNumber (zero based line number) - 1, // fSelStart - 1024, // fSelEnd - 0, // reserved1 - 0 // reserved2 - }; + log->Printf("Error creating AEDesc: %ld.\n", error); + return false; + } + + file_and_line_desc.descKey = keyAEPosition; + + static std::string g_app_name; + static FSRef g_app_fsref; + + LSApplicationParameters app_params; + ::memset(&app_params, 0, sizeof(app_params)); + app_params.flags = + kLSLaunchDefaults | kLSLaunchDontAddToRecents | kLSLaunchDontSwitch; + + char *external_editor = ::getenv("LLDB_EXTERNAL_EDITOR"); + + if (external_editor) { + if (log) + log->Printf("Looking for external editor \"%s\".\n", external_editor); - AEKeyDesc file_and_line_desc; - - error = ::AECreateDesc (typeUTF8Text, - &file_and_line_info, - sizeof (file_and_line_info), - &(file_and_line_desc.descContent)); - - if (error != noErr) - { + if (g_app_name.empty() || + strcmp(g_app_name.c_str(), external_editor) != 0) { + CFCString editor_name(external_editor, kCFStringEncodingUTF8); + error = ::LSFindApplicationForInfo(kLSUnknownCreator, NULL, + editor_name.get(), &g_app_fsref, NULL); + + // If we found the app, then store away the name so we don't have to + // re-look it up. + if (error != noErr) { if (log) - log->Printf("Error creating AEDesc: %ld.\n", error); + log->Printf( + "Could not find External Editor application, error: %ld.\n", + error); return false; + } } - - file_and_line_desc.descKey = keyAEPosition; - - static std::string g_app_name; - static FSRef g_app_fsref; - - LSApplicationParameters app_params; - ::memset (&app_params, 0, sizeof (app_params)); - app_params.flags = kLSLaunchDefaults | - kLSLaunchDontAddToRecents | - kLSLaunchDontSwitch; - - char *external_editor = ::getenv ("LLDB_EXTERNAL_EDITOR"); - - if (external_editor) - { - if (log) - log->Printf("Looking for external editor \"%s\".\n", external_editor); - - if (g_app_name.empty() || strcmp (g_app_name.c_str(), external_editor) != 0) - { - CFCString editor_name (external_editor, kCFStringEncodingUTF8); - error = ::LSFindApplicationForInfo (kLSUnknownCreator, - NULL, - editor_name.get(), - &g_app_fsref, - NULL); - - // If we found the app, then store away the name so we don't have to re-look it up. - if (error != noErr) - { - if (log) - log->Printf("Could not find External Editor application, error: %ld.\n", error); - return false; - } - - } - app_params.application = &g_app_fsref; - } + app_params.application = &g_app_fsref; + } - ProcessSerialNumber psn; - CFCReleaser<CFArrayRef> file_array(CFArrayCreate (NULL, (const void **) file_URL.ptr_address(false), 1, NULL)); - error = ::LSOpenURLsWithRole (file_array.get(), - kLSRolesAll, - &file_and_line_desc, - &app_params, - &psn, - 1); - - AEDisposeDesc (&(file_and_line_desc.descContent)); - - if (error != noErr) - { - if (log) - log->Printf("LSOpenURLsWithRole failed, error: %ld.\n", error); + ProcessSerialNumber psn; + CFCReleaser<CFArrayRef> file_array( + CFArrayCreate(NULL, (const void **)file_URL.ptr_address(false), 1, NULL)); + error = ::LSOpenURLsWithRole(file_array.get(), kLSRolesAll, + &file_and_line_desc, &app_params, &psn, 1); - return false; - } + AEDisposeDesc(&(file_and_line_desc.descContent)); - return true; + if (error != noErr) { + if (log) + log->Printf("LSOpenURLsWithRole failed, error: %ld.\n", error); + + return false; + } + + return true; #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; - +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; } -static bool -GetMacOSXProcessCPUType (ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - // Make a new mib to stay thread safe - int mib[CTL_MAXNAME]={0,}; - size_t mib_len = CTL_MAXNAME; - if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len)) - return false; - - mib[mib_len] = process_info.GetProcessID(); - mib_len++; - - cpu_type_t cpu, sub = 0; - size_t len = sizeof(cpu); - if (::sysctl (mib, mib_len, &cpu, &len, 0, 0) == 0) - { - switch (cpu) - { - case CPU_TYPE_I386: sub = CPU_SUBTYPE_I386_ALL; break; - case CPU_TYPE_X86_64: sub = CPU_SUBTYPE_X86_64_ALL; break; - -#if defined (CPU_TYPE_ARM64) && defined (CPU_SUBTYPE_ARM64_ALL) - case CPU_TYPE_ARM64: sub = CPU_SUBTYPE_ARM64_ALL; break; +static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + // Make a new mib to stay thread safe + int mib[CTL_MAXNAME] = { + 0, + }; + size_t mib_len = CTL_MAXNAME; + if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len)) + return false; + + mib[mib_len] = process_info.GetProcessID(); + mib_len++; + + cpu_type_t cpu, sub = 0; + size_t len = sizeof(cpu); + if (::sysctl(mib, mib_len, &cpu, &len, 0, 0) == 0) { + switch (cpu) { + case CPU_TYPE_I386: + sub = CPU_SUBTYPE_I386_ALL; + break; + case CPU_TYPE_X86_64: + sub = CPU_SUBTYPE_X86_64_ALL; + break; + +#if defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64_ALL) + case CPU_TYPE_ARM64: + sub = CPU_SUBTYPE_ARM64_ALL; + break; #endif - case CPU_TYPE_ARM: - { - // Note that we fetched the cpu type from the PROCESS but we can't get a cpusubtype of the - // process -- we can only get the host's cpu subtype. - uint32_t cpusubtype = 0; - len = sizeof(cpusubtype); - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) - sub = cpusubtype; - - bool host_cpu_is_64bit; - uint32_t is64bit_capable; - size_t is64bit_capable_len = sizeof (is64bit_capable); - if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, &is64bit_capable_len, NULL, 0) == 0) - host_cpu_is_64bit = true; - else - host_cpu_is_64bit = false; - - // if the host is an armv8 device, its cpusubtype will be in CPU_SUBTYPE_ARM64 numbering - // and we need to rewrite it to a reasonable CPU_SUBTYPE_ARM value instead. - - if (host_cpu_is_64bit) - { - sub = CPU_SUBTYPE_ARM_V7; - } - } - break; - - default: - break; - } - process_info.GetArchitecture ().SetArchitecture (eArchTypeMachO, cpu, sub); - return true; + case CPU_TYPE_ARM: { + // Note that we fetched the cpu type from the PROCESS but we can't get a + // cpusubtype of the + // process -- we can only get the host's cpu subtype. + uint32_t cpusubtype = 0; + len = sizeof(cpusubtype); + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) + sub = cpusubtype; + + bool host_cpu_is_64bit; + uint32_t is64bit_capable; + size_t is64bit_capable_len = sizeof(is64bit_capable); + if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, + &is64bit_capable_len, NULL, 0) == 0) + host_cpu_is_64bit = true; + else + host_cpu_is_64bit = false; + + // if the host is an armv8 device, its cpusubtype will be in + // CPU_SUBTYPE_ARM64 numbering + // and we need to rewrite it to a reasonable CPU_SUBTYPE_ARM value + // instead. + + if (host_cpu_is_64bit) { + sub = CPU_SUBTYPE_ARM_V7; } + } break; + + default: + break; + } + process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu, sub); + return true; } - process_info.GetArchitecture().Clear(); - return false; + } + process_info.GetArchitecture().Clear(); + return false; } -static bool -GetMacOSXProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, - ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)process_info.GetProcessID() }; - - size_t arg_data_size = 0; - if (::sysctl (proc_args_mib, 3, nullptr, &arg_data_size, NULL, 0) || arg_data_size == 0) - arg_data_size = 8192; - - // Add a few bytes to the calculated length, I know we need to add at least one byte - // to this number otherwise we get junk back, so add 128 just in case... - DataBufferHeap arg_data(arg_data_size+128, 0); - arg_data_size = arg_data.GetByteSize(); - if (::sysctl (proc_args_mib, 3, arg_data.GetBytes(), &arg_data_size , NULL, 0) == 0) - { - DataExtractor data (arg_data.GetBytes(), arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); - lldb::offset_t offset = 0; - uint32_t argc = data.GetU32 (&offset); - llvm::Triple &triple = process_info.GetArchitecture().GetTriple(); - const llvm::Triple::ArchType triple_arch = triple.getArch(); - const bool check_for_ios_simulator = (triple_arch == llvm::Triple::x86 || triple_arch == llvm::Triple::x86_64); - const char *cstr = data.GetCStr (&offset); +static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, + ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, + (int)process_info.GetProcessID()}; + + size_t arg_data_size = 0; + if (::sysctl(proc_args_mib, 3, nullptr, &arg_data_size, NULL, 0) || + arg_data_size == 0) + arg_data_size = 8192; + + // Add a few bytes to the calculated length, I know we need to add at least + // one byte + // to this number otherwise we get junk back, so add 128 just in case... + DataBufferHeap arg_data(arg_data_size + 128, 0); + arg_data_size = arg_data.GetByteSize(); + if (::sysctl(proc_args_mib, 3, arg_data.GetBytes(), &arg_data_size, NULL, + 0) == 0) { + DataExtractor data(arg_data.GetBytes(), arg_data_size, + endian::InlHostByteOrder(), sizeof(void *)); + lldb::offset_t offset = 0; + uint32_t argc = data.GetU32(&offset); + llvm::Triple &triple = process_info.GetArchitecture().GetTriple(); + const llvm::Triple::ArchType triple_arch = triple.getArch(); + const bool check_for_ios_simulator = + (triple_arch == llvm::Triple::x86 || + triple_arch == llvm::Triple::x86_64); + const char *cstr = data.GetCStr(&offset); + if (cstr) { + process_info.GetExecutableFile().SetFile(cstr, false); + + if (match_info_ptr == NULL || + NameMatches( + process_info.GetExecutableFile().GetFilename().GetCString(), + match_info_ptr->GetNameMatchType(), + match_info_ptr->GetProcessInfo().GetName())) { + // Skip NULLs + while (1) { + const uint8_t *p = data.PeekData(offset, 1); + if ((p == NULL) || (*p != '\0')) + break; + ++offset; + } + // Now extract all arguments + Args &proc_args = process_info.GetArguments(); + for (int i = 0; i < static_cast<int>(argc); ++i) { + cstr = data.GetCStr(&offset); if (cstr) - { - process_info.GetExecutableFile().SetFile(cstr, false); - - if (match_info_ptr == NULL || - NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), - match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName())) - { - // Skip NULLs - while (1) - { - const uint8_t *p = data.PeekData(offset, 1); - if ((p == NULL) || (*p != '\0')) - break; - ++offset; - } - // Now extract all arguments - Args &proc_args = process_info.GetArguments(); - for (int i=0; i<static_cast<int>(argc); ++i) - { - cstr = data.GetCStr(&offset); - if (cstr) - proc_args.AppendArgument(cstr); - } - - Args &proc_env = process_info.GetEnvironmentEntries (); - while ((cstr = data.GetCStr(&offset))) - { - if (cstr[0] == '\0') - break; - - if (check_for_ios_simulator) - { - if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0) - process_info.GetArchitecture().GetTriple().setOS(llvm::Triple::IOS); - else - process_info.GetArchitecture().GetTriple().setOS(llvm::Triple::MacOSX); - } - - proc_env.AppendArgument(cstr); - } - return true; - } + proc_args.AppendArgument(cstr); + } + + Args &proc_env = process_info.GetEnvironmentEntries(); + while ((cstr = data.GetCStr(&offset))) { + if (cstr[0] == '\0') + break; + + if (check_for_ios_simulator) { + if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == + 0) + process_info.GetArchitecture().GetTriple().setOS( + llvm::Triple::IOS); + else + process_info.GetArchitecture().GetTriple().setOS( + llvm::Triple::MacOSX); } + + proc_env.AppendArgument(cstr); + } + return true; } + } } - return false; + } + return false; } -static bool -GetMacOSXProcessUserAndGroup (ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - int mib[4]; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = process_info.GetProcessID(); - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size = sizeof(struct kinfo_proc); - - if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) - { - if (proc_kinfo_size > 0) - { - process_info.SetParentProcessID (proc_kinfo.kp_eproc.e_ppid); - process_info.SetUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid); - process_info.SetGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid); - process_info.SetEffectiveUserID (proc_kinfo.kp_eproc.e_ucred.cr_uid); - if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) - process_info.SetEffectiveGroupID (proc_kinfo.kp_eproc.e_ucred.cr_groups[0]); - else - process_info.SetEffectiveGroupID (UINT32_MAX); - return true; - } - } +static bool GetMacOSXProcessUserAndGroup(ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = process_info.GetProcessID(); + struct kinfo_proc proc_kinfo; + size_t proc_kinfo_size = sizeof(struct kinfo_proc); + + if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { + if (proc_kinfo_size > 0) { + process_info.SetParentProcessID(proc_kinfo.kp_eproc.e_ppid); + process_info.SetUserID(proc_kinfo.kp_eproc.e_pcred.p_ruid); + process_info.SetGroupID(proc_kinfo.kp_eproc.e_pcred.p_rgid); + process_info.SetEffectiveUserID(proc_kinfo.kp_eproc.e_ucred.cr_uid); + if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) + process_info.SetEffectiveGroupID( + proc_kinfo.kp_eproc.e_ucred.cr_groups[0]); + else + process_info.SetEffectiveGroupID(UINT32_MAX); + return true; + } } - process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); - process_info.SetUserID (UINT32_MAX); - process_info.SetGroupID (UINT32_MAX); - process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); - return false; + } + process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID); + process_info.SetUserID(UINT32_MAX); + process_info.SetGroupID(UINT32_MAX); + process_info.SetEffectiveUserID(UINT32_MAX); + process_info.SetEffectiveGroupID(UINT32_MAX); + return false; } +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + std::vector<struct kinfo_proc> kinfos; -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - std::vector<struct kinfo_proc> kinfos; - - int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - - size_t pid_data_size = 0; - if (::sysctl (mib, 4, NULL, &pid_data_size, NULL, 0) != 0) - return 0; - - // Add a few extra in case a few more show up - const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; - - kinfos.resize (estimated_pid_count); - pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); - - if (::sysctl (mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0) - return 0; - - const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); - - bool all_users = match_info.GetMatchAllUsers(); - const lldb::pid_t our_pid = getpid(); - const uid_t our_uid = getuid(); - for (size_t i = 0; i < actual_pid_count; i++) - { - const struct kinfo_proc &kinfo = kinfos[i]; - - bool kinfo_user_matches = false; - if (all_users) - kinfo_user_matches = true; - else - kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid; - - // Special case, if lldb is being run as root we can attach to anything. - if (our_uid == 0) - kinfo_user_matches = true; - - if (kinfo_user_matches == false || // Make sure the user is acceptable - static_cast<lldb::pid_t>(kinfo.kp_proc.p_pid) == our_pid || // Skip this process - kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero) - kinfo.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains... - kinfo.kp_proc.p_flag & P_TRACED || // Being debugged? - kinfo.kp_proc.p_flag & P_WEXIT || // Working on exiting? - kinfo.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta) - continue; - - ProcessInstanceInfo process_info; - process_info.SetProcessID (kinfo.kp_proc.p_pid); - process_info.SetParentProcessID (kinfo.kp_eproc.e_ppid); - process_info.SetUserID (kinfo.kp_eproc.e_pcred.p_ruid); - process_info.SetGroupID (kinfo.kp_eproc.e_pcred.p_rgid); - process_info.SetEffectiveUserID (kinfo.kp_eproc.e_ucred.cr_uid); - if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0) - process_info.SetEffectiveGroupID (kinfo.kp_eproc.e_ucred.cr_groups[0]); - else - process_info.SetEffectiveGroupID (UINT32_MAX); - - // Make sure our info matches before we go fetch the name and cpu type - if (match_info.Matches (process_info)) - { - // Get CPU type first so we can know to look for iOS simulator is we have x86 or x86_64 - if (GetMacOSXProcessCPUType (process_info)) - { - if (GetMacOSXProcessArgs (&match_info, process_info)) - { - if (match_info.Matches (process_info)) - process_infos.Append (process_info); - } - } + int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + + size_t pid_data_size = 0; + if (::sysctl(mib, 4, NULL, &pid_data_size, NULL, 0) != 0) + return 0; + + // Add a few extra in case a few more show up + const size_t estimated_pid_count = + (pid_data_size / sizeof(struct kinfo_proc)) + 10; + + kinfos.resize(estimated_pid_count); + pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); + + if (::sysctl(mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0) + return 0; + + const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); + + bool all_users = match_info.GetMatchAllUsers(); + const lldb::pid_t our_pid = getpid(); + const uid_t our_uid = getuid(); + for (size_t i = 0; i < actual_pid_count; i++) { + const struct kinfo_proc &kinfo = kinfos[i]; + + bool kinfo_user_matches = false; + if (all_users) + kinfo_user_matches = true; + else + kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid; + + // Special case, if lldb is being run as root we can attach to anything. + if (our_uid == 0) + kinfo_user_matches = true; + + if (kinfo_user_matches == false || // Make sure the user is acceptable + static_cast<lldb::pid_t>(kinfo.kp_proc.p_pid) == + our_pid || // Skip this process + kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero) + kinfo.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains... + kinfo.kp_proc.p_flag & P_TRACED || // Being debugged? + kinfo.kp_proc.p_flag & P_WEXIT || // Working on exiting? + kinfo.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta) + continue; + + ProcessInstanceInfo process_info; + process_info.SetProcessID(kinfo.kp_proc.p_pid); + process_info.SetParentProcessID(kinfo.kp_eproc.e_ppid); + process_info.SetUserID(kinfo.kp_eproc.e_pcred.p_ruid); + process_info.SetGroupID(kinfo.kp_eproc.e_pcred.p_rgid); + process_info.SetEffectiveUserID(kinfo.kp_eproc.e_ucred.cr_uid); + if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0) + process_info.SetEffectiveGroupID(kinfo.kp_eproc.e_ucred.cr_groups[0]); + else + process_info.SetEffectiveGroupID(UINT32_MAX); + + // Make sure our info matches before we go fetch the name and cpu type + if (match_info.Matches(process_info)) { + // Get CPU type first so we can know to look for iOS simulator is we have + // x86 or x86_64 + if (GetMacOSXProcessCPUType(process_info)) { + if (GetMacOSXProcessArgs(&match_info, process_info)) { + if (match_info.Matches(process_info)) + process_infos.Append(process_info); } - } - return process_infos.GetSize(); + } + } + } + return process_infos.GetSize(); } -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.SetProcessID(pid); - bool success = false; - - // Get CPU type first so we can know to look for iOS simulator is we have x86 or x86_64 - if (GetMacOSXProcessCPUType (process_info)) - success = true; - - if (GetMacOSXProcessArgs (NULL, process_info)) - success = true; - - if (GetMacOSXProcessUserAndGroup (process_info)) - success = true; - - if (success) - return true; - - process_info.Clear(); - return false; +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.SetProcessID(pid); + bool success = false; + + // Get CPU type first so we can know to look for iOS simulator is we have x86 + // or x86_64 + if (GetMacOSXProcessCPUType(process_info)) + success = true; + + if (GetMacOSXProcessArgs(NULL, process_info)) + success = true; + + if (GetMacOSXProcessUserAndGroup(process_info)) + success = true; + + if (success) + return true; + + process_info.Clear(); + return false; } #if !NO_XPC_SERVICES -static void -PackageXPCArguments (xpc_object_t message, const char *prefix, const Args& args) -{ - size_t count = args.GetArgumentCount(); - char buf[50]; // long enough for 'argXXX' +static void PackageXPCArguments(xpc_object_t message, const char *prefix, + const Args &args) { + size_t count = args.GetArgumentCount(); + char buf[50]; // long enough for 'argXXX' + memset(buf, 0, 50); + sprintf(buf, "%sCount", prefix); + xpc_dictionary_set_int64(message, buf, count); + for (size_t i = 0; i < count; i++) { memset(buf, 0, 50); - sprintf(buf, "%sCount", prefix); - xpc_dictionary_set_int64(message, buf, count); - for (size_t i=0; i<count; i++) { - memset(buf, 0, 50); - sprintf(buf, "%s%zi", prefix, i); - xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i)); - } + sprintf(buf, "%s%zi", prefix, i); + xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i)); + } } /* - A valid authorizationRef means that + A valid authorizationRef means that - there is the LaunchUsingXPCRightName rights in the /etc/authorization - we have successfully copied the rights to be send over the XPC wire Once obtained, it will be valid for as long as the process lives. */ static AuthorizationRef authorizationRef = NULL; -static Error -getXPCAuthorization (ProcessLaunchInfo &launch_info) -{ - Error error; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); - - if ((launch_info.GetUserID() == 0) && !authorizationRef) - { - OSStatus createStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); - if (createStatus != errAuthorizationSuccess) - { - error.SetError(1, eErrorTypeGeneric); - error.SetErrorString("Can't create authorizationRef."); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } - return error; - } - - OSStatus rightsStatus = AuthorizationRightGet(LaunchUsingXPCRightName, NULL); - if (rightsStatus != errAuthorizationSuccess) - { - // No rights in the security database, Create it with the right prompt. - CFStringRef prompt = CFSTR("Xcode is trying to take control of a root process."); - CFStringRef keys[] = { CFSTR("en") }; - CFTypeRef values[] = { prompt }; - CFDictionaryRef promptDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef keys1[] = { CFSTR("class"), CFSTR("group"), CFSTR("comment"), CFSTR("default-prompt"), CFSTR("shared") }; - CFTypeRef values1[] = { CFSTR("user"), CFSTR("admin"), CFSTR(LaunchUsingXPCRightName), promptDict, kCFBooleanFalse }; - CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - rightsStatus = AuthorizationRightSet(authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL); - CFRelease(promptDict); - CFRelease(dict); - } - - OSStatus copyRightStatus = errAuthorizationDenied; - if (rightsStatus == errAuthorizationSuccess) - { - AuthorizationItem item1 = { LaunchUsingXPCRightName, 0, NULL, 0 }; - AuthorizationItem items[] = {item1}; - AuthorizationRights requestedRights = {1, items }; - AuthorizationFlags authorizationFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; - copyRightStatus = AuthorizationCopyRights(authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment, authorizationFlags, NULL); - } - - if (copyRightStatus != errAuthorizationSuccess) - { - // Eventually when the commandline supports running as root and the user is not - // logged in in the current audit session, we will need the trick in gdb where - // we ask the user to type in the root passwd in the terminal. - error.SetError(2, eErrorTypeGeneric); - error.SetErrorStringWithFormat("Launching as root needs root authorization."); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } - - if (authorizationRef) - { - AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); - authorizationRef = NULL; - } - } +static Error getXPCAuthorization(ProcessLaunchInfo &launch_info) { + Error error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); + + if ((launch_info.GetUserID() == 0) && !authorizationRef) { + OSStatus createStatus = + AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, + kAuthorizationFlagDefaults, &authorizationRef); + if (createStatus != errAuthorizationSuccess) { + error.SetError(1, eErrorTypeGeneric); + error.SetErrorString("Can't create authorizationRef."); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); + } + return error; } - return error; + OSStatus rightsStatus = + AuthorizationRightGet(LaunchUsingXPCRightName, NULL); + if (rightsStatus != errAuthorizationSuccess) { + // No rights in the security database, Create it with the right prompt. + CFStringRef prompt = + CFSTR("Xcode is trying to take control of a root process."); + CFStringRef keys[] = {CFSTR("en")}; + CFTypeRef values[] = {prompt}; + CFDictionaryRef promptDict = CFDictionaryCreate( + kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFStringRef keys1[] = {CFSTR("class"), CFSTR("group"), CFSTR("comment"), + CFSTR("default-prompt"), CFSTR("shared")}; + CFTypeRef values1[] = {CFSTR("user"), CFSTR("admin"), + CFSTR(LaunchUsingXPCRightName), promptDict, + kCFBooleanFalse}; + CFDictionaryRef dict = CFDictionaryCreate( + kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + rightsStatus = AuthorizationRightSet( + authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL); + CFRelease(promptDict); + CFRelease(dict); + } + + OSStatus copyRightStatus = errAuthorizationDenied; + if (rightsStatus == errAuthorizationSuccess) { + AuthorizationItem item1 = {LaunchUsingXPCRightName, 0, NULL, 0}; + AuthorizationItem items[] = {item1}; + AuthorizationRights requestedRights = {1, items}; + AuthorizationFlags authorizationFlags = + kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; + copyRightStatus = AuthorizationCopyRights( + authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment, + authorizationFlags, NULL); + } + + if (copyRightStatus != errAuthorizationSuccess) { + // Eventually when the commandline supports running as root and the user + // is not + // logged in in the current audit session, we will need the trick in gdb + // where + // we ask the user to type in the root passwd in the terminal. + error.SetError(2, eErrorTypeGeneric); + error.SetErrorStringWithFormat( + "Launching as root needs root authorization."); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); + } + + if (authorizationRef) { + AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); + authorizationRef = NULL; + } + } + } + + return error; } #endif -static Error -LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid) -{ +static Error LaunchProcessXPC(const char *exe_path, + ProcessLaunchInfo &launch_info, + lldb::pid_t &pid) { #if !NO_XPC_SERVICES - Error error = getXPCAuthorization(launch_info); - if (error.Fail()) - return error; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); - - uid_t requested_uid = launch_info.GetUserID(); - const char *xpc_service = nil; - bool send_auth = false; - AuthorizationExternalForm extForm; - if (requested_uid == 0) - { - if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == errAuthorizationSuccess) - { - send_auth = true; - } - else - { - error.SetError(3, eErrorTypeGeneric); - error.SetErrorStringWithFormat("Launching root via XPC needs to externalize authorization reference."); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } - return error; - } - xpc_service = LaunchUsingXPCRightName; - } - else - { - error.SetError(4, eErrorTypeGeneric); - error.SetErrorStringWithFormat("Launching via XPC is only currently available for root."); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } - return error; - } - - xpc_connection_t conn = xpc_connection_create(xpc_service, NULL); - - xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { - xpc_type_t type = xpc_get_type(event); - - if (type == XPC_TYPE_ERROR) { - if (event == XPC_ERROR_CONNECTION_INTERRUPTED) { - // The service has either canceled itself, crashed, or been terminated. - // The XPC connection is still valid and sending a message to it will re-launch the service. - // If the service is state-full, this is the time to initialize the new service. - return; - } else if (event == XPC_ERROR_CONNECTION_INVALID) { - // The service is invalid. Either the service name supplied to xpc_connection_create() is incorrect - // or we (this process) have canceled the service; we can do any cleanup of application state at this point. - // printf("Service disconnected"); - return; - } else { - // printf("Unexpected error from service: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); - } - - } else { - // printf("Received unexpected event in handler"); - } - }); - - xpc_connection_set_finalizer_f (conn, xpc_finalizer_t(xpc_release)); - xpc_connection_resume (conn); - xpc_object_t message = xpc_dictionary_create (nil, nil, 0); - - if (send_auth) - { - xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, sizeof(AuthorizationExternalForm)); - } - - PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments()); - PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, launch_info.GetEnvironmentEntries()); - - // Posix spawn stuff. - xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType()); - xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, Host::GetPosixspawnFlags(launch_info)); - const FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO); - if (file_action && file_action->GetPath()) - { - xpc_dictionary_set_string(message, LauncherXPCServiceStdInPathKeyKey, file_action->GetPath()); + Error error = getXPCAuthorization(launch_info); + if (error.Fail()) + return error; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); + + uid_t requested_uid = launch_info.GetUserID(); + const char *xpc_service = nil; + bool send_auth = false; + AuthorizationExternalForm extForm; + if (requested_uid == 0) { + if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == + errAuthorizationSuccess) { + send_auth = true; + } else { + error.SetError(3, eErrorTypeGeneric); + error.SetErrorStringWithFormat("Launching root via XPC needs to " + "externalize authorization reference."); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); + } + return error; } - file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); - if (file_action && file_action->GetPath()) - { - xpc_dictionary_set_string(message, LauncherXPCServiceStdOutPathKeyKey, file_action->GetPath()); + xpc_service = LaunchUsingXPCRightName; + } else { + error.SetError(4, eErrorTypeGeneric); + error.SetErrorStringWithFormat( + "Launching via XPC is only currently available for root."); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); } - file_action = launch_info.GetFileActionForFD(STDERR_FILENO); - if (file_action && file_action->GetPath()) - { - xpc_dictionary_set_string(message, LauncherXPCServiceStdErrPathKeyKey, file_action->GetPath()); + return error; + } + + xpc_connection_t conn = xpc_connection_create(xpc_service, NULL); + + xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { + xpc_type_t type = xpc_get_type(event); + + if (type == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INTERRUPTED) { + // The service has either canceled itself, crashed, or been terminated. + // The XPC connection is still valid and sending a message to it will + // re-launch the service. + // If the service is state-full, this is the time to initialize the new + // service. + return; + } else if (event == XPC_ERROR_CONNECTION_INVALID) { + // The service is invalid. Either the service name supplied to + // xpc_connection_create() is incorrect + // or we (this process) have canceled the service; we can do any cleanup + // of application state at this point. + // printf("Service disconnected"); + return; + } else { + // printf("Unexpected error from service: %s", + // xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } + + } else { + // printf("Received unexpected event in handler"); } - - xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message); - xpc_type_t returnType = xpc_get_type(reply); - if (returnType == XPC_TYPE_DICTIONARY) - { - pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey); - if (pid == 0) - { - int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey); - int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey); - - error.SetError(errorCode, eErrorTypeGeneric); - error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } - - if (authorizationRef) - { - AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); - authorizationRef = NULL; - } - } + }); + + xpc_connection_set_finalizer_f(conn, xpc_finalizer_t(xpc_release)); + xpc_connection_resume(conn); + xpc_object_t message = xpc_dictionary_create(nil, nil, 0); + + if (send_auth) { + xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, + sizeof(AuthorizationExternalForm)); + } + + PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, + launch_info.GetArguments()); + PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, + launch_info.GetEnvironmentEntries()); + + // Posix spawn stuff. + xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, + launch_info.GetArchitecture().GetMachOCPUType()); + xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, + Host::GetPosixspawnFlags(launch_info)); + const FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO); + if (file_action && file_action->GetPath()) { + xpc_dictionary_set_string(message, LauncherXPCServiceStdInPathKeyKey, + file_action->GetPath()); + } + file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); + if (file_action && file_action->GetPath()) { + xpc_dictionary_set_string(message, LauncherXPCServiceStdOutPathKeyKey, + file_action->GetPath()); + } + file_action = launch_info.GetFileActionForFD(STDERR_FILENO); + if (file_action && file_action->GetPath()) { + xpc_dictionary_set_string(message, LauncherXPCServiceStdErrPathKeyKey, + file_action->GetPath()); + } + + xpc_object_t reply = + xpc_connection_send_message_with_reply_sync(conn, message); + xpc_type_t returnType = xpc_get_type(reply); + if (returnType == XPC_TYPE_DICTIONARY) { + pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey); + if (pid == 0) { + int errorType = + xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey); + int errorCode = + xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey); + + error.SetError(errorCode, eErrorTypeGeneric); + error.SetErrorStringWithFormat( + "Problems with launching via XPC. Error type : %i, code : %i", + errorType, errorCode); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); + } + + if (authorizationRef) { + AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); + authorizationRef = NULL; + } } - else if (returnType == XPC_TYPE_ERROR) - { - error.SetError(5, eErrorTypeGeneric); - error.SetErrorStringWithFormat("Problems with launching via XPC. XPC error : %s", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); - if (log) - { - error.PutToLog(log, "%s", error.AsCString()); - } + } else if (returnType == XPC_TYPE_ERROR) { + error.SetError(5, eErrorTypeGeneric); + error.SetErrorStringWithFormat( + "Problems with launching via XPC. XPC error : %s", + xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); + if (log) { + error.PutToLog(log, "%s", error.AsCString()); } - - return error; + } + + return error; #else - Error error; - return error; + Error error; + return error; #endif } -static bool -ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) -{ - bool result = false; - -#if !NO_XPC_SERVICES - bool launchingAsRoot = launch_info.GetUserID() == 0; - bool currentUserIsRoot = HostInfo::GetEffectiveUserID() == 0; - - if (launchingAsRoot && !currentUserIsRoot) - { - // If current user is already root, we don't need XPC's help. - result = true; - } +static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) { + bool result = false; + +#if !NO_XPC_SERVICES + bool launchingAsRoot = launch_info.GetUserID() == 0; + bool currentUserIsRoot = HostInfo::GetEffectiveUserID() == 0; + + if (launchingAsRoot && !currentUserIsRoot) { + // If current user is already root, we don't need XPC's help. + result = true; + } #endif - - return result; + + return result; } -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - Error error; - char exe_path[PATH_MAX]; - PlatformSP host_platform_sp (Platform::GetHostPlatform ()); - - ModuleSpec exe_module_spec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()); - - FileSpec::FileType file_type = exe_module_spec.GetFileSpec().GetFileType(); - if (file_type != FileSpec::eFileTypeRegular) - { - lldb::ModuleSP exe_module_sp; - error = host_platform_sp->ResolveExecutable (exe_module_spec, - exe_module_sp, - NULL); - - if (error.Fail()) - return error; - - if (exe_module_sp) - exe_module_spec.GetFileSpec() = exe_module_sp->GetFileSpec(); +Error Host::LaunchProcess(ProcessLaunchInfo &launch_info) { + Error error; + char exe_path[PATH_MAX]; + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + + ModuleSpec exe_module_spec(launch_info.GetExecutableFile(), + launch_info.GetArchitecture()); + + FileSpec::FileType file_type = exe_module_spec.GetFileSpec().GetFileType(); + if (file_type != FileSpec::eFileTypeRegular) { + lldb::ModuleSP exe_module_sp; + error = host_platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, + NULL); + + if (error.Fail()) + return error; + + if (exe_module_sp) + exe_module_spec.GetFileSpec() = exe_module_sp->GetFileSpec(); + } + + 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); + return error; + } + + if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) { +#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) + return LaunchInNewTerminalWithAppleScript(exe_path, launch_info); +#else + error.SetErrorString("launching a process in a new terminal is not " + "supported on iOS devices"); + return error; +#endif + } + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + if (ShouldLaunchUsingXPC(launch_info)) { + error = LaunchProcessXPC(exe_path, launch_info, pid); + } else { + error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); + } + + if (pid != LLDB_INVALID_PROCESS_ID) { + // If all went well, then set the process ID into the 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); } - - if (exe_module_spec.GetFileSpec().Exists()) - { - exe_module_spec.GetFileSpec().GetPath (exe_path, sizeof(exe_path)); + } else { + // Invalid process ID, something didn't go well + if (error.Success()) + error.SetErrorString("process launch failed for unknown reasons"); + } + return error; +} + +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + Error error; + if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { + FileSpec expand_tool_spec; + if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, + expand_tool_spec)) { + error.SetErrorString( + "could not get support executable directory for lldb-argdumper tool"); + return error; } - else - { - launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); - return error; + expand_tool_spec.AppendPathComponent("lldb-argdumper"); + if (!expand_tool_spec.Exists()) { + error.SetErrorStringWithFormat( + "could not find the lldb-argdumper tool: %s", + expand_tool_spec.GetPath().c_str()); + return error; } - - if (launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) - { -#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) - return LaunchInNewTerminalWithAppleScript (exe_path, launch_info); -#else - error.SetErrorString ("launching a process in a new terminal is not supported on iOS devices"); + + StreamString expand_tool_spec_stream; + expand_tool_spec_stream.Printf("\"%s\"", + expand_tool_spec.GetPath().c_str()); + + Args expand_command(expand_tool_spec_stream.GetData()); + expand_command.AppendArguments(launch_info.GetArguments()); + + int status; + std::string output; + FileSpec cwd(launch_info.GetWorkingDirectory()); + if (!cwd.Exists()) { + char *wd = getcwd(nullptr, 0); + if (wd == nullptr) { + error.SetErrorStringWithFormat( + "cwd does not exist; cannot launch with shell argument expansion"); return error; -#endif + } else { + FileSpec working_dir(wd, false); + free(wd); + launch_info.SetWorkingDirectory(working_dir); + } } + RunShellCommand(expand_command, cwd, &status, nullptr, &output, 10); - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + if (status != 0) { + error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", + status); + return error; + } - if (ShouldLaunchUsingXPC(launch_info)) - { - error = LaunchProcessXPC(exe_path, launch_info, pid); + auto data_sp = StructuredData::ParseJSON(output); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; } - else - { - error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); + + auto dict_sp = data_sp->GetAsDictionary(); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; } - - if (pid != LLDB_INVALID_PROCESS_ID) - { - // If all went well, then set the process ID into the 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); - } + + auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); + if (!args_sp) { + error.SetErrorString("invalid JSON"); + return error; } - else - { - // Invalid process ID, something didn't go well - if (error.Success()) - error.SetErrorString ("process launch failed for unknown reasons"); + + auto args_array_sp = args_sp->GetAsArray(); + if (!args_array_sp) { + error.SetErrorString("invalid JSON"); + return error; } - return error; -} -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - Error error; - if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) - { - FileSpec expand_tool_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec)) - { - error.SetErrorString("could not get support executable directory for lldb-argdumper tool"); - return error; - } - expand_tool_spec.AppendPathComponent("lldb-argdumper"); - if (!expand_tool_spec.Exists()) - { - error.SetErrorStringWithFormat("could not find the lldb-argdumper tool: %s", expand_tool_spec.GetPath().c_str()); - return error; - } - - StreamString expand_tool_spec_stream; - expand_tool_spec_stream.Printf("\"%s\"",expand_tool_spec.GetPath().c_str()); - - Args expand_command(expand_tool_spec_stream.GetData()); - expand_command.AppendArguments (launch_info.GetArguments()); - - int status; - std::string output; - FileSpec cwd(launch_info.GetWorkingDirectory()); - if (!cwd.Exists()) - { - char *wd = getcwd(nullptr, 0); - if (wd == nullptr) - { - error.SetErrorStringWithFormat("cwd does not exist; cannot launch with shell argument expansion"); - return error; - } - else - { - FileSpec working_dir(wd, false); - free(wd); - launch_info.SetWorkingDirectory(working_dir); + launch_info.GetArguments().Clear(); - } - } - RunShellCommand(expand_command, cwd, &status, nullptr, &output, 10); - - if (status != 0) - { - error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", status); - return error; - } - - auto data_sp = StructuredData::ParseJSON(output); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto dict_sp = data_sp->GetAsDictionary(); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); - if (!args_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } + for (size_t i = 0; i < args_array_sp->GetSize(); i++) { + auto item_sp = args_array_sp->GetItemAtIndex(i); + if (!item_sp) + continue; + auto str_sp = item_sp->GetAsString(); + if (!str_sp) + continue; - auto args_array_sp = args_sp->GetAsArray(); - if (!args_array_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - launch_info.GetArguments().Clear(); - - for (size_t i = 0; - i < args_array_sp->GetSize(); - i++) - { - auto item_sp = args_array_sp->GetItemAtIndex(i); - if (!item_sp) - continue; - auto str_sp = item_sp->GetAsString(); - if (!str_sp) - continue; - - launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); - } + launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); } - - return error; -} + } -HostThread -Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, - bool monitor_signals) -{ - unsigned long mask = DISPATCH_PROC_EXIT; - if (monitor_signals) - mask |= DISPATCH_PROC_SIGNAL; + return error; +} - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); +HostThread Host::StartMonitoringChildProcess( + const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, + bool monitor_signals) { + unsigned long mask = DISPATCH_PROC_EXIT; + if (monitor_signals) + mask |= DISPATCH_PROC_SIGNAL; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); + + dispatch_source_t source = ::dispatch_source_create( + DISPATCH_SOURCE_TYPE_PROC, pid, mask, + ::dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + + if (log) + log->Printf("Host::StartMonitoringChildProcess " + "(callback, pid=%i, monitor_signals=%i) " + "source = %p\n", + static_cast<int>(pid), monitor_signals, + reinterpret_cast<void *>(source)); + + if (source) { + Host::MonitorChildProcessCallback callback_copy = callback; + ::dispatch_source_set_cancel_handler(source, ^{ + ::dispatch_release(source); + }); + ::dispatch_source_set_event_handler(source, ^{ + + int status = 0; + int wait_pid = 0; + bool cancel = false; + bool exited = false; + do { + wait_pid = ::waitpid(pid, &status, 0); + } while (wait_pid < 0 && errno == EINTR); + + if (wait_pid >= 0) { + int signal = 0; + int exit_status = 0; + const char *status_cstr = NULL; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + status_cstr = "STOPPED"; + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + status_cstr = "EXITED"; + exited = true; + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + status_cstr = "SIGNALED"; + exited = true; + exit_status = -1; + } else { + status_cstr = "???"; + } + if (log) + log->Printf("::waitpid (pid = %llu, &status, 0) => pid = %i, status " + "= 0x%8.8x (%s), signal = %i, exit_status = %i", + pid, wait_pid, status, status_cstr, signal, exit_status); - dispatch_source_t source = ::dispatch_source_create (DISPATCH_SOURCE_TYPE_PROC, - pid, - mask, - ::dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT,0)); + if (callback_copy) + cancel = callback_copy(pid, exited, signal, exit_status); - if (log) - log->Printf("Host::StartMonitoringChildProcess " - "(callback, pid=%i, monitor_signals=%i) " - "source = %p\n", - static_cast<int>(pid), monitor_signals, reinterpret_cast<void *>(source)); - - if (source) - { - Host::MonitorChildProcessCallback callback_copy = callback; - ::dispatch_source_set_cancel_handler (source, ^{ - ::dispatch_release (source); - }); - ::dispatch_source_set_event_handler (source, ^{ - - int status= 0; - int wait_pid = 0; - bool cancel = false; - bool exited = false; - do - { - wait_pid = ::waitpid (pid, &status, 0); - } while (wait_pid < 0 && errno == EINTR); - - if (wait_pid >= 0) - { - int signal = 0; - int exit_status = 0; - const char *status_cstr = NULL; - if (WIFSTOPPED(status)) - { - signal = WSTOPSIG(status); - status_cstr = "STOPPED"; - } - else if (WIFEXITED(status)) - { - exit_status = WEXITSTATUS(status); - status_cstr = "EXITED"; - exited = true; - } - else if (WIFSIGNALED(status)) - { - signal = WTERMSIG(status); - status_cstr = "SIGNALED"; - exited = true; - exit_status = -1; - } - else - { - status_cstr = "???"; - } - - if (log) - log->Printf ("::waitpid (pid = %llu, &status, 0) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_status = %i", - pid, - wait_pid, - status, - status_cstr, - signal, - exit_status); - - if (callback_copy) - cancel = callback_copy(pid, exited, signal, exit_status); - - if (exited || cancel) - { - ::dispatch_source_cancel(source); - } - } - }); + if (exited || cancel) { + ::dispatch_source_cancel(source); + } + } + }); - ::dispatch_resume (source); - } - return HostThread(); + ::dispatch_resume(source); + } + return HostThread(); } //---------------------------------------------------------------------- // Log to both stderr and to ASL Logging when running on MacOSX. //---------------------------------------------------------------------- -void -Host::SystemLog (SystemLogType type, const char *format, va_list args) -{ - if (format && format[0]) - { - static aslmsg g_aslmsg = NULL; - if (g_aslmsg == NULL) - { - g_aslmsg = ::asl_new (ASL_TYPE_MSG); - char asl_key_sender[PATH_MAX]; - snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.LLDB.framework"); - ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender); - } - - // Copy the va_list so we can log this message twice - va_list copy_args; - va_copy (copy_args, args); - // Log to stderr - ::vfprintf (stderr, format, copy_args); - va_end (copy_args); - - int asl_level; - switch (type) - { - case eSystemLogError: - asl_level = ASL_LEVEL_ERR; - break; - - case eSystemLogWarning: - asl_level = ASL_LEVEL_WARNING; - break; - } - - // Log to ASL - ::asl_vlog (NULL, g_aslmsg, asl_level, format, args); +void Host::SystemLog(SystemLogType type, const char *format, va_list args) { + if (format && format[0]) { + static aslmsg g_aslmsg = NULL; + if (g_aslmsg == NULL) { + g_aslmsg = ::asl_new(ASL_TYPE_MSG); + char asl_key_sender[PATH_MAX]; + snprintf(asl_key_sender, sizeof(asl_key_sender), + "com.apple.LLDB.framework"); + ::asl_set(g_aslmsg, ASL_KEY_SENDER, asl_key_sender); } + + // Copy the va_list so we can log this message twice + va_list copy_args; + va_copy(copy_args, args); + // Log to stderr + ::vfprintf(stderr, format, copy_args); + va_end(copy_args); + + int asl_level; + switch (type) { + case eSystemLogError: + asl_level = ASL_LEVEL_ERR; + break; + + case eSystemLogWarning: + asl_level = ASL_LEVEL_WARNING; + break; + } + + // Log to ASL + ::asl_vlog(NULL, g_aslmsg, asl_level, format, args); + } } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - return lldb::DataBufferSP(); +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + return lldb::DataBufferSP(); } diff --git a/lldb/source/Host/macosx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/HostInfoMacOSX.mm index 8b664f0..b79332d 100644 --- a/lldb/source/Host/macosx/HostInfoMacOSX.mm +++ b/lldb/source/Host/macosx/HostInfoMacOSX.mm @@ -11,9 +11,9 @@ #include "Plugins/ScriptInterpreter/Python/lldb-python.h" #endif +#include "lldb/Core/Log.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/macosx/HostInfoMacOSX.h" -#include "lldb/Core/Log.h" #include "lldb/Interpreter/Args.h" #include "lldb/Utility/SafeMachO.h" @@ -42,337 +42,294 @@ #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) #endif #ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 (CPU_TYPE_ARM|CPU_ARCH_ABI64) +#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) #endif #include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH using namespace lldb_private; -bool -HostInfoMacOSX::GetOSBuildString(std::string &s) -{ - int mib[2] = {CTL_KERN, KERN_OSVERSION}; - char cstr[PATH_MAX]; - size_t cstr_len = sizeof(cstr); - if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) - { - s.assign(cstr, cstr_len); - return true; - } +bool HostInfoMacOSX::GetOSBuildString(std::string &s) { + int mib[2] = {CTL_KERN, KERN_OSVERSION}; + char cstr[PATH_MAX]; + size_t cstr_len = sizeof(cstr); + if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) { + s.assign(cstr, cstr_len); + return true; + } - s.clear(); - return false; + s.clear(); + return false; } -bool -HostInfoMacOSX::GetOSKernelDescription(std::string &s) -{ - int mib[2] = {CTL_KERN, KERN_VERSION}; - char cstr[PATH_MAX]; - size_t cstr_len = sizeof(cstr); - if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) - { - s.assign(cstr, cstr_len); - return true; - } - s.clear(); - return false; +bool HostInfoMacOSX::GetOSKernelDescription(std::string &s) { + int mib[2] = {CTL_KERN, KERN_VERSION}; + char cstr[PATH_MAX]; + size_t cstr_len = sizeof(cstr); + if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) { + s.assign(cstr, cstr_len); + return true; + } + s.clear(); + 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; - - if (g_major == 0) - { - @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(version_str, g_major, g_minor, g_update); - } +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; + + if (g_major == 0) { + @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(version_str, g_major, g_minor, g_update); } + } - if (g_major != 0) - { - major = g_major; - minor = g_minor; - update = g_update; - return true; - } - return false; + if (g_major != 0) { + major = g_major; + minor = g_minor; + update = g_update; + return true; + } + return false; } -FileSpec -HostInfoMacOSX::GetProgramFileSpec() -{ - static FileSpec g_program_filespec; - if (!g_program_filespec) - { - char program_fullpath[PATH_MAX]; - // If DST is NULL, then return the number of bytes needed. - uint32_t len = sizeof(program_fullpath); - int err = _NSGetExecutablePath(program_fullpath, &len); - if (err == 0) - g_program_filespec.SetFile(program_fullpath, false); - 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); - - ::free(large_program_fullpath); - } +FileSpec HostInfoMacOSX::GetProgramFileSpec() { + static FileSpec g_program_filespec; + if (!g_program_filespec) { + char program_fullpath[PATH_MAX]; + // If DST is NULL, then return the number of bytes needed. + uint32_t len = sizeof(program_fullpath); + int err = _NSGetExecutablePath(program_fullpath, &len); + if (err == 0) + g_program_filespec.SetFile(program_fullpath, false); + 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); + + ::free(large_program_fullpath); } - return g_program_filespec; + } + return g_program_filespec; } -bool -HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; +bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) { + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; - std::string raw_path = lldb_file_spec.GetPath(); + 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"); + size_t framework_pos = raw_path.find("LLDB.framework"); + if (framework_pos != std::string::npos) { + framework_pos += strlen("LLDB.framework"); #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - // Shallow bundle - raw_path.resize(framework_pos); + // Shallow bundle + raw_path.resize(framework_pos); #else - // Normal bundle - raw_path.resize(framework_pos); - raw_path.append("/Resources"); + // Normal bundle + raw_path.resize(framework_pos); + raw_path.append("/Resources"); #endif + } else { + // Find the bin path relative to the lib path where the cmake-based + // OS X .dylib lives. This is not going to work if the bin and lib + // dir are not both in the same dir. + // + // It is not going to work to do it by the executable path either, + // as in the case of a python script, the executable is python, not + // the lldb driver. + raw_path.append("/../bin"); + FileSpec support_dir_spec(raw_path, true); + if (!support_dir_spec.Exists() || !support_dir_spec.IsDirectory()) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoMacOSX::%s(): failed to find support directory", + __FUNCTION__); + return false; } - else - { - // Find the bin path relative to the lib path where the cmake-based - // OS X .dylib lives. This is not going to work if the bin and lib - // dir are not both in the same dir. - // - // It is not going to work to do it by the executable path either, - // as in the case of a python script, the executable is python, not - // the lldb driver. - raw_path.append("/../bin"); - FileSpec support_dir_spec(raw_path, true); - if (!support_dir_spec.Exists() || !support_dir_spec.IsDirectory()) - { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("HostInfoMacOSX::%s(): failed to find support directory", - __FUNCTION__); - return false; - } - - // Get normalization from support_dir_spec. Note the FileSpec resolve - // does not remove '..' in the path. - char *const dir_realpath = realpath(support_dir_spec.GetPath().c_str(), NULL); - if (dir_realpath) - { - raw_path = dir_realpath; - free(dir_realpath); - } - else - { - raw_path = support_dir_spec.GetPath(); - } + + // Get normalization from support_dir_spec. Note the FileSpec resolve + // does not remove '..' in the path. + char *const dir_realpath = + realpath(support_dir_spec.GetPath().c_str(), NULL); + if (dir_realpath) { + raw_path = dir_realpath; + free(dir_realpath); + } else { + raw_path = support_dir_spec.GetPath(); } + } - file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size())); - return (bool)file_spec.GetDirectory(); + file_spec.GetDirectory().SetString( + llvm::StringRef(raw_path.c_str(), raw_path.size())); + return (bool)file_spec.GetDirectory(); } -bool -HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) -{ - FileSpec lldb_file_spec; - if (!HostInfo::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("/Headers"); - } - file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size())); - return true; +bool HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) { + FileSpec lldb_file_spec; + if (!HostInfo::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("/Headers"); + } + file_spec.GetDirectory().SetString( + llvm::StringRef(raw_path.c_str(), raw_path.size())); + return true; } -bool -HostInfoMacOSX::ComputePythonDirectory(FileSpec &file_spec) -{ +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 + 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) - { - 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::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) { + 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)) - return false; +bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) { + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; - std::string raw_path = lldb_file_spec.GetPath(); + std::string raw_path = lldb_file_spec.GetPath(); - size_t framework_pos = raw_path.find("LLDB.framework"); - if (framework_pos == std::string::npos) - return false; + size_t framework_pos = raw_path.find("LLDB.framework"); + if (framework_pos == std::string::npos) + return false; - framework_pos += strlen("LLDB.framework"); - raw_path.resize(framework_pos); - raw_path.append("/Resources/PlugIns"); - file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size())); - return true; + framework_pos += strlen("LLDB.framework"); + raw_path.resize(framework_pos); + raw_path.append("/Resources/PlugIns"); + file_spec.GetDirectory().SetString( + llvm::StringRef(raw_path.c_str(), raw_path.size())); + return true; } -bool -HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) -{ - FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true); - file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); - return true; +bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) { + FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true); + file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); + return true; } -void -HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) -{ - // All apple systems support 32 bit execution. - uint32_t cputype, cpusubtype; - uint32_t is_64_bit_capable = false; - size_t len = sizeof(cputype); - ArchSpec host_arch; - // These will tell us about the kernel architecture, which even on a 64 - // bit machine can be 32 bit... - if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) - { - len = sizeof(cpusubtype); - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) - cpusubtype = CPU_TYPE_ANY; - - len = sizeof(is_64_bit_capable); - ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0); - - if (is_64_bit_capable) - { - if (cputype & CPU_ARCH_ABI64) - { - // We have a 64 bit kernel on a 64 bit system - arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype); - } - else - { - // We have a 64 bit kernel that is returning a 32 bit cputype, the - // cpusubtype will be correct as if it were for a 64 bit architecture - arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64, cpusubtype); - } - - // Now we need modify the cpusubtype for the 32 bit slices. - uint32_t cpusubtype32 = cpusubtype; +void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + // All apple systems support 32 bit execution. + uint32_t cputype, cpusubtype; + uint32_t is_64_bit_capable = false; + size_t len = sizeof(cputype); + ArchSpec host_arch; + // These will tell us about the kernel architecture, which even on a 64 + // bit machine can be 32 bit... + if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) { + len = sizeof(cpusubtype); + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) + cpusubtype = CPU_TYPE_ANY; + + len = sizeof(is_64_bit_capable); + ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0); + + if (is_64_bit_capable) { + if (cputype & CPU_ARCH_ABI64) { + // We have a 64 bit kernel on a 64 bit system + arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype); + } else { + // We have a 64 bit kernel that is returning a 32 bit cputype, the + // cpusubtype will be correct as if it were for a 64 bit architecture + arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64, + cpusubtype); + } + + // Now we need modify the cpusubtype for the 32 bit slices. + uint32_t cpusubtype32 = cpusubtype; #if defined(__i386__) || defined(__x86_64__) - if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H) - cpusubtype32 = CPU_SUBTYPE_I386_ALL; + if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H) + cpusubtype32 = CPU_SUBTYPE_I386_ALL; #elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) - cpusubtype32 = CPU_SUBTYPE_ARM_V7S; + if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) + cpusubtype32 = CPU_SUBTYPE_ARM_V7S; #endif - arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK), cpusubtype32); - - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) - { - // When running on a watch or tv, report the host os correctly -#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1 - arch_32.GetTriple().setOS(llvm::Triple::TvOS); - arch_64.GetTriple().setOS(llvm::Triple::TvOS); + arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK), + cpusubtype32); + + if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) { +// When running on a watch or tv, report the host os correctly +#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 + arch_32.GetTriple().setOS(llvm::Triple::TvOS); + arch_64.GetTriple().setOS(llvm::Triple::TvOS); #else - arch_32.GetTriple().setOS(llvm::Triple::IOS); - arch_64.GetTriple().setOS(llvm::Triple::IOS); + arch_32.GetTriple().setOS(llvm::Triple::IOS); + arch_64.GetTriple().setOS(llvm::Triple::IOS); #endif - } - else - { - arch_32.GetTriple().setOS(llvm::Triple::MacOSX); - arch_64.GetTriple().setOS(llvm::Triple::MacOSX); - } - } - else - { - // We have a 32 bit kernel on a 32 bit system - arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype); -#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - arch_32.GetTriple().setOS(llvm::Triple::WatchOS); + } else { + arch_32.GetTriple().setOS(llvm::Triple::MacOSX); + arch_64.GetTriple().setOS(llvm::Triple::MacOSX); + } + } else { + // We have a 32 bit kernel on a 32 bit system + arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype); +#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + arch_32.GetTriple().setOS(llvm::Triple::WatchOS); #else - arch_32.GetTriple().setOS(llvm::Triple::IOS); + arch_32.GetTriple().setOS(llvm::Triple::IOS); #endif - arch_64.Clear(); - } + arch_64.Clear(); } + } } -uint32_t -HostInfoMacOSX::GetMaxThreadNameLength() -{ - return 64; -} +uint32_t HostInfoMacOSX::GetMaxThreadNameLength() { return 64; } diff --git a/lldb/source/Host/macosx/HostThreadMacOSX.mm b/lldb/source/Host/macosx/HostThreadMacOSX.mm index 6fb498c..c5051cd 100644 --- a/lldb/source/Host/macosx/HostThreadMacOSX.mm +++ b/lldb/source/Host/macosx/HostThreadMacOSX.mm @@ -17,70 +17,54 @@ using namespace lldb_private; -namespace -{ +namespace { pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; pthread_key_t g_thread_create_key = 0; -class MacOSXDarwinThread -{ - public: - MacOSXDarwinThread() - : m_pool(nil) - { - m_pool = [[NSAutoreleasePool alloc] init]; - } +class MacOSXDarwinThread { +public: + MacOSXDarwinThread() : m_pool(nil) { + m_pool = [[NSAutoreleasePool alloc] init]; + } - ~MacOSXDarwinThread() - { - if (m_pool) - { - [m_pool drain]; - m_pool = nil; - } + ~MacOSXDarwinThread() { + if (m_pool) { + [m_pool drain]; + m_pool = nil; } + } - static void - PThreadDestructor(void *v) - { - if (v) - delete static_cast<MacOSXDarwinThread *>(v); - ::pthread_setspecific(g_thread_create_key, NULL); - } + static void PThreadDestructor(void *v) { + if (v) + delete static_cast<MacOSXDarwinThread *>(v); + ::pthread_setspecific(g_thread_create_key, NULL); + } - protected: - NSAutoreleasePool *m_pool; +protected: + NSAutoreleasePool *m_pool; - private: - DISALLOW_COPY_AND_ASSIGN(MacOSXDarwinThread); +private: + DISALLOW_COPY_AND_ASSIGN(MacOSXDarwinThread); }; -void -InitThreadCreated() -{ - ::pthread_key_create(&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor); +void InitThreadCreated() { + ::pthread_key_create(&g_thread_create_key, + MacOSXDarwinThread::PThreadDestructor); } } // namespace -HostThreadMacOSX::HostThreadMacOSX() - : HostThreadPosix() -{ -} +HostThreadMacOSX::HostThreadMacOSX() : HostThreadPosix() {} HostThreadMacOSX::HostThreadMacOSX(lldb::thread_t thread) - : HostThreadPosix(thread) -{ -} + : HostThreadPosix(thread) {} lldb::thread_result_t -HostThreadMacOSX::ThreadCreateTrampoline(lldb::thread_arg_t arg) -{ - ::pthread_once(&g_thread_create_once, InitThreadCreated); - if (g_thread_create_key) - { - ::pthread_setspecific(g_thread_create_key, new MacOSXDarwinThread()); - } +HostThreadMacOSX::ThreadCreateTrampoline(lldb::thread_arg_t arg) { + ::pthread_once(&g_thread_create_once, InitThreadCreated); + if (g_thread_create_key) { + ::pthread_setspecific(g_thread_create_key, new MacOSXDarwinThread()); + } - return HostThreadPosix::ThreadCreateTrampoline(arg); + return HostThreadPosix::ThreadCreateTrampoline(arg); } diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index 3eba327..e6b31c6 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -10,15 +10,19 @@ #include "lldb/Host/Symbols.h" // C Includes +#include "lldb/Utility/SafeMachO.h" #include <dirent.h> #include <pwd.h> -#include "lldb/Utility/SafeMachO.h" // C++ Includes // Other libraries and framework includes #include <CoreFoundation/CoreFoundation.h> // Project includes +#include "Host/macosx/cfcpp/CFCBundle.h" +#include "Host/macosx/cfcpp/CFCData.h" +#include "Host/macosx/cfcpp/CFCReleaser.h" +#include "Host/macosx/cfcpp/CFCString.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataExtractor.h" @@ -32,590 +36,554 @@ #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/CleanUp.h" -#include "Host/macosx/cfcpp/CFCBundle.h" -#include "Host/macosx/cfcpp/CFCData.h" -#include "Host/macosx/cfcpp/CFCReleaser.h" -#include "Host/macosx/cfcpp/CFCString.h" #include "mach/machine.h" using namespace lldb; using namespace lldb_private; using namespace llvm::MachO; -#if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__) // No DebugSymbols on the iOS devices +#if !defined(__arm__) && !defined(__arm64__) && \ + !defined(__aarch64__) // No DebugSymbols on the iOS devices extern "C" { -CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url); -CFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url); - +CFURLRef DBGCopyFullDSYMURLForUUID(CFUUIDRef uuid, CFURLRef exec_url); +CFDictionaryRef DBGCopyDSYMPropertyLists(CFURLRef dsym_url); } #endif -int -LocateMacOSXFilesUsingDebugSymbols -( - const ModuleSpec &module_spec, - ModuleSpec &return_module_spec -) -{ - return_module_spec = module_spec; - return_module_spec.GetFileSpec().Clear(); - return_module_spec.GetSymbolFileSpec().Clear(); - - int items_found = 0; - -#if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__) // No DebugSymbols on the iOS devices - - const UUID *uuid = module_spec.GetUUIDPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - - 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) - { - 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], - module_uuid[8], - module_uuid[9], - module_uuid[10], - module_uuid[11], - module_uuid[12], - module_uuid[13], - module_uuid[14], - module_uuid[15])); - - 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))) - exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL, - (const UInt8 *)exec_cf_path, - strlen(exec_cf_path), - FALSE)); - } - - CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get())); - char path[PATH_MAX]; +int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, + ModuleSpec &return_module_spec) { + return_module_spec = module_spec; + return_module_spec.GetFileSpec().Clear(); + return_module_spec.GetSymbolFileSpec().Clear(); + + int items_found = 0; + +#if !defined(__arm__) && !defined(__arm64__) && \ + !defined(__aarch64__) // No DebugSymbols on the iOS devices + + const UUID *uuid = module_spec.GetUUIDPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + + 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) { + 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], + module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], + module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); + + 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))) + exec_url.reset(::CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), + FALSE)); + } - if (dsym_url.get()) + CFCReleaser<CFURLRef> dsym_url( + ::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get())); + char path[PATH_MAX]; + + if (dsym_url.get()) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + if (log) { + log->Printf("DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for the dSYM", + path, uuid->GetAsString().c_str()); + } + FileSpec dsym_filespec(path, path[0] == '~'); + + if (dsym_filespec.GetFileType() == FileSpec::eFileTypeDirectory) { + dsym_filespec = + Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch); + ++items_found; + } else { + ++items_found; + } + return_module_spec.GetSymbolFileSpec() = dsym_filespec; + } + + bool success = false; + if (log) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + log->Printf("DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for an exec file", + path, uuid->GetAsString().c_str()); + } + } + + CFCReleaser<CFDictionaryRef> dict( + ::DBGCopyDSYMPropertyLists(dsym_url.get())); + CFDictionaryRef uuid_dict = NULL; + if (dict.get()) { + CFCString uuid_cfstr(uuid->GetAsString().c_str()); + uuid_dict = static_cast<CFDictionaryRef>( + ::CFDictionaryGetValue(dict.get(), uuid_cfstr.get())); + } + if (uuid_dict) { + CFStringRef exec_cf_path = + static_cast<CFStringRef>(::CFDictionaryGetValue( + uuid_dict, CFSTR("DBGSymbolRichExecutable"))); + if (exec_cf_path && ::CFStringGetFileSystemRepresentation( + exec_cf_path, path, sizeof(path))) { + if (log) { + log->Printf("plist bundle has exec path of %s for UUID %s", + path, uuid->GetAsString().c_str()); + } + ++items_found; + FileSpec exec_filespec(path, path[0] == '~'); + if (exec_filespec.Exists()) { + success = true; + return_module_spec.GetFileSpec() = exec_filespec; + } + } + } + + if (!success) { + // No dictionary, check near the dSYM bundle for an executable that + // matches... + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + char *dsym_extension_pos = ::strstr(path, ".dSYM"); + if (dsym_extension_pos) { + *dsym_extension_pos = '\0'; + if (log) { + log->Printf("Looking for executable binary next to dSYM " + "bundle with name with name %s", + path); + } + FileSpec file_spec(path, true); + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + switch (file_spec.GetFileType()) { + case FileSpec::eFileTypeDirectory: // Bundle directory? { - if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) - { - if (log) - { - log->Printf ("DebugSymbols framework returned dSYM path of %s for UUID %s -- looking for the dSYM", path, uuid->GetAsString().c_str()); - } - FileSpec dsym_filespec(path, path[0] == '~'); - - if (dsym_filespec.GetFileType () == FileSpec::eFileTypeDirectory) - { - dsym_filespec = Symbols::FindSymbolFileInBundle (dsym_filespec, uuid, arch); - ++items_found; - } - else - { - ++items_found; + CFCBundle bundle(path); + CFCReleaser<CFURLRef> bundle_exe_url( + bundle.CopyExecutableURL()); + if (bundle_exe_url.get()) { + if (::CFURLGetFileSystemRepresentation(bundle_exe_url.get(), + true, (UInt8 *)path, + sizeof(path) - 1)) { + FileSpec bundle_exe_file_spec(path, true); + if (ObjectFile::GetModuleSpecifications( + bundle_exe_file_spec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec( + module_spec, matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = bundle_exe_file_spec; + if (log) { + log->Printf("Executable binary %s next to dSYM is " + "compatible; using", + path); } - return_module_spec.GetSymbolFileSpec() = dsym_filespec; + } } - - bool success = false; - if (log) - { - if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) - { - log->Printf ("DebugSymbols framework returned dSYM path of %s for UUID %s -- looking for an exec file", path, uuid->GetAsString().c_str()); - } - - } - - CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get())); - CFDictionaryRef uuid_dict = NULL; - if (dict.get()) - { - CFCString uuid_cfstr (uuid->GetAsString().c_str()); - uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get())); - } - if (uuid_dict) - { - CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable"))); - if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path))) - { - if (log) - { - log->Printf ("plist bundle has exec path of %s for UUID %s", path, uuid->GetAsString().c_str()); - } - ++items_found; - FileSpec exec_filespec (path, path[0] == '~'); - if (exec_filespec.Exists()) - { - success = true; - return_module_spec.GetFileSpec() = exec_filespec; - } - } - } - - if (!success) - { - // No dictionary, check near the dSYM bundle for an executable that matches... - if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) - { - char *dsym_extension_pos = ::strstr (path, ".dSYM"); - if (dsym_extension_pos) - { - *dsym_extension_pos = '\0'; - if (log) - { - log->Printf ("Looking for executable binary next to dSYM bundle with name with name %s", path); - } - FileSpec file_spec (path, true); - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - switch (file_spec.GetFileType()) - { - case FileSpec::eFileTypeDirectory: // Bundle directory? - { - CFCBundle bundle (path); - CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ()); - if (bundle_exe_url.get()) - { - if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1)) - { - FileSpec bundle_exe_file_spec (path, true); - if (ObjectFile::GetModuleSpecifications(bundle_exe_file_spec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) - - { - ++items_found; - return_module_spec.GetFileSpec() = bundle_exe_file_spec; - if (log) - { - log->Printf ("Executable binary %s next to dSYM is compatible; using", path); - } - } - } - } - } - break; - - case FileSpec::eFileTypePipe: // Forget pipes - case FileSpec::eFileTypeSocket: // We can't process socket files - case FileSpec::eFileTypeInvalid: // File doesn't exist... - break; - - case FileSpec::eFileTypeUnknown: - case FileSpec::eFileTypeRegular: - case FileSpec::eFileTypeSymbolicLink: - case FileSpec::eFileTypeOther: - if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) - - { - ++items_found; - return_module_spec.GetFileSpec() = file_spec; - if (log) - { - log->Printf ("Executable binary %s next to dSYM is compatible; using", path); - } - } - break; - } - } - } + } + } break; + + case FileSpec::eFileTypePipe: // Forget pipes + case FileSpec::eFileTypeSocket: // We can't process socket files + case FileSpec::eFileTypeInvalid: // File doesn't exist... + break; + + case FileSpec::eFileTypeUnknown: + case FileSpec::eFileTypeRegular: + case FileSpec::eFileTypeSymbolicLink: + case FileSpec::eFileTypeOther: + if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, + module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, + matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = file_spec; + if (log) { + log->Printf("Executable binary %s next to dSYM is " + "compatible; using", + path); } + } + break; } + } } + } } + } } -#endif // #if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__) + } +#endif // #if !defined (__arm__) && !defined (__arm64__) && !defined + // (__aarch64__) - return items_found; + return items_found; } -FileSpec -Symbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec, - const lldb_private::UUID *uuid, - const ArchSpec *arch) -{ - char path[PATH_MAX]; - - FileSpec dsym_fspec; - - if (dsym_bundle_fspec.GetPath(path, sizeof(path))) - { - ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1); - - 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; - - if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.') - continue; - } +FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, + const lldb_private::UUID *uuid, + const ArchSpec *arch) { + char path[PATH_MAX]; + + FileSpec dsym_fspec; + + if (dsym_bundle_fspec.GetPath(path, sizeof(path))) { + ::strncat(path, "/Contents/Resources/DWARF", + sizeof(path) - strlen(path) - 1); + + 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; + + 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) - { - assert(module_specs.GetModuleSpecAtIndex(i, spec)); - if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && - (arch == NULL || (spec.GetArchitecturePtr() && spec.GetArchitecture().IsCompatibleMatch(*arch)))) - { - return dsym_fspec; - } - } - } - } + 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) { + assert(module_specs.GetModuleSpecAtIndex(i, 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; + } + dsym_fspec.Clear(); + return dsym_fspec; } -static bool -GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec) -{ - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - bool success = false; - if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ()) - { - std::string str; - CFStringRef cf_str; - CFDictionaryRef cf_dict; - - cf_str = (CFStringRef)CFDictionaryGetValue ((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); - if (log) - { - log->Printf ("From dsymForUUID plist: Symbol rich executable is at '%s'", str.c_str()); - } - } - } - - cf_str = (CFStringRef)CFDictionaryGetValue ((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); - success = true; - if (log) - { - log->Printf ("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); - } - } +static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, + ModuleSpec &module_spec) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + bool success = false; + if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) { + std::string str; + CFStringRef cf_str; + CFDictionaryRef cf_dict; + + cf_str = (CFStringRef)CFDictionaryGetValue( + (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); + if (log) { + log->Printf( + "From dsymForUUID plist: Symbol rich executable is at '%s'", + str.c_str()); } - - cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture")); - if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) - { - if (CFCString::FileSystemRepresentation(cf_str, str)) - module_spec.GetArchitecture().SetTriple(str.c_str()); + } + } + + cf_str = (CFStringRef)CFDictionaryGetValue((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); + success = true; + if (log) { + log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); } + } + } - std::string DBGBuildSourcePath; - std::string DBGSourcePath; + cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, + CFSTR("DBGArchitecture")); + if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { + if (CFCString::FileSystemRepresentation(cf_str, str)) + module_spec.GetArchitecture().SetTriple(str.c_str()); + } - cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath")); - if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) - { - CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); - } + std::string DBGBuildSourcePath; + std::string DBGSourcePath; - 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); - } + cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, + CFSTR("DBGBuildSourcePath")); + if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); + } - cf_dict = (CFDictionaryRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePathRemapping")); - if (cf_dict && CFGetTypeID (cf_dict) == CFDictionaryGetTypeID ()) - { - // If we see DBGVersion with any kind of value, this is a new style DBGSourcePathRemapping dictionary - bool new_style_source_remapping_dictionary = false; - std::string original_DBGSourcePath_value = DBGSourcePath; - const void *version_value; - version_value = CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGVersion")); - if (version_value) - new_style_source_remapping_dictionary = true; - - CFIndex kv_pair_count = CFDictionaryGetCount ((CFDictionaryRef) uuid_dict); - if (kv_pair_count > 0) - { - CFStringRef *keys = (CFStringRef *) malloc (kv_pair_count * sizeof (CFStringRef)); - CFStringRef *values = (CFStringRef *) malloc (kv_pair_count * sizeof (CFStringRef)); - if (keys != nullptr && values != nullptr) - { - CFDictionaryGetKeysAndValues ((CFDictionaryRef) uuid_dict, (const void**)keys, (const void**)values); - } - for (CFIndex i = 0; i < kv_pair_count; i++) - { - DBGBuildSourcePath.clear(); - DBGSourcePath.clear(); - if (keys[i] && CFGetTypeID (keys[i]) == CFStringGetTypeID ()) - { - CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath); - } - if (values[i] && CFGetTypeID (values[i]) == CFStringGetTypeID ()) - { - CFCString::FileSystemRepresentation(values[i], DBGSourcePath); - } - 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. - if (new_style_source_remapping_dictionary == true && !original_DBGSourcePath_value.empty()) - { - DBGSourcePath = original_DBGSourcePath_value; - } - 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 (keys) - free (keys); - if (values) - free (values); - } - } + cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, + CFSTR("DBGSourcePath")); + if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); } - return success; -} + 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); + } -bool -Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup) -{ - bool success = false; - const UUID *uuid_ptr = module_spec.GetUUIDPtr(); - 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. - static bool g_have_checked_for_dbgshell_command = false; - static const char *g_dbgshell_command = NULL; - if (g_have_checked_for_dbgshell_command == false) - { - g_have_checked_for_dbgshell_command = true; - CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols")); - if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID()) - { - char cstr_buf[PATH_MAX]; - if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8)) - { - g_dbgshell_command = strdup (cstr_buf); // this malloc'ed memory will never be freed - } + cf_dict = (CFDictionaryRef)CFDictionaryGetValue( + (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping")); + if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) { + // If we see DBGVersion with any kind of value, this is a new style + // DBGSourcePathRemapping dictionary + bool new_style_source_remapping_dictionary = false; + std::string original_DBGSourcePath_value = DBGSourcePath; + const void *version_value; + version_value = + CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGVersion")); + if (version_value) + new_style_source_remapping_dictionary = true; + + CFIndex kv_pair_count = CFDictionaryGetCount((CFDictionaryRef)uuid_dict); + if (kv_pair_count > 0) { + CFStringRef *keys = + (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); + CFStringRef *values = + (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); + if (keys != nullptr && values != nullptr) { + CFDictionaryGetKeysAndValues((CFDictionaryRef)uuid_dict, + (const void **)keys, + (const void **)values); } - if (defaults_setting) - { - CFRelease (defaults_setting); + for (CFIndex i = 0; i < kv_pair_count; i++) { + DBGBuildSourcePath.clear(); + DBGSourcePath.clear(); + if (keys[i] && CFGetTypeID(keys[i]) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath); + } + if (values[i] && CFGetTypeID(values[i]) == CFStringGetTypeID()) { + CFCString::FileSystemRepresentation(values[i], DBGSourcePath); + } + 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. + if (new_style_source_remapping_dictionary == true && + !original_DBGSourcePath_value.empty()) { + DBGSourcePath = original_DBGSourcePath_value; + } + 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 (keys) + free(keys); + if (values) + free(values); + } } + } + return success; +} - // When g_dbgshell_command is NULL, the user has not enabled the use of an external program - // to find the symbols, don't run it for them. - if (force_lookup == false && g_dbgshell_command == NULL) - { - return false; +bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + bool force_lookup) { + bool success = false; + const UUID *uuid_ptr = module_spec.GetUUIDPtr(); + 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. + static bool g_have_checked_for_dbgshell_command = false; + static const char *g_dbgshell_command = NULL; + if (g_have_checked_for_dbgshell_command == false) { + g_have_checked_for_dbgshell_command = true; + CFTypeRef defaults_setting = CFPreferencesCopyAppValue( + CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols")); + if (defaults_setting && + CFGetTypeID(defaults_setting) == CFStringGetTypeID()) { + char cstr_buf[PATH_MAX]; + if (CFStringGetCString((CFStringRef)defaults_setting, cstr_buf, + sizeof(cstr_buf), kCFStringEncodingUTF8)) { + g_dbgshell_command = + strdup(cstr_buf); // this malloc'ed memory will never be freed + } } - - if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) - { - static bool g_located_dsym_for_uuid_exe = false; - static bool g_dsym_for_uuid_exe_exists = false; - static char g_dsym_for_uuid_exe_path[PATH_MAX]; - if (!g_located_dsym_for_uuid_exe) - { - g_located_dsym_for_uuid_exe = true; - const char *dsym_for_uuid_exe_path_cstr = 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); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + if (defaults_setting) { + CFRelease(defaults_setting); + } + } + + // When g_dbgshell_command is NULL, the user has not enabled the use of an + // external program + // to find the symbols, don't run it for them. + if (force_lookup == false && g_dbgshell_command == NULL) { + return false; + } + + if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) { + static bool g_located_dsym_for_uuid_exe = false; + static bool g_dsym_for_uuid_exe_exists = false; + static char g_dsym_for_uuid_exe_path[PATH_MAX]; + if (!g_located_dsym_for_uuid_exe) { + g_located_dsym_for_uuid_exe = true; + const char *dsym_for_uuid_exe_path_cstr = + 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); + 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); + g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + if (!g_dsym_for_uuid_exe_exists) { + long bufsize; + if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) { + char buffer[bufsize]; + struct passwd pwd; + struct passwd *tilde_rc = NULL; + // we are a library so we need to use the reentrant version of + // getpwnam() + if (getpwnam_r("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 && + 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); + 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); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); - if (!g_dsym_for_uuid_exe_exists) - { - long bufsize; - if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) - { - char buffer[bufsize]; - struct passwd pwd; - struct passwd *tilde_rc = NULL; - // we are a library so we need to use the reentrant version of getpwnam() - if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 - && 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); - 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); + g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + } + + if (g_dsym_for_uuid_exe_exists) + dsym_for_uuid_exe_spec.GetPath(g_dsym_for_uuid_exe_path, + sizeof(g_dsym_for_uuid_exe_path)); + } + if (g_dsym_for_uuid_exe_exists) { + std::string uuid_str; + char file_path[PATH_MAX]; + file_path[0] = '\0'; + + if (uuid_ptr) + uuid_str = uuid_ptr->GetAsString(); + + if (file_spec_ptr) + file_spec_ptr->GetPath(file_path, sizeof(file_path)); + + StreamString command; + if (!uuid_str.empty()) + command.Printf("%s --ignoreNegativeCache --copyExecutable %s", + g_dsym_for_uuid_exe_path, uuid_str.c_str()); + else if (file_path[0] != '\0') + command.Printf("%s --ignoreNegativeCache --copyExecutable %s", + g_dsym_for_uuid_exe_path, file_path); + + if (!command.GetString().empty()) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + int exit_status = -1; + int signo = -1; + std::string command_output; + if (log) { + if (!uuid_str.empty()) + log->Printf("Calling %s with UUID %s to find dSYM", + g_dsym_for_uuid_exe_path, uuid_str.c_str()); + else if (file_path[0] != '\0') + log->Printf("Calling %s with file %s to find dSYM", + g_dsym_for_uuid_exe_path, file_path); + } + Error error = Host::RunShellCommand( + command.GetData(), + NULL, // current working directory + &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) + if (error.Success() && exit_status == 0 && !command_output.empty()) { + CFCData data(CFDataCreateWithBytesNoCopy( + NULL, (const UInt8 *)command_output.data(), command_output.size(), + kCFAllocatorNull)); + + CFCReleaser<CFDictionaryRef> plist( + (CFDictionaryRef)::CFPropertyListCreateFromXMLData( + NULL, data.get(), kCFPropertyListImmutable, NULL)); + + if (plist.get() && + CFGetTypeID(plist.get()) == CFDictionaryGetTypeID()) { + if (!uuid_str.empty()) { + CFCString uuid_cfstr(uuid_str.c_str()); + CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue( + plist.get(), uuid_cfstr.get()); + success = + GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec); + } else { + const CFIndex num_values = ::CFDictionaryGetCount(plist.get()); + if (num_values > 0) { + std::vector<CFStringRef> keys(num_values, NULL); + std::vector<CFDictionaryRef> values(num_values, NULL); + ::CFDictionaryGetKeysAndValues(plist.get(), NULL, + (const void **)&values[0]); + if (num_values == 1) { + return GetModuleSpecInfoFromUUIDDictionary(values[0], + module_spec); + } else { + for (CFIndex i = 0; i < num_values; ++i) { + ModuleSpec curr_module_spec; + if (GetModuleSpecInfoFromUUIDDictionary(values[i], + curr_module_spec)) { + if (module_spec.GetArchitecture().IsCompatibleMatch( + curr_module_spec.GetArchitecture())) { + module_spec = curr_module_spec; + return true; + } } + } } + } } - if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) - { - dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true); - g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); - } - - if (g_dsym_for_uuid_exe_exists) - dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path)); - } - if (g_dsym_for_uuid_exe_exists) - { - std::string uuid_str; - char file_path[PATH_MAX]; - file_path[0] = '\0'; - - if (uuid_ptr) - uuid_str = uuid_ptr->GetAsString(); - - if (file_spec_ptr) - file_spec_ptr->GetPath(file_path, sizeof(file_path)); - - StreamString command; + } + } else { + if (log) { if (!uuid_str.empty()) - command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str()); + log->Printf("Called %s on %s, no matches", + g_dsym_for_uuid_exe_path, uuid_str.c_str()); else if (file_path[0] != '\0') - command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path); - - if (!command.GetString().empty()) - { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - int exit_status = -1; - int signo = -1; - std::string command_output; - if (log) - { - if (!uuid_str.empty()) - log->Printf("Calling %s with UUID %s to find dSYM", g_dsym_for_uuid_exe_path, uuid_str.c_str()); - else if (file_path[0] != '\0') - log->Printf("Calling %s with file %s to find dSYM", g_dsym_for_uuid_exe_path, file_path); - } - Error error = Host::RunShellCommand (command.GetData(), - NULL, // current working directory - &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) - if (error.Success() && exit_status == 0 && !command_output.empty()) - { - CFCData data (CFDataCreateWithBytesNoCopy (NULL, - (const UInt8 *)command_output.data(), - command_output.size(), - kCFAllocatorNull)); - - CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL)); - - if (plist.get() && CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ()) - { - if (!uuid_str.empty()) - { - CFCString uuid_cfstr(uuid_str.c_str()); - CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get()); - success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec); - } - else - { - const CFIndex num_values = ::CFDictionaryGetCount(plist.get()); - if (num_values > 0) - { - std::vector<CFStringRef> keys (num_values, NULL); - std::vector<CFDictionaryRef> values (num_values, NULL); - ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]); - if (num_values == 1) - { - return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec); - } - else - { - for (CFIndex i=0; i<num_values; ++i) - { - ModuleSpec curr_module_spec; - if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec)) - { - if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture())) - { - module_spec = curr_module_spec; - return true; - } - } - } - } - } - } - } - } - else - { - if (log) - { - if (!uuid_str.empty()) - log->Printf("Called %s on %s, no matches", g_dsym_for_uuid_exe_path, uuid_str.c_str()); - else if (file_path[0] != '\0') - log->Printf("Called %s on %s, no matches", g_dsym_for_uuid_exe_path, file_path); - } - } - } + log->Printf("Called %s on %s, no matches", + g_dsym_for_uuid_exe_path, file_path); + } } + } } - return success; + } + return success; } - diff --git a/lldb/source/Host/macosx/ThisThread.cpp b/lldb/source/Host/macosx/ThisThread.cpp index 6f1c88f..5244ba0 100644 --- a/lldb/source/Host/macosx/ThisThread.cpp +++ b/lldb/source/Host/macosx/ThisThread.cpp @@ -9,21 +9,17 @@ #include "lldb/Host/ThisThread.h" -#include <pthread.h> #include "llvm/ADT/SmallVector.h" +#include <pthread.h> using namespace lldb_private; -void -ThisThread::SetName(llvm::StringRef name) -{ -#if defined (__APPLE__) - ::pthread_setname_np(name.str().c_str()); +void ThisThread::SetName(llvm::StringRef name) { +#if defined(__APPLE__) + ::pthread_setname_np(name.str().c_str()); #endif } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ - // FIXME - implement this. +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { + // FIXME - implement this. } diff --git a/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp b/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp index 71b0749..08f1670 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp @@ -13,87 +13,71 @@ //---------------------------------------------------------------------- // CFCBundle constructor //---------------------------------------------------------------------- -CFCBundle::CFCBundle(const char *path) : - CFCReleaser<CFBundleRef>() -{ - if (path && path[0]) - SetPath(path); +CFCBundle::CFCBundle(const char *path) : CFCReleaser<CFBundleRef>() { + if (path && path[0]) + SetPath(path); } -CFCBundle::CFCBundle(CFURLRef url) : - CFCReleaser<CFBundleRef>(url ? CFBundleCreate(NULL, url) : NULL) -{ -} +CFCBundle::CFCBundle(CFURLRef url) + : CFCReleaser<CFBundleRef>(url ? CFBundleCreate(NULL, url) : NULL) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCBundle::~CFCBundle() -{ -} +CFCBundle::~CFCBundle() {} //---------------------------------------------------------------------- // Set the path for a bundle by supplying a //---------------------------------------------------------------------- -bool -CFCBundle::SetPath (const char *path) -{ - CFAllocatorRef alloc = kCFAllocatorDefault; - // Release our old bundle and URL - reset(); +bool CFCBundle::SetPath(const char *path) { + CFAllocatorRef alloc = kCFAllocatorDefault; + // Release our old bundle and URL + reset(); - // Make a CFStringRef from the supplied path - CFCString cf_path; - cf_path.SetFileSystemRepresentation(path); - if (cf_path.get()) - { - // Make our Bundle URL - CFCReleaser<CFURLRef> bundle_url (::CFURLCreateWithFileSystemPath (alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); - if (bundle_url.get()) - reset (::CFBundleCreate (alloc, bundle_url.get())); - } - return get() != NULL; + // Make a CFStringRef from the supplied path + CFCString cf_path; + cf_path.SetFileSystemRepresentation(path); + if (cf_path.get()) { + // Make our Bundle URL + CFCReleaser<CFURLRef> bundle_url(::CFURLCreateWithFileSystemPath( + alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); + if (bundle_url.get()) + reset(::CFBundleCreate(alloc, bundle_url.get())); + } + return get() != NULL; } -bool -CFCBundle::GetPath (char *dst, size_t dst_len) -{ - CFBundleRef bundle = get(); - if (bundle) - { - CFCReleaser<CFURLRef> bundle_url (CFBundleCopyBundleURL (bundle)); - if (bundle_url.get()) - { - Boolean resolveAgainstBase = 0; - return ::CFURLGetFileSystemRepresentation (bundle_url.get(), resolveAgainstBase, (UInt8 *)dst, dst_len) != 0; - } +bool CFCBundle::GetPath(char *dst, size_t dst_len) { + CFBundleRef bundle = get(); + if (bundle) { + CFCReleaser<CFURLRef> bundle_url(CFBundleCopyBundleURL(bundle)); + if (bundle_url.get()) { + Boolean resolveAgainstBase = 0; + return ::CFURLGetFileSystemRepresentation(bundle_url.get(), + resolveAgainstBase, + (UInt8 *)dst, dst_len) != 0; } - return false; -} + } + return false; +} -CFStringRef -CFCBundle::GetIdentifier () const -{ - CFBundleRef bundle = get(); - if (bundle != NULL) - return ::CFBundleGetIdentifier (bundle); - return NULL; +CFStringRef CFCBundle::GetIdentifier() const { + CFBundleRef bundle = get(); + if (bundle != NULL) + return ::CFBundleGetIdentifier(bundle); + return NULL; } -CFTypeRef -CFCBundle::GetValueForInfoDictionaryKey(CFStringRef key) const -{ - CFBundleRef bundle = get(); - if (bundle != NULL) - return ::CFBundleGetValueForInfoDictionaryKey(bundle, key); - return NULL; +CFTypeRef CFCBundle::GetValueForInfoDictionaryKey(CFStringRef key) const { + CFBundleRef bundle = get(); + if (bundle != NULL) + return ::CFBundleGetValueForInfoDictionaryKey(bundle, key); + return NULL; } -CFURLRef -CFCBundle::CopyExecutableURL () const -{ - CFBundleRef bundle = get(); - if (bundle != NULL) - return CFBundleCopyExecutableURL(bundle); - return NULL; +CFURLRef CFCBundle::CopyExecutableURL() const { + CFBundleRef bundle = get(); + if (bundle != NULL) + return CFBundleCopyExecutableURL(bundle); + return NULL; } diff --git a/lldb/source/Host/macosx/cfcpp/CFCBundle.h b/lldb/source/Host/macosx/cfcpp/CFCBundle.h index 1cd1b68..9506b93 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCBundle.h +++ b/lldb/source/Host/macosx/cfcpp/CFCBundle.h @@ -12,39 +12,31 @@ #include "CFCReleaser.h" -class CFCBundle : public CFCReleaser<CFBundleRef> -{ +class CFCBundle : public CFCReleaser<CFBundleRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCBundle (const char *path = NULL); - CFCBundle (CFURLRef url); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCBundle(const char *path = NULL); + CFCBundle(CFURLRef url); - virtual - ~CFCBundle(); + virtual ~CFCBundle(); - CFURLRef - CopyExecutableURL () const; + CFURLRef CopyExecutableURL() const; - CFStringRef - GetIdentifier () const; + CFStringRef GetIdentifier() const; - CFTypeRef - GetValueForInfoDictionaryKey(CFStringRef key) const; + CFTypeRef GetValueForInfoDictionaryKey(CFStringRef key) const; - bool - GetPath (char *dst, size_t dst_len); + bool GetPath(char *dst, size_t dst_len); - bool - SetPath (const char *path); + bool SetPath(const char *path); private: - // Disallow copy and assignment constructors - CFCBundle(const CFCBundle&); + // Disallow copy and assignment constructors + CFCBundle(const CFCBundle &); - const CFCBundle& - operator=(const CFCBundle&); + const CFCBundle &operator=(const CFCBundle &); }; #endif // #ifndef CoreFoundationCPP_CFBundle_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCData.cpp b/lldb/source/Host/macosx/cfcpp/CFCData.cpp index 4f49368..95caded 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCData.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCData.cpp @@ -12,71 +12,55 @@ //---------------------------------------------------------------------- // CFCData constructor //---------------------------------------------------------------------- -CFCData::CFCData(CFDataRef data) : - CFCReleaser<CFDataRef>(data) -{ - -} +CFCData::CFCData(CFDataRef data) : CFCReleaser<CFDataRef>(data) {} //---------------------------------------------------------------------- // CFCData copy constructor //---------------------------------------------------------------------- -CFCData::CFCData(const CFCData& rhs) : - CFCReleaser<CFDataRef>(rhs) -{ - -} +CFCData::CFCData(const CFCData &rhs) : CFCReleaser<CFDataRef>(rhs) {} //---------------------------------------------------------------------- // CFCData copy constructor //---------------------------------------------------------------------- -CFCData& -CFCData::operator=(const CFCData& rhs) +CFCData &CFCData::operator=(const CFCData &rhs) { - if (this != &rhs) - *this = rhs; - return *this; + if (this != &rhs) + *this = rhs; + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCData::~CFCData() -{ -} - +CFCData::~CFCData() {} -CFIndex -CFCData::GetLength() const -{ - CFDataRef data = get(); - if (data) - return CFDataGetLength (data); - return 0; +CFIndex CFCData::GetLength() const { + CFDataRef data = get(); + if (data) + return CFDataGetLength(data); + return 0; } - -const uint8_t* -CFCData::GetBytePtr() const -{ - CFDataRef data = get(); - if (data) - return CFDataGetBytePtr (data); - return NULL; +const uint8_t *CFCData::GetBytePtr() const { + CFDataRef data = get(); + if (data) + return CFDataGetBytePtr(data); + return NULL; } -CFDataRef -CFCData::Serialize(CFPropertyListRef plist, CFPropertyListFormat format) -{ - CFAllocatorRef alloc = kCFAllocatorDefault; - reset(); - CFCReleaser<CFWriteStreamRef> stream (::CFWriteStreamCreateWithAllocatedBuffers (alloc, alloc)); - ::CFWriteStreamOpen (stream.get()); - CFIndex len = ::CFPropertyListWriteToStream (plist, stream.get(), format, NULL); - if (len > 0) - reset((CFDataRef)::CFWriteStreamCopyProperty (stream.get(), kCFStreamPropertyDataWritten)); - ::CFWriteStreamClose (stream.get()); - return get(); +CFDataRef CFCData::Serialize(CFPropertyListRef plist, + CFPropertyListFormat format) { + CFAllocatorRef alloc = kCFAllocatorDefault; + reset(); + CFCReleaser<CFWriteStreamRef> stream( + ::CFWriteStreamCreateWithAllocatedBuffers(alloc, alloc)); + ::CFWriteStreamOpen(stream.get()); + CFIndex len = + ::CFPropertyListWriteToStream(plist, stream.get(), format, NULL); + if (len > 0) + reset((CFDataRef)::CFWriteStreamCopyProperty(stream.get(), + kCFStreamPropertyDataWritten)); + ::CFWriteStreamClose(stream.get()); + return get(); } - diff --git a/lldb/source/Host/macosx/cfcpp/CFCData.h b/lldb/source/Host/macosx/cfcpp/CFCData.h index 6a718f5..e89d7be 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCData.h +++ b/lldb/source/Host/macosx/cfcpp/CFCData.h @@ -12,24 +12,24 @@ #include "CFCReleaser.h" -class CFCData : public CFCReleaser<CFDataRef> -{ +class CFCData : public CFCReleaser<CFDataRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCData(CFDataRef data = NULL); - CFCData(const CFCData& rhs); - CFCData& operator=(const CFCData& rhs); - virtual ~CFCData(); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCData(CFDataRef data = NULL); + CFCData(const CFCData &rhs); + CFCData &operator=(const CFCData &rhs); + virtual ~CFCData(); + + CFDataRef Serialize(CFPropertyListRef plist, CFPropertyListFormat format); + const uint8_t *GetBytePtr() const; + CFIndex GetLength() const; - CFDataRef Serialize(CFPropertyListRef plist, CFPropertyListFormat format); - const uint8_t* GetBytePtr () const; - CFIndex GetLength () const; protected: - //------------------------------------------------------------------ - // Classes that inherit from CFCData can see and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from CFCData can see and modify these + //------------------------------------------------------------------ }; #endif // #ifndef CoreFoundationCPP_CFData_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp index c3c0a11..0b62583 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp @@ -13,154 +13,128 @@ //---------------------------------------------------------------------- // CFCString constructor //---------------------------------------------------------------------- -CFCMutableArray::CFCMutableArray(CFMutableArrayRef s) : - CFCReleaser<CFMutableArrayRef> (s) -{ -} +CFCMutableArray::CFCMutableArray(CFMutableArrayRef s) + : CFCReleaser<CFMutableArrayRef>(s) {} //---------------------------------------------------------------------- // CFCMutableArray copy constructor //---------------------------------------------------------------------- -CFCMutableArray::CFCMutableArray(const CFCMutableArray& rhs) : - CFCReleaser<CFMutableArrayRef> (rhs) // NOTE: this won't make a copy of the array, just add a new reference to it -{ -} +CFCMutableArray::CFCMutableArray(const CFCMutableArray &rhs) + : CFCReleaser<CFMutableArrayRef>(rhs) // NOTE: this won't make a copy of the + // array, just add a new reference to + // it +{} //---------------------------------------------------------------------- // CFCMutableArray copy constructor //---------------------------------------------------------------------- -CFCMutableArray& -CFCMutableArray::operator=(const CFCMutableArray& rhs) -{ - if (this != &rhs) - *this = rhs; // NOTE: this operator won't make a copy of the array, just add a new reference to it - return *this; +CFCMutableArray &CFCMutableArray::operator=(const CFCMutableArray &rhs) { + if (this != &rhs) + *this = rhs; // NOTE: this operator won't make a copy of the array, just add + // a new reference to it + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCMutableArray::~CFCMutableArray() -{ -} +CFCMutableArray::~CFCMutableArray() {} - -CFIndex -CFCMutableArray::GetCount() const -{ - CFMutableArrayRef array = get(); - if (array) - return ::CFArrayGetCount (array); - return 0; +CFIndex CFCMutableArray::GetCount() const { + CFMutableArrayRef array = get(); + if (array) + return ::CFArrayGetCount(array); + return 0; } -CFIndex -CFCMutableArray::GetCountOfValue(CFRange range, const void *value) const -{ - CFMutableArrayRef array = get(); - if (array) - return ::CFArrayGetCountOfValue (array, range, value); - return 0; +CFIndex CFCMutableArray::GetCountOfValue(CFRange range, + const void *value) const { + CFMutableArrayRef array = get(); + if (array) + return ::CFArrayGetCountOfValue(array, range, value); + return 0; } -CFIndex -CFCMutableArray::GetCountOfValue(const void *value) const -{ - CFMutableArrayRef array = get(); - if (array) - return ::CFArrayGetCountOfValue (array, CFRangeMake(0, GetCount()), value); - return 0; +CFIndex CFCMutableArray::GetCountOfValue(const void *value) const { + CFMutableArrayRef array = get(); + if (array) + return ::CFArrayGetCountOfValue(array, CFRangeMake(0, GetCount()), value); + return 0; } -const void * -CFCMutableArray::GetValueAtIndex(CFIndex idx) const -{ - CFMutableArrayRef array = get(); - if (array) - { - const CFIndex num_array_items = ::CFArrayGetCount (array); - if (0 <= idx && idx < num_array_items) - { - return ::CFArrayGetValueAtIndex (array, idx); - } +const void *CFCMutableArray::GetValueAtIndex(CFIndex idx) const { + CFMutableArrayRef array = get(); + if (array) { + const CFIndex num_array_items = ::CFArrayGetCount(array); + if (0 <= idx && idx < num_array_items) { + return ::CFArrayGetValueAtIndex(array, idx); } - return NULL; + } + return NULL; } -bool -CFCMutableArray::SetValueAtIndex(CFIndex idx, const void *value) -{ - CFMutableArrayRef array = get(); - if (array != NULL) - { - const CFIndex num_array_items = ::CFArrayGetCount (array); - if (0 <= idx && idx < num_array_items) - { - ::CFArraySetValueAtIndex (array, idx, value); - return true; - } +bool CFCMutableArray::SetValueAtIndex(CFIndex idx, const void *value) { + CFMutableArrayRef array = get(); + if (array != NULL) { + const CFIndex num_array_items = ::CFArrayGetCount(array); + if (0 <= idx && idx < num_array_items) { + ::CFArraySetValueAtIndex(array, idx, value); + return true; } - return false; + } + return false; } - -bool -CFCMutableArray::AppendValue(const void *value, bool can_create) -{ - CFMutableArrayRef array = get(); - if (array == NULL) - { - if (can_create == false) - return false; - array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - reset ( array ); - } - if (array != NULL) - { - ::CFArrayAppendValue(array, value); - return true; - } - return false; +bool CFCMutableArray::AppendValue(const void *value, bool can_create) { + CFMutableArrayRef array = get(); + if (array == NULL) { + if (can_create == false) + return false; + array = + ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + reset(array); + } + if (array != NULL) { + ::CFArrayAppendValue(array, value); + return true; + } + return false; } - -bool -CFCMutableArray::AppendCStringAsCFString (const char *s, CFStringEncoding encoding, bool can_create) -{ - CFMutableArrayRef array = get(); - if (array == NULL) - { - if (can_create == false) - return false; - array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - reset ( array ); - } - if (array != NULL) - { - CFCString cf_str (s, encoding); - ::CFArrayAppendValue (array, cf_str.get()); - return true; - } - return false; +bool CFCMutableArray::AppendCStringAsCFString(const char *s, + CFStringEncoding encoding, + bool can_create) { + CFMutableArrayRef array = get(); + if (array == NULL) { + if (can_create == false) + return false; + array = + ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + reset(array); + } + if (array != NULL) { + CFCString cf_str(s, encoding); + ::CFArrayAppendValue(array, cf_str.get()); + return true; + } + return false; } -bool -CFCMutableArray::AppendFileSystemRepresentationAsCFString (const char *s, bool can_create) -{ - CFMutableArrayRef array = get(); - if (array == NULL) - { - if (can_create == false) - return false; - array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - reset ( array ); - } - if (array != NULL) - { - CFCString cf_path; - cf_path.SetFileSystemRepresentation(s); - ::CFArrayAppendValue (array, cf_path.get()); - return true; - } - return false; +bool CFCMutableArray::AppendFileSystemRepresentationAsCFString( + const char *s, bool can_create) { + CFMutableArrayRef array = get(); + if (array == NULL) { + if (can_create == false) + return false; + array = + ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + reset(array); + } + if (array != NULL) { + CFCString cf_path; + cf_path.SetFileSystemRepresentation(s); + ::CFArrayAppendValue(array, cf_path.get()); + return true; + } + return false; } diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h index f78cd92..23d1f93 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h @@ -12,28 +12,35 @@ #include "CFCReleaser.h" -class CFCMutableArray : public CFCReleaser<CFMutableArrayRef> -{ +class CFCMutableArray : public CFCReleaser<CFMutableArrayRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCMutableArray(CFMutableArrayRef array = NULL); - CFCMutableArray(const CFCMutableArray& rhs); // This will copy the array contents into a new array - CFCMutableArray& operator=(const CFCMutableArray& rhs); // This will re-use the same array and just bump the ref count - virtual ~CFCMutableArray(); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCMutableArray(CFMutableArrayRef array = NULL); + CFCMutableArray(const CFCMutableArray &rhs); // This will copy the array + // contents into a new array + CFCMutableArray &operator=(const CFCMutableArray &rhs); // This will re-use + // the same array and + // just bump the ref + // count + virtual ~CFCMutableArray(); - CFIndex GetCount() const; - CFIndex GetCountOfValue(const void *value) const; - CFIndex GetCountOfValue(CFRange range, const void *value) const; - const void * GetValueAtIndex(CFIndex idx) const; - bool SetValueAtIndex(CFIndex idx, const void *value); - bool AppendValue(const void *value, bool can_create = true); // Appends value and optionally creates a CFCMutableArray if this class doesn't contain one - bool AppendCStringAsCFString (const char *cstr, - CFStringEncoding encoding = kCFStringEncodingUTF8, - bool can_create = true); - bool AppendFileSystemRepresentationAsCFString (const char *s, - bool can_create = true); + CFIndex GetCount() const; + CFIndex GetCountOfValue(const void *value) const; + CFIndex GetCountOfValue(CFRange range, const void *value) const; + const void *GetValueAtIndex(CFIndex idx) const; + bool SetValueAtIndex(CFIndex idx, const void *value); + bool AppendValue(const void *value, + bool can_create = true); // Appends value and optionally + // creates a CFCMutableArray if this + // class doesn't contain one + bool + AppendCStringAsCFString(const char *cstr, + CFStringEncoding encoding = kCFStringEncodingUTF8, + bool can_create = true); + bool AppendFileSystemRepresentationAsCFString(const char *s, + bool can_create = true); }; #endif // #ifndef CoreFoundationCPP_CFMutableArray_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp b/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp index bce023b..201ec9a 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp @@ -12,518 +12,458 @@ //---------------------------------------------------------------------- // CFCString constructor //---------------------------------------------------------------------- -CFCMutableDictionary::CFCMutableDictionary(CFMutableDictionaryRef s) : - CFCReleaser<CFMutableDictionaryRef> (s) -{ -} +CFCMutableDictionary::CFCMutableDictionary(CFMutableDictionaryRef s) + : CFCReleaser<CFMutableDictionaryRef>(s) {} //---------------------------------------------------------------------- // CFCMutableDictionary copy constructor //---------------------------------------------------------------------- -CFCMutableDictionary::CFCMutableDictionary(const CFCMutableDictionary& rhs) : - CFCReleaser<CFMutableDictionaryRef> (rhs) -{ -} +CFCMutableDictionary::CFCMutableDictionary(const CFCMutableDictionary &rhs) + : CFCReleaser<CFMutableDictionaryRef>(rhs) {} //---------------------------------------------------------------------- // CFCMutableDictionary copy constructor //---------------------------------------------------------------------- -const CFCMutableDictionary& -CFCMutableDictionary::operator=(const CFCMutableDictionary& rhs) -{ - if (this != &rhs) - *this = rhs; - return *this; +const CFCMutableDictionary &CFCMutableDictionary:: +operator=(const CFCMutableDictionary &rhs) { + if (this != &rhs) + *this = rhs; + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCMutableDictionary::~CFCMutableDictionary() -{ -} - +CFCMutableDictionary::~CFCMutableDictionary() {} -CFIndex -CFCMutableDictionary::GetCount() const -{ - CFMutableDictionaryRef dict = get(); - if (dict) - return ::CFDictionaryGetCount (dict); - return 0; +CFIndex CFCMutableDictionary::GetCount() const { + CFMutableDictionaryRef dict = get(); + if (dict) + return ::CFDictionaryGetCount(dict); + return 0; } -CFIndex -CFCMutableDictionary::GetCountOfKey(const void *key) const +CFIndex CFCMutableDictionary::GetCountOfKey(const void *key) const { - CFMutableDictionaryRef dict = get(); - if (dict) - return ::CFDictionaryGetCountOfKey (dict, key); - return 0; + CFMutableDictionaryRef dict = get(); + if (dict) + return ::CFDictionaryGetCountOfKey(dict, key); + return 0; } -CFIndex -CFCMutableDictionary::GetCountOfValue(const void *value) const +CFIndex CFCMutableDictionary::GetCountOfValue(const void *value) const { - CFMutableDictionaryRef dict = get(); - if (dict) - return ::CFDictionaryGetCountOfValue (dict, value); - return 0; + CFMutableDictionaryRef dict = get(); + if (dict) + return ::CFDictionaryGetCountOfValue(dict, value); + return 0; } -void -CFCMutableDictionary::GetKeysAndValues(const void **keys, const void **values) const -{ - CFMutableDictionaryRef dict = get(); - if (dict) - ::CFDictionaryGetKeysAndValues (dict, keys, values); +void CFCMutableDictionary::GetKeysAndValues(const void **keys, + const void **values) const { + CFMutableDictionaryRef dict = get(); + if (dict) + ::CFDictionaryGetKeysAndValues(dict, keys, values); } - -const void * -CFCMutableDictionary::GetValue(const void *key) const +const void *CFCMutableDictionary::GetValue(const void *key) const { - CFMutableDictionaryRef dict = get(); - if (dict) - return ::CFDictionaryGetValue (dict, key); - return NULL; + CFMutableDictionaryRef dict = get(); + if (dict) + return ::CFDictionaryGetValue(dict, key); + return NULL; } Boolean -CFCMutableDictionary::GetValueIfPresent(const void *key, const void **value_handle) const -{ - CFMutableDictionaryRef dict = get(); - if (dict) - return ::CFDictionaryGetValueIfPresent (dict, key, value_handle); - return false; -} - - -CFMutableDictionaryRef -CFCMutableDictionary::Dictionary(bool can_create) -{ - CFMutableDictionaryRef dict = get(); - if (can_create && dict == NULL) - { - dict = ::CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - reset ( dict ); +CFCMutableDictionary::GetValueIfPresent(const void *key, + const void **value_handle) const { + CFMutableDictionaryRef dict = get(); + if (dict) + return ::CFDictionaryGetValueIfPresent(dict, key, value_handle); + return false; +} + +CFMutableDictionaryRef CFCMutableDictionary::Dictionary(bool can_create) { + CFMutableDictionaryRef dict = get(); + if (can_create && dict == NULL) { + dict = ::CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + reset(dict); + } + return dict; +} + +bool CFCMutableDictionary::AddValue(CFStringRef key, const void *value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, value); + return true; + } + return false; +} + +bool CFCMutableDictionary::SetValue(CFStringRef key, const void *value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, value); + return true; + } + return false; +} + +bool CFCMutableDictionary::AddValueSInt8(CFStringRef key, int8_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return dict; -} - -bool -CFCMutableDictionary::AddValue(CFStringRef key, const void *value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, value); - return true; + } + return false; +} + +bool CFCMutableDictionary::SetValueSInt8(CFStringRef key, int8_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValue(CFStringRef key, const void *value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, value); - return true; + } + return false; +} + +bool CFCMutableDictionary::AddValueSInt16(CFStringRef key, int16_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueSInt8(CFStringRef key, int8_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt8Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueSInt16(CFStringRef key, int16_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueSInt8(CFStringRef key, int8_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt8Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueSInt32(CFStringRef key, int32_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueSInt16(CFStringRef key, int16_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueSInt32(CFStringRef key, int32_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueSInt16(CFStringRef key, int16_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueSInt64(CFStringRef key, int64_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueSInt32(CFStringRef key, int32_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueSInt64(CFStringRef key, int64_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueSInt32(CFStringRef key, int32_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueUInt8(CFStringRef key, uint8_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int16_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueSInt64(CFStringRef key, int64_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueUInt8(CFStringRef key, uint8_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int16_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueSInt64(CFStringRef key, int64_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueUInt16(CFStringRef key, uint16_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int32_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueUInt8(CFStringRef key, uint8_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int16_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueUInt16(CFStringRef key, uint16_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int32_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueUInt8(CFStringRef key, uint8_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int16_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueUInt32(CFStringRef key, uint32_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int64_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - - -bool -CFCMutableDictionary::AddValueUInt16(CFStringRef key, uint16_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int32_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueUInt32(CFStringRef key, uint32_t value, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + // Have to promote to the next size type so things don't appear negative of + // the MSBit is set... + int64_t sval = value; + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &sval)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueUInt16(CFStringRef key, uint16_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int32_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } - } - return false; -} - -bool -CFCMutableDictionary::AddValueUInt32(CFStringRef key, uint32_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int64_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } - } - return false; -} - -bool -CFCMutableDictionary::SetValueUInt32(CFStringRef key, uint32_t value, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - // Have to promote to the next size type so things don't appear negative of the MSBit is set... - int64_t sval = value; - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &sval)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } - } - return false; -} - - -bool -CFCMutableDictionary::AddValueUInt64(CFStringRef key, uint64_t value, bool can_create) -{ - 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. - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueUInt64(CFStringRef key, uint64_t value, + bool can_create) { + 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. + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - - -bool -CFCMutableDictionary::SetValueUInt64(CFStringRef key, uint64_t value, bool can_create) -{ - 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. - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueUInt64(CFStringRef key, uint64_t value, + bool can_create) { + 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. + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueDouble(CFStringRef key, double value, bool can_create) -{ - 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. - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueDouble(CFStringRef key, double value, + bool can_create) { + 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. + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueDouble(CFStringRef key, double value, bool can_create) -{ - 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. - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value)); - if (cf_number.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_number.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueDouble(CFStringRef key, double value, + bool can_create) { + 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. + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); + if (cf_number.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_number.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::AddValueCString(CFStringRef key, const char *cstr, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCString cf_str(cstr, kCFStringEncodingUTF8); - if (cf_str.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionaryAddValue (dict, key, cf_str.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::AddValueCString(CFStringRef key, const char *cstr, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCString cf_str(cstr, kCFStringEncodingUTF8); + if (cf_str.get()) { + // Let the dictionary own the CFNumber + ::CFDictionaryAddValue(dict, key, cf_str.get()); + return true; } - return false; -} - -bool -CFCMutableDictionary::SetValueCString(CFStringRef key, const char *cstr, bool can_create) -{ - CFMutableDictionaryRef dict = Dictionary(can_create); - if (dict != NULL) - { - CFCString cf_str(cstr, kCFStringEncodingUTF8); - if (cf_str.get()) - { - // Let the dictionary own the CFNumber - ::CFDictionarySetValue (dict, key, cf_str.get()); - return true; - } + } + return false; +} + +bool CFCMutableDictionary::SetValueCString(CFStringRef key, const char *cstr, + bool can_create) { + CFMutableDictionaryRef dict = Dictionary(can_create); + if (dict != NULL) { + CFCString cf_str(cstr, kCFStringEncodingUTF8); + if (cf_str.get()) { + // Let the dictionary own the CFNumber + ::CFDictionarySetValue(dict, key, cf_str.get()); + return true; } - return false; + } + return false; } - -void -CFCMutableDictionary::RemoveAllValues() -{ - CFMutableDictionaryRef dict = get(); - if (dict) - ::CFDictionaryRemoveAllValues(dict); +void CFCMutableDictionary::RemoveAllValues() { + CFMutableDictionaryRef dict = get(); + if (dict) + ::CFDictionaryRemoveAllValues(dict); } -void -CFCMutableDictionary::RemoveValue(const void *value) -{ - CFMutableDictionaryRef dict = get(); - if (dict) - ::CFDictionaryRemoveValue(dict, value); +void CFCMutableDictionary::RemoveValue(const void *value) { + CFMutableDictionaryRef dict = get(); + if (dict) + ::CFDictionaryRemoveValue(dict, value); } -void -CFCMutableDictionary::ReplaceValue(const void *key, const void *value) -{ - CFMutableDictionaryRef dict = get(); - if (dict) - ::CFDictionaryReplaceValue (dict, key, value); +void CFCMutableDictionary::ReplaceValue(const void *key, const void *value) { + CFMutableDictionaryRef dict = get(); + if (dict) + ::CFDictionaryReplaceValue(dict, key, value); } - diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.h b/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.h index a1cfb68..b30a2e6 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.h +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableDictionary.h @@ -12,68 +12,64 @@ #include "CFCReleaser.h" -class CFCMutableDictionary : public CFCReleaser<CFMutableDictionaryRef> -{ +class CFCMutableDictionary : public CFCReleaser<CFMutableDictionaryRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCMutableDictionary(CFMutableDictionaryRef s = NULL); - CFCMutableDictionary(const CFCMutableDictionary& rhs); - virtual ~CFCMutableDictionary(); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCMutableDictionary(CFMutableDictionaryRef s = NULL); + CFCMutableDictionary(const CFCMutableDictionary &rhs); + virtual ~CFCMutableDictionary(); - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - const CFCMutableDictionary& - operator=(const CFCMutableDictionary& rhs); - - - CFIndex GetCount() const; - CFIndex GetCountOfKey(const void *value) const; - CFIndex GetCountOfValue(const void *value) const; - void GetKeysAndValues(const void **keys, const void **values) const; - const void * GetValue(const void *key) const; - Boolean GetValueIfPresent(const void *key, const void **value_handle) const; - bool AddValue(CFStringRef key, const void *value, bool can_create = false); - bool SetValue(CFStringRef key, const void *value, bool can_create = false); - bool AddValueSInt8(CFStringRef key, int8_t value, bool can_create = false); - bool SetValueSInt8(CFStringRef key, int8_t value, bool can_create = false); - bool AddValueSInt16(CFStringRef key, int16_t value, bool can_create = false); - bool SetValueSInt16(CFStringRef key, int16_t value, bool can_create = false); - bool AddValueSInt32(CFStringRef key, int32_t value, bool can_create = false); - bool SetValueSInt32(CFStringRef key, int32_t value, bool can_create = false); - bool AddValueSInt64(CFStringRef key, int64_t value, bool can_create = false); - bool SetValueSInt64(CFStringRef key, int64_t value, bool can_create = false); - bool AddValueUInt8(CFStringRef key, uint8_t value, bool can_create = false); - bool SetValueUInt8(CFStringRef key, uint8_t value, bool can_create = false); - bool AddValueUInt16(CFStringRef key, uint16_t value, bool can_create = false); - bool SetValueUInt16(CFStringRef key, uint16_t value, bool can_create = false); - bool AddValueUInt32(CFStringRef key, uint32_t value, bool can_create = false); - bool SetValueUInt32(CFStringRef key, uint32_t value, bool can_create = false); - bool AddValueUInt64(CFStringRef key, uint64_t value, bool can_create = false); - bool SetValueUInt64(CFStringRef key, uint64_t value, bool can_create = false); - bool AddValueDouble(CFStringRef key, double value, bool can_create = false); - bool SetValueDouble(CFStringRef key, double value, bool can_create = false); - bool AddValueCString(CFStringRef key, const char *cstr, bool can_create = false); - bool SetValueCString(CFStringRef key, const char *cstr, bool can_create = false); - void RemoveValue(const void *value); - void ReplaceValue(const void *key, const void *value); - void RemoveAllValues(); - CFMutableDictionaryRef Dictionary(bool can_create); + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const CFCMutableDictionary &operator=(const CFCMutableDictionary &rhs); + CFIndex GetCount() const; + CFIndex GetCountOfKey(const void *value) const; + CFIndex GetCountOfValue(const void *value) const; + void GetKeysAndValues(const void **keys, const void **values) const; + const void *GetValue(const void *key) const; + Boolean GetValueIfPresent(const void *key, const void **value_handle) const; + bool AddValue(CFStringRef key, const void *value, bool can_create = false); + bool SetValue(CFStringRef key, const void *value, bool can_create = false); + bool AddValueSInt8(CFStringRef key, int8_t value, bool can_create = false); + bool SetValueSInt8(CFStringRef key, int8_t value, bool can_create = false); + bool AddValueSInt16(CFStringRef key, int16_t value, bool can_create = false); + bool SetValueSInt16(CFStringRef key, int16_t value, bool can_create = false); + bool AddValueSInt32(CFStringRef key, int32_t value, bool can_create = false); + bool SetValueSInt32(CFStringRef key, int32_t value, bool can_create = false); + bool AddValueSInt64(CFStringRef key, int64_t value, bool can_create = false); + bool SetValueSInt64(CFStringRef key, int64_t value, bool can_create = false); + bool AddValueUInt8(CFStringRef key, uint8_t value, bool can_create = false); + bool SetValueUInt8(CFStringRef key, uint8_t value, bool can_create = false); + bool AddValueUInt16(CFStringRef key, uint16_t value, bool can_create = false); + bool SetValueUInt16(CFStringRef key, uint16_t value, bool can_create = false); + bool AddValueUInt32(CFStringRef key, uint32_t value, bool can_create = false); + bool SetValueUInt32(CFStringRef key, uint32_t value, bool can_create = false); + bool AddValueUInt64(CFStringRef key, uint64_t value, bool can_create = false); + bool SetValueUInt64(CFStringRef key, uint64_t value, bool can_create = false); + bool AddValueDouble(CFStringRef key, double value, bool can_create = false); + bool SetValueDouble(CFStringRef key, double value, bool can_create = false); + bool AddValueCString(CFStringRef key, const char *cstr, + bool can_create = false); + bool SetValueCString(CFStringRef key, const char *cstr, + bool can_create = false); + void RemoveValue(const void *value); + void ReplaceValue(const void *key, const void *value); + void RemoveAllValues(); + CFMutableDictionaryRef Dictionary(bool can_create); protected: - //------------------------------------------------------------------ - // Classes that inherit from CFCMutableDictionary can see and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from CFCMutableDictionary can see and modify these + //------------------------------------------------------------------ private: - //------------------------------------------------------------------ - // For CFCMutableDictionary only - //------------------------------------------------------------------ - + //------------------------------------------------------------------ + // For CFCMutableDictionary only + //------------------------------------------------------------------ }; - -#endif // CoreFoundationCPP_CFMutableDictionary_h_ +#endif // CoreFoundationCPP_CFMutableDictionary_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableSet.cpp b/lldb/source/Host/macosx/cfcpp/CFCMutableSet.cpp index afc09e1..c339e95 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableSet.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableSet.cpp @@ -17,98 +17,73 @@ //---------------------------------------------------------------------- // CFCString constructor //---------------------------------------------------------------------- -CFCMutableSet::CFCMutableSet(CFMutableSetRef s) : - CFCReleaser<CFMutableSetRef> (s) -{ -} +CFCMutableSet::CFCMutableSet(CFMutableSetRef s) + : CFCReleaser<CFMutableSetRef>(s) {} //---------------------------------------------------------------------- // CFCMutableSet copy constructor //---------------------------------------------------------------------- -CFCMutableSet::CFCMutableSet(const CFCMutableSet& rhs) : - CFCReleaser<CFMutableSetRef> (rhs) -{ -} +CFCMutableSet::CFCMutableSet(const CFCMutableSet &rhs) + : CFCReleaser<CFMutableSetRef>(rhs) {} //---------------------------------------------------------------------- // CFCMutableSet copy constructor //---------------------------------------------------------------------- -const CFCMutableSet& -CFCMutableSet::operator=(const CFCMutableSet& rhs) -{ - if (this != &rhs) - *this = rhs; - return *this; +const CFCMutableSet &CFCMutableSet::operator=(const CFCMutableSet &rhs) { + if (this != &rhs) + *this = rhs; + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCMutableSet::~CFCMutableSet() -{ -} +CFCMutableSet::~CFCMutableSet() {} - -CFIndex -CFCMutableSet::GetCount() const -{ - CFMutableSetRef set = get(); - if (set) - return ::CFSetGetCount (set); - return 0; +CFIndex CFCMutableSet::GetCount() const { + CFMutableSetRef set = get(); + if (set) + return ::CFSetGetCount(set); + return 0; } -CFIndex -CFCMutableSet::GetCountOfValue(const void *value) const -{ - CFMutableSetRef set = get(); - if (set) - return ::CFSetGetCountOfValue (set, value); - return 0; +CFIndex CFCMutableSet::GetCountOfValue(const void *value) const { + CFMutableSetRef set = get(); + if (set) + return ::CFSetGetCountOfValue(set, value); + return 0; } -const void * -CFCMutableSet::GetValue(const void *value) const -{ - CFMutableSetRef set = get(); - if (set) - return ::CFSetGetValue(set, value); - return NULL; +const void *CFCMutableSet::GetValue(const void *value) const { + CFMutableSetRef set = get(); + if (set) + return ::CFSetGetValue(set, value); + return NULL; } - -const void * -CFCMutableSet::AddValue(const void *value, bool can_create) -{ - CFMutableSetRef set = get(); - if (set == NULL) - { - if (can_create == false) - return NULL; - set = ::CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); - reset ( set ); - } - if (set != NULL) - { - ::CFSetAddValue(set, value); - return value; - } - return NULL; +const void *CFCMutableSet::AddValue(const void *value, bool can_create) { + CFMutableSetRef set = get(); + if (set == NULL) { + if (can_create == false) + return NULL; + set = ::CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + reset(set); + } + if (set != NULL) { + ::CFSetAddValue(set, value); + return value; + } + return NULL; } -void -CFCMutableSet::RemoveValue(const void *value) -{ - CFMutableSetRef set = get(); - if (set) - ::CFSetRemoveValue(set, value); +void CFCMutableSet::RemoveValue(const void *value) { + CFMutableSetRef set = get(); + if (set) + ::CFSetRemoveValue(set, value); } -void -CFCMutableSet::RemoveAllValues() -{ - CFMutableSetRef set = get(); - if (set) - ::CFSetRemoveAllValues(set); +void CFCMutableSet::RemoveAllValues() { + CFMutableSetRef set = get(); + if (set) + ::CFSetRemoveAllValues(set); } - diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableSet.h b/lldb/source/Host/macosx/cfcpp/CFCMutableSet.h index 78f7a8b..1459b7e 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCMutableSet.h +++ b/lldb/source/Host/macosx/cfcpp/CFCMutableSet.h @@ -12,42 +12,36 @@ #include "CFCReleaser.h" -class CFCMutableSet : public CFCReleaser<CFMutableSetRef> -{ +class CFCMutableSet : public CFCReleaser<CFMutableSetRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCMutableSet(CFMutableSetRef s = NULL); - CFCMutableSet(const CFCMutableSet& rhs); - virtual ~CFCMutableSet(); - - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - const CFCMutableSet& - operator=(const CFCMutableSet& rhs); - - - CFIndex GetCount() const; - CFIndex GetCountOfValue(const void *value) const; - const void * GetValue(const void *value) const; - const void * AddValue(const void *value, bool can_create); - void RemoveValue(const void *value); - void RemoveAllValues(); - - + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCMutableSet(CFMutableSetRef s = NULL); + CFCMutableSet(const CFCMutableSet &rhs); + virtual ~CFCMutableSet(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const CFCMutableSet &operator=(const CFCMutableSet &rhs); + + CFIndex GetCount() const; + CFIndex GetCountOfValue(const void *value) const; + const void *GetValue(const void *value) const; + const void *AddValue(const void *value, bool can_create); + void RemoveValue(const void *value); + void RemoveAllValues(); protected: - //------------------------------------------------------------------ - // Classes that inherit from CFCMutableSet can see and modify these - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Classes that inherit from CFCMutableSet can see and modify these + //------------------------------------------------------------------ private: - //------------------------------------------------------------------ - // For CFCMutableSet only - //------------------------------------------------------------------ - + //------------------------------------------------------------------ + // For CFCMutableSet only + //------------------------------------------------------------------ }; -#endif // CoreFoundationCPP_CFMutableSet_h_ +#endif // CoreFoundationCPP_CFMutableSet_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCReleaser.h b/lldb/source/Host/macosx/cfcpp/CFCReleaser.h index 67dd2ea..c596d1e 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCReleaser.h +++ b/lldb/source/Host/macosx/cfcpp/CFCReleaser.h @@ -26,133 +26,103 @@ // pointer, it is designed to relinquish ownership of the pointer just // like std:auto_ptr<T>::release() does. //---------------------------------------------------------------------- -template <class T> -class CFCReleaser -{ +template <class T> class CFCReleaser { public: - //---------------------------------------------------------- - // Constructor that takes a pointer to a CF object that is - // to be released when this object goes out of scope - //---------------------------------------------------------- - CFCReleaser(T ptr = NULL) : - _ptr(ptr) - { - } - - //---------------------------------------------------------- - // Copy constructor - // - // Note that copying a CFCReleaser will not transfer - // ownership of the contained pointer, but it will bump its - // reference count. This is where this class differs from - // std::auto_ptr. - //---------------------------------------------------------- - CFCReleaser(const CFCReleaser& rhs) : - _ptr(rhs.get()) - { - if (get()) - ::CFRetain(get()); - } - - - //---------------------------------------------------------- - // The destructor will release the pointer that it contains - // if it has a valid pointer. - //---------------------------------------------------------- - virtual ~CFCReleaser() - { - reset(); - } - - //---------------------------------------------------------- - // Assignment operator. - // - // Note that assigning one CFCReleaser to another will - // not transfer ownership of the contained pointer, but it - // will bump its reference count. This is where this class - // differs from std::auto_ptr. - //---------------------------------------------------------- - CFCReleaser& - operator= (const CFCReleaser<T>& rhs) - { - if (this != &rhs) - { - // Replace our owned pointer with the new one - reset(rhs.get()); - // Retain the current pointer that we own - if (get()) - ::CFRetain(get()); - } - return *this; - } - - //---------------------------------------------------------- - // Get the address of the contained type in case it needs - // to be passed to a function that will fill in a pointer - // value. The function currently will assert if _ptr is not - // NULL because the only time this method should be used is - // if another function will modify the contents, and we - // could leak a pointer if this is not NULL. If the - // assertion fires, check the offending code, or call - // reset() prior to using the "ptr_address()" member to make - // sure any owned objects has CFRelease called on it. - // I had to add the "enforce_null" bool here because some - // API's require the pointer address even though they don't change it. - //---------------------------------------------------------- - T* - ptr_address(bool enforce_null = true) - { - if (enforce_null) - assert (_ptr == NULL); - return &_ptr; - } - - //---------------------------------------------------------- - // Access the pointer itself - //---------------------------------------------------------- - T - get() - { - return _ptr; - } - - const T - get() const - { - return _ptr; - } - - - //---------------------------------------------------------- - // Set a new value for the pointer and CFRelease our old - // value if we had a valid one. - //---------------------------------------------------------- - void - reset(T ptr = NULL) - { - if ((_ptr != NULL) && (ptr != _ptr)) - ::CFRelease(_ptr); - _ptr = ptr; - } - - //---------------------------------------------------------- - // Release ownership without calling CFRelease. This class - // is designed to mimic std::auto_ptr<T>, so the release - // method releases ownership of the contained pointer - // and does NOT call CFRelease. - //---------------------------------------------------------- - T - release() - { - T tmp = _ptr; - _ptr = NULL; - return tmp; + //---------------------------------------------------------- + // Constructor that takes a pointer to a CF object that is + // to be released when this object goes out of scope + //---------------------------------------------------------- + CFCReleaser(T ptr = NULL) : _ptr(ptr) {} + + //---------------------------------------------------------- + // Copy constructor + // + // Note that copying a CFCReleaser will not transfer + // ownership of the contained pointer, but it will bump its + // reference count. This is where this class differs from + // std::auto_ptr. + //---------------------------------------------------------- + CFCReleaser(const CFCReleaser &rhs) : _ptr(rhs.get()) { + if (get()) + ::CFRetain(get()); + } + + //---------------------------------------------------------- + // The destructor will release the pointer that it contains + // if it has a valid pointer. + //---------------------------------------------------------- + virtual ~CFCReleaser() { reset(); } + + //---------------------------------------------------------- + // Assignment operator. + // + // Note that assigning one CFCReleaser to another will + // not transfer ownership of the contained pointer, but it + // will bump its reference count. This is where this class + // differs from std::auto_ptr. + //---------------------------------------------------------- + CFCReleaser &operator=(const CFCReleaser<T> &rhs) { + if (this != &rhs) { + // Replace our owned pointer with the new one + reset(rhs.get()); + // Retain the current pointer that we own + if (get()) + ::CFRetain(get()); } + return *this; + } + + //---------------------------------------------------------- + // Get the address of the contained type in case it needs + // to be passed to a function that will fill in a pointer + // value. The function currently will assert if _ptr is not + // NULL because the only time this method should be used is + // if another function will modify the contents, and we + // could leak a pointer if this is not NULL. If the + // assertion fires, check the offending code, or call + // reset() prior to using the "ptr_address()" member to make + // sure any owned objects has CFRelease called on it. + // I had to add the "enforce_null" bool here because some + // API's require the pointer address even though they don't change it. + //---------------------------------------------------------- + T *ptr_address(bool enforce_null = true) { + if (enforce_null) + assert(_ptr == NULL); + return &_ptr; + } + + //---------------------------------------------------------- + // Access the pointer itself + //---------------------------------------------------------- + T get() { return _ptr; } + + const T get() const { return _ptr; } + + //---------------------------------------------------------- + // Set a new value for the pointer and CFRelease our old + // value if we had a valid one. + //---------------------------------------------------------- + void reset(T ptr = NULL) { + if ((_ptr != NULL) && (ptr != _ptr)) + ::CFRelease(_ptr); + _ptr = ptr; + } + + //---------------------------------------------------------- + // Release ownership without calling CFRelease. This class + // is designed to mimic std::auto_ptr<T>, so the release + // method releases ownership of the contained pointer + // and does NOT call CFRelease. + //---------------------------------------------------------- + T release() { + T tmp = _ptr; + _ptr = NULL; + return tmp; + } private: - T _ptr; + T _ptr; }; -#endif // #ifdef __cplusplus -#endif // #ifndef CoreFoundationCPP_CFReleaser_h_ - +#endif // #ifdef __cplusplus +#endif // #ifndef CoreFoundationCPP_CFReleaser_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CFCString.cpp b/lldb/source/Host/macosx/cfcpp/CFCString.cpp index 81a96b8..0d3853c 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCString.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCString.cpp @@ -8,151 +8,123 @@ //===----------------------------------------------------------------------===// #include "CFCString.h" -#include <string> #include <glob.h> +#include <string> //---------------------------------------------------------------------- // CFCString constructor //---------------------------------------------------------------------- -CFCString::CFCString(CFStringRef s) : - CFCReleaser<CFStringRef> (s) -{ -} +CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {} //---------------------------------------------------------------------- // CFCString copy constructor //---------------------------------------------------------------------- -CFCString::CFCString(const CFCString& rhs) : - CFCReleaser<CFStringRef> (rhs) -{ - -} +CFCString::CFCString(const CFCString &rhs) : CFCReleaser<CFStringRef>(rhs) {} //---------------------------------------------------------------------- // CFCString copy constructor //---------------------------------------------------------------------- -CFCString& -CFCString::operator=(const CFCString& rhs) -{ - if (this != &rhs) - *this = rhs; - return *this; +CFCString &CFCString::operator=(const CFCString &rhs) { + if (this != &rhs) + *this = rhs; + return *this; } -CFCString::CFCString (const char *cstr, CFStringEncoding cstr_encoding) : - CFCReleaser<CFStringRef> () -{ - if (cstr && cstr[0]) - { - reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); - } +CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding) + : CFCReleaser<CFStringRef>() { + if (cstr && cstr[0]) { + reset( + ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); + } } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFCString::~CFCString() -{ -} +CFCString::~CFCString() {} -const char * -CFCString::GetFileSystemRepresentation(std::string& s) -{ - return CFCString::FileSystemRepresentation(get(), s); +const char *CFCString::GetFileSystemRepresentation(std::string &s) { + return CFCString::FileSystemRepresentation(get(), s); } -CFStringRef -CFCString::SetFileSystemRepresentation (const char *path) -{ - CFStringRef new_value = NULL; - if (path && path[0]) - new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path); - reset(new_value); - return get(); +CFStringRef CFCString::SetFileSystemRepresentation(const char *path) { + CFStringRef new_value = NULL; + if (path && path[0]) + new_value = + ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); + reset(new_value); + return get(); } - CFStringRef -CFCString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type) -{ - CFStringRef new_value = NULL; - if (cf_type != NULL) - { - CFTypeID cf_type_id = ::CFGetTypeID(cf_type); - - if (cf_type_id == ::CFStringGetTypeID()) - { - // Retain since we are using the existing object - new_value = (CFStringRef)::CFRetain(cf_type); - } - else if (cf_type_id == ::CFURLGetTypeID()) - { - new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); - } +CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { + CFStringRef new_value = NULL; + if (cf_type != NULL) { + CFTypeID cf_type_id = ::CFGetTypeID(cf_type); + + if (cf_type_id == ::CFStringGetTypeID()) { + // Retain since we are using the existing object + new_value = (CFStringRef)::CFRetain(cf_type); + } else if (cf_type_id == ::CFURLGetTypeID()) { + new_value = + ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); } - reset(new_value); - return get(); + } + reset(new_value); + return get(); } CFStringRef -CFCString::SetFileSystemRepresentationAndExpandTilde (const char *path) -{ - std::string expanded_path; - if (CFCString::ExpandTildeInPath(path, expanded_path)) - SetFileSystemRepresentation(expanded_path.c_str()); - else - reset(); - return get(); +CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) { + std::string expanded_path; + if (CFCString::ExpandTildeInPath(path, expanded_path)) + SetFileSystemRepresentation(expanded_path.c_str()); + else + reset(); + return get(); } -const char * -CFCString::UTF8(std::string& str) -{ - return CFCString::UTF8(get(), str); +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 -// 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::UTF8 (CFStringRef cf_str, std::string& str) -{ - if (cf_str) - { - const CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex max_utf8_str_len = CFStringGetLength (cf_str); - max_utf8_str_len = CFStringGetMaximumSizeForEncoding (max_utf8_str_len, encoding); - if (max_utf8_str_len > 0) - { - str.resize(max_utf8_str_len); - if (!str.empty()) - { - if (CFStringGetCString (cf_str, &str[0], str.size(), encoding)) - { - str.resize(strlen(str.c_str())); - return str.c_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. + +const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) { + if (cf_str) { + const CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex max_utf8_str_len = CFStringGetLength(cf_str); + max_utf8_str_len = + CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); + if (max_utf8_str_len > 0) { + str.resize(max_utf8_str_len); + if (!str.empty()) { + if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { + str.resize(strlen(str.c_str())); + return str.c_str(); } + } } - return NULL; + } + return NULL; } -const char* -CFCString::ExpandTildeInPath(const char* path, std::string &expanded_path) -{ - glob_t globbuf; - if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0) - { - expanded_path = globbuf.gl_pathv[0]; - ::globfree (&globbuf); - } - else - expanded_path.clear(); +const char *CFCString::ExpandTildeInPath(const char *path, + std::string &expanded_path) { + glob_t globbuf; + if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { + expanded_path = globbuf.gl_pathv[0]; + ::globfree(&globbuf); + } else + expanded_path.clear(); - return expanded_path.c_str(); + return expanded_path.c_str(); } // Static function that puts a copy of the file system representation of CF_STR @@ -161,35 +133,29 @@ CFCString::ExpandTildeInPath(const char* path, std::string &expanded_path) // 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) -{ - if (cf_str) - { - CFIndex max_length = ::CFStringGetMaximumSizeOfFileSystemRepresentation (cf_str); - if (max_length > 0) - { - str.resize(max_length); - if (!str.empty()) - { - if (::CFStringGetFileSystemRepresentation (cf_str, &str[0], str.size())) - { - str.erase(::strlen(str.c_str())); - return str.c_str(); - } - } +const char *CFCString::FileSystemRepresentation(CFStringRef cf_str, + std::string &str) { + if (cf_str) { + CFIndex max_length = + ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); + if (max_length > 0) { + str.resize(max_length); + if (!str.empty()) { + if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], + str.size())) { + str.erase(::strlen(str.c_str())); + return str.c_str(); } + } } - str.erase(); - return NULL; + } + str.erase(); + return NULL; } - -CFIndex -CFCString::GetLength() const -{ - CFStringRef str = get(); - if (str) - return CFStringGetLength (str); - return 0; +CFIndex CFCString::GetLength() const { + CFStringRef str = get(); + if (str) + return CFStringGetLength(str); + return 0; } diff --git a/lldb/source/Host/macosx/cfcpp/CFCString.h b/lldb/source/Host/macosx/cfcpp/CFCString.h index 27c0903..a7bb0294 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCString.h +++ b/lldb/source/Host/macosx/cfcpp/CFCString.h @@ -14,28 +14,28 @@ #include "CFCReleaser.h" -class CFCString : public CFCReleaser<CFStringRef> -{ +class CFCString : public CFCReleaser<CFStringRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFCString (CFStringRef cf_str = NULL); - CFCString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); - CFCString (const CFCString& rhs); - CFCString& operator= (const CFCString& rhs); - virtual ~CFCString (); - - const char * GetFileSystemRepresentation (std::string& str); - CFStringRef SetFileSystemRepresentation (const char *path); - CFStringRef SetFileSystemRepresentationFromCFType (CFTypeRef cf_type); - CFStringRef SetFileSystemRepresentationAndExpandTilde (const char *path); - const char * UTF8 (std::string& str); - CFIndex GetLength() const; - static const char *UTF8 (CFStringRef cf_str, std::string& str); - static const char *FileSystemRepresentation (CFStringRef cf_str, std::string& str); - static const char *ExpandTildeInPath(const char* path, std::string &expanded_path); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFCString(CFStringRef cf_str = NULL); + CFCString(const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); + CFCString(const CFCString &rhs); + CFCString &operator=(const CFCString &rhs); + virtual ~CFCString(); + const char *GetFileSystemRepresentation(std::string &str); + CFStringRef SetFileSystemRepresentation(const char *path); + CFStringRef SetFileSystemRepresentationFromCFType(CFTypeRef cf_type); + CFStringRef SetFileSystemRepresentationAndExpandTilde(const char *path); + const char *UTF8(std::string &str); + CFIndex GetLength() const; + static const char *UTF8(CFStringRef cf_str, std::string &str); + static const char *FileSystemRepresentation(CFStringRef cf_str, + std::string &str); + static const char *ExpandTildeInPath(const char *path, + std::string &expanded_path); }; #endif // #ifndef CoreFoundationCPP_CFString_h_ diff --git a/lldb/source/Host/macosx/cfcpp/CoreFoundationCPP.h b/lldb/source/Host/macosx/cfcpp/CoreFoundationCPP.h index 6843e26..88d0f5a 100644 --- a/lldb/source/Host/macosx/cfcpp/CoreFoundationCPP.h +++ b/lldb/source/Host/macosx/cfcpp/CoreFoundationCPP.h @@ -21,10 +21,10 @@ #include <CoreFoundationCPP/CFCBundle.h> #include <CoreFoundationCPP/CFCData.h> -#include <CoreFoundationCPP/CFCReleaser.h> #include <CoreFoundationCPP/CFCMutableArray.h> #include <CoreFoundationCPP/CFCMutableDictionary.h> #include <CoreFoundationCPP/CFCMutableSet.h> +#include <CoreFoundationCPP/CFCReleaser.h> #include <CoreFoundationCPP/CFCString.h> -#endif // CoreFoundationCPP_CoreFoundationCPP_H_ +#endif // CoreFoundationCPP_CoreFoundationCPP_H_ diff --git a/lldb/source/Host/netbsd/Host.cpp b/lldb/source/Host/netbsd/Host.cpp index 8742850..d56b046 100644 --- a/lldb/source/Host/netbsd/Host.cpp +++ b/lldb/source/Host/netbsd/Host.cpp @@ -1,4 +1,5 @@ -//===-- source/Host/netbsd/Host.cpp ------------------------------*- C++ -*-===// +//===-- source/Host/netbsd/Host.cpp ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -8,35 +9,35 @@ //===----------------------------------------------------------------------===// // C Includes -#include <stdio.h> #include <dlfcn.h> #include <execinfo.h> +#include <stdio.h> +#include <sys/proc.h> +#include <sys/sysctl.h> #include <sys/types.h> #include <sys/user.h> -#include <sys/sysctl.h> -#include <sys/proc.h> #include <limits.h> -#include <sys/ptrace.h> -#include <sys/exec.h> #include <elf.h> #include <kvm.h> +#include <sys/exec.h> +#include <sys/ptrace.h> // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" -#include "lldb/Host/Endian.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" +#include "lldb/Host/Endian.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" @@ -46,242 +47,222 @@ #include "llvm/Support/Host.h" extern "C" { - extern char **environ; +extern char **environ; } using namespace lldb; using namespace lldb_private; -size_t -Host::GetEnvironment (StringList &env) -{ - char *v; - char **var = environ; - for (; var != NULL && *var != NULL; ++var) - { - v = ::strchr(*var, (int)'-'); - if (v == NULL) - continue; - env.AppendString(v); - } - return env.GetSize(); +size_t Host::GetEnvironment(StringList &env) { + char *v; + char **var = environ; + for (; var != NULL && *var != NULL; ++var) { + v = ::strchr(*var, (int)'-'); + if (v == NULL) + continue; + env.AppendString(v); + } + return env.GetSize(); } -static bool -GetNetBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, - ProcessInstanceInfo &process_info) -{ - if (!process_info.ProcessIDIsValid()) - return false; +static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, + ProcessInstanceInfo &process_info) { + if (!process_info.ProcessIDIsValid()) + return false; + + int pid = process_info.GetProcessID(); - int pid = process_info.GetProcessID(); + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; - int mib[4] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV }; + char arg_data[8192]; + size_t arg_data_size = sizeof(arg_data); + if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0) + return false; - char arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) != 0) - return false; + DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(), + sizeof(void *)); + lldb::offset_t offset = 0; + const char *cstr; - DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); - lldb::offset_t offset = 0; - const char *cstr; + cstr = data.GetCStr(&offset); + if (!cstr) + return false; - cstr = data.GetCStr (&offset); - if (!cstr) - return false; - - process_info.GetExecutableFile().SetFile(cstr, false); - - if (!(match_info_ptr == NULL || - NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), - match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName()))) - return false; - - Args &proc_args = process_info.GetArguments(); - while (1) - { - const uint8_t *p = data.PeekData(offset, 1); - while ((p != NULL) && (*p == '\0') && offset < arg_data_size) - { - ++offset; - p = data.PeekData(offset, 1); - } - if (p == NULL || offset >= arg_data_size) - break; + process_info.GetExecutableFile().SetFile(cstr, false); - cstr = data.GetCStr(&offset); - if (!cstr) - break; + if (!(match_info_ptr == NULL || + NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), + match_info_ptr->GetNameMatchType(), + match_info_ptr->GetProcessInfo().GetName()))) + return false; - proc_args.AppendArgument(cstr); + Args &proc_args = process_info.GetArguments(); + while (1) { + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { + ++offset; + p = data.PeekData(offset, 1); } + if (p == NULL || offset >= arg_data_size) + break; - return true; + cstr = data.GetCStr(&offset); + if (!cstr) + break; + + proc_args.AppendArgument(cstr); + } + + return true; } -static bool -GetNetBSDProcessCPUType (ProcessInstanceInfo &process_info) -{ - if (process_info.ProcessIDIsValid()) - { - process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - return true; - } - process_info.GetArchitecture().Clear(); - return false; +static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) { + if (process_info.ProcessIDIsValid()) { + process_info.GetArchitecture() = + HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + return true; + } + process_info.GetArchitecture().Clear(); + return false; } -static bool -GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) -{ - ::kvm_t *kdp; - char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ +static bool GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { + ::kvm_t *kdp; + char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ - struct ::kinfo_proc2 *proc_kinfo; - const int pid = process_info.GetProcessID(); - int nproc; + struct ::kinfo_proc2 *proc_kinfo; + const int pid = process_info.GetProcessID(); + int nproc; - if (!process_info.ProcessIDIsValid()) - goto error; + if (!process_info.ProcessIDIsValid()) + goto error; - if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) - goto error; + if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) + goto error; - if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid, - sizeof(struct ::kinfo_proc2), - &nproc)) == NULL) { - ::kvm_close(kdp); - goto error; - } + if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid, + sizeof(struct ::kinfo_proc2), &nproc)) == + NULL) { + ::kvm_close(kdp); + goto error; + } - if (nproc < 1) { - ::kvm_close(kdp); /* XXX: we don't check for error here */ - goto error; - } + if (nproc < 1) { + ::kvm_close(kdp); /* XXX: we don't check for error here */ + goto error; + } - process_info.SetParentProcessID (proc_kinfo->p_ppid); - process_info.SetUserID (proc_kinfo->p_ruid); - process_info.SetGroupID (proc_kinfo->p_rgid); - process_info.SetEffectiveUserID (proc_kinfo->p_uid); - process_info.SetEffectiveGroupID (proc_kinfo->p_gid); + process_info.SetParentProcessID(proc_kinfo->p_ppid); + process_info.SetUserID(proc_kinfo->p_ruid); + process_info.SetGroupID(proc_kinfo->p_rgid); + process_info.SetEffectiveUserID(proc_kinfo->p_uid); + process_info.SetEffectiveGroupID(proc_kinfo->p_gid); - ::kvm_close(kdp); /* XXX: we don't check for error here */ + ::kvm_close(kdp); /* XXX: we don't check for error here */ - return true; + return true; error: - process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); - process_info.SetUserID (UINT32_MAX); - process_info.SetGroupID (UINT32_MAX); - process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); - return false; + process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID); + process_info.SetUserID(UINT32_MAX); + process_info.SetGroupID(UINT32_MAX); + process_info.SetEffectiveUserID(UINT32_MAX); + process_info.SetEffectiveGroupID(UINT32_MAX); + return false; } -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - const ::pid_t our_pid = ::getpid(); - const ::uid_t our_uid = ::getuid(); - - const bool all_users = match_info.GetMatchAllUsers() || - // Special case, if lldb is being run as root we can attach to anything - (our_uid == 0); - - kvm_t *kdp; - char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ - if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) - return 0; - - struct ::kinfo_proc2 *proc_kinfo; - int nproc; - if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0, - sizeof(struct ::kinfo_proc2), - &nproc)) == NULL) { - ::kvm_close(kdp); - return 0; - } - - for (int i = 0; i < nproc; i++) { - if (proc_kinfo[i].p_pid < 1) - continue; /* not valid */ - /* Make sure the user is acceptable */ - if (!all_users && proc_kinfo[i].p_ruid != our_uid) - continue; - - if (proc_kinfo[i].p_pid == our_pid || // Skip this process - proc_kinfo[i].p_pid == 0 || // Skip kernel (kernel pid is 0) - proc_kinfo[i].p_stat == LSZOMB || // Zombies are bad - proc_kinfo[i].p_flag & P_TRACED || // Being debugged? - proc_kinfo[i].p_flag & P_WEXIT) // Working on exiting - 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. - if (proc_kinfo[i].p_nlwps > 1) { - bool already_registered = false; - for (size_t pi = 0; pi < process_infos.GetSize(); pi++) { - if (process_infos.GetProcessIDAtIndex(pi) == - proc_kinfo[i].p_pid) { - already_registered = true; - break; - } - } - - if (already_registered) - continue; - } - ProcessInstanceInfo process_info; - process_info.SetProcessID (proc_kinfo[i].p_pid); - process_info.SetParentProcessID (proc_kinfo[i].p_ppid); - process_info.SetUserID (proc_kinfo[i].p_ruid); - process_info.SetGroupID (proc_kinfo[i].p_rgid); - process_info.SetEffectiveUserID (proc_kinfo[i].p_uid); - process_info.SetEffectiveGroupID (proc_kinfo[i].p_gid); - // Make sure our info matches before we go fetch the name and cpu type - if (match_info.Matches (process_info) && - GetNetBSDProcessArgs (&match_info, process_info)) - { - GetNetBSDProcessCPUType (process_info); - if (match_info.Matches (process_info)) - process_infos.Append (process_info); +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + const ::pid_t our_pid = ::getpid(); + const ::uid_t our_uid = ::getuid(); + + const bool all_users = + match_info.GetMatchAllUsers() || + // Special case, if lldb is being run as root we can attach to anything + (our_uid == 0); + + kvm_t *kdp; + char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ + if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) + return 0; + + struct ::kinfo_proc2 *proc_kinfo; + int nproc; + if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0, + sizeof(struct ::kinfo_proc2), &nproc)) == + NULL) { + ::kvm_close(kdp); + return 0; + } + + for (int i = 0; i < nproc; i++) { + if (proc_kinfo[i].p_pid < 1) + continue; /* not valid */ + /* Make sure the user is acceptable */ + if (!all_users && proc_kinfo[i].p_ruid != our_uid) + continue; + + if (proc_kinfo[i].p_pid == our_pid || // Skip this process + proc_kinfo[i].p_pid == 0 || // Skip kernel (kernel pid is 0) + proc_kinfo[i].p_stat == LSZOMB || // Zombies are bad + proc_kinfo[i].p_flag & P_TRACED || // Being debugged? + proc_kinfo[i].p_flag & P_WEXIT) // Working on exiting + 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. + if (proc_kinfo[i].p_nlwps > 1) { + bool already_registered = false; + for (size_t pi = 0; pi < process_infos.GetSize(); pi++) { + if (process_infos.GetProcessIDAtIndex(pi) == proc_kinfo[i].p_pid) { + already_registered = true; + break; } + } + + if (already_registered) + continue; + } + ProcessInstanceInfo process_info; + process_info.SetProcessID(proc_kinfo[i].p_pid); + process_info.SetParentProcessID(proc_kinfo[i].p_ppid); + process_info.SetUserID(proc_kinfo[i].p_ruid); + process_info.SetGroupID(proc_kinfo[i].p_rgid); + process_info.SetEffectiveUserID(proc_kinfo[i].p_uid); + process_info.SetEffectiveGroupID(proc_kinfo[i].p_gid); + // Make sure our info matches before we go fetch the name and cpu type + if (match_info.Matches(process_info) && + GetNetBSDProcessArgs(&match_info, process_info)) { + GetNetBSDProcessCPUType(process_info); + if (match_info.Matches(process_info)) + process_infos.Append(process_info); } + } - kvm_close(kdp); /* XXX: we don't check for error here */ + kvm_close(kdp); /* XXX: we don't check for error here */ - return process_infos.GetSize(); + return process_infos.GetSize(); } -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.SetProcessID(pid); +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.SetProcessID(pid); - if (GetNetBSDProcessArgs(NULL, process_info)) - { - GetNetBSDProcessCPUType(process_info); - GetNetBSDProcessUserAndGroup(process_info); - return true; - } + if (GetNetBSDProcessArgs(NULL, process_info)) { + GetNetBSDProcessCPUType(process_info); + GetNetBSDProcessUserAndGroup(process_info); + return true; + } - process_info.Clear(); - return false; + process_info.Clear(); + return false; } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - return lldb::DataBufferSP(); +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + return lldb::DataBufferSP(); } -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - return Error("unimplemented"); +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + return Error("unimplemented"); } diff --git a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp index aadda76..3c1385a 100644 --- a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp @@ -9,104 +9,92 @@ #include "lldb/Host/netbsd/HostInfoNetBSD.h" +#include <inttypes.h> #include <limits.h> +#include <pthread.h> #include <stdio.h> #include <string.h> -#include <sys/types.h> #include <sys/sysctl.h> +#include <sys/types.h> #include <sys/utsname.h> #include <unistd.h> -#include <pthread.h> -#include <inttypes.h> - using namespace lldb_private; -uint32_t -HostInfoNetBSD::GetMaxThreadNameLength() -{ - return PTHREAD_MAX_NAMELEN_NP; +uint32_t HostInfoNetBSD::GetMaxThreadNameLength() { + return PTHREAD_MAX_NAMELEN_NP; } -bool -HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) -{ - struct utsname un; - - ::memset(&un, 0, sizeof(un)); - if (::uname(&un) < 0) - return false; - - /* Accept versions like 7.99.21 and 6.1_STABLE */ - int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, &minor, &update); - switch(status) { - case 0: - return false; - case 1: - minor = 0; - /* FALLTHROUGH */ - case 2: - update = 0; - /* FALLTHROUGH */ - case 3: - default: - return true; - } -} +bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + struct utsname un; -bool -HostInfoNetBSD::GetOSBuildString(std::string &s) -{ - int mib[2] = {CTL_KERN, KERN_OSREV}; - char osrev_str[12]; - int osrev = 0; - size_t osrev_len = sizeof(osrev); - - if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) - { - ::snprintf(osrev_str, sizeof(osrev_str), "%-10.10d", osrev); - s.assign(osrev_str); - return true; - } + ::memset(&un, 0, sizeof(un)); + if (::uname(&un) < 0) + return false; - s.clear(); + /* Accept versions like 7.99.21 and 6.1_STABLE */ + int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, + &minor, &update); + switch (status) { + case 0: return false; + case 1: + minor = 0; + /* FALLTHROUGH */ + case 2: + update = 0; + /* FALLTHROUGH */ + case 3: + default: + return true; + } } -bool -HostInfoNetBSD::GetOSKernelDescription(std::string &s) -{ - struct utsname un; +bool HostInfoNetBSD::GetOSBuildString(std::string &s) { + int mib[2] = {CTL_KERN, KERN_OSREV}; + char osrev_str[12]; + int osrev = 0; + size_t osrev_len = sizeof(osrev); - ::memset(&un, 0, sizeof(un)); - s.clear(); + if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) { + ::snprintf(osrev_str, sizeof(osrev_str), "%-10.10d", osrev); + s.assign(osrev_str); + return true; + } - if (::uname(&un) < 0) - return false; + s.clear(); + return false; +} - s.assign(un.version); +bool HostInfoNetBSD::GetOSKernelDescription(std::string &s) { + struct utsname un; - return true; + ::memset(&un, 0, sizeof(un)); + s.clear(); + + if (::uname(&un) < 0) + return false; + + s.assign(un.version); + + return true; } -FileSpec -HostInfoNetBSD::GetProgramFileSpec() -{ - static FileSpec g_program_filespec; - - if (!g_program_filespec) - { - ssize_t len; - static char buf[PATH_MAX]; - char name[PATH_MAX]; - - ::snprintf(name, PATH_MAX, "/proc/%d/exe", ::getpid()); - len = ::readlink(name, buf, PATH_MAX - 1); - if (len != -1) - { - buf[len] = '\0'; - g_program_filespec.SetFile(buf, false); - } +FileSpec HostInfoNetBSD::GetProgramFileSpec() { + static FileSpec g_program_filespec; + + if (!g_program_filespec) { + ssize_t len; + static char buf[PATH_MAX]; + char name[PATH_MAX]; + + ::snprintf(name, PATH_MAX, "/proc/%d/exe", ::getpid()); + len = ::readlink(name, buf, PATH_MAX - 1); + if (len != -1) { + buf[len] = '\0'; + g_program_filespec.SetFile(buf, false); } - return g_program_filespec; + } + return g_program_filespec; } diff --git a/lldb/source/Host/netbsd/HostThreadNetBSD.cpp b/lldb/source/Host/netbsd/HostThreadNetBSD.cpp index 06bc502..e8c106b 100644 --- a/lldb/source/Host/netbsd/HostThreadNetBSD.cpp +++ b/lldb/source/Host/netbsd/HostThreadNetBSD.cpp @@ -24,27 +24,20 @@ using namespace lldb_private; -HostThreadNetBSD::HostThreadNetBSD() -{ -} +HostThreadNetBSD::HostThreadNetBSD() {} HostThreadNetBSD::HostThreadNetBSD(lldb::thread_t thread) - : HostThreadPosix(thread) -{ -} + : HostThreadPosix(thread) {} -void -HostThreadNetBSD::SetName(lldb::thread_t thread, llvm::StringRef &name) -{ - ::pthread_setname_np(thread, "%s", const_cast<char*>(name.data())); +void HostThreadNetBSD::SetName(lldb::thread_t thread, llvm::StringRef &name) { + ::pthread_setname_np(thread, "%s", const_cast<char *>(name.data())); } -void -HostThreadNetBSD::GetName(lldb::thread_t thread, llvm::SmallVectorImpl<char> &name) -{ - char buf[PTHREAD_MAX_NAMELEN_NP]; - ::pthread_getname_np(thread, buf, PTHREAD_MAX_NAMELEN_NP); +void HostThreadNetBSD::GetName(lldb::thread_t thread, + llvm::SmallVectorImpl<char> &name) { + char buf[PTHREAD_MAX_NAMELEN_NP]; + ::pthread_getname_np(thread, buf, PTHREAD_MAX_NAMELEN_NP); - name.clear(); - name.append(buf, buf + strlen(buf)); + name.clear(); + name.append(buf, buf + strlen(buf)); } diff --git a/lldb/source/Host/netbsd/ThisThread.cpp b/lldb/source/Host/netbsd/ThisThread.cpp index dff5d9e..ea16981 100644 --- a/lldb/source/Host/netbsd/ThisThread.cpp +++ b/lldb/source/Host/netbsd/ThisThread.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/ThisThread.h" +#include "lldb/Host/HostNativeThread.h" #include "llvm/ADT/SmallVector.h" @@ -17,14 +17,10 @@ using namespace lldb_private; -void -ThisThread::SetName(llvm::StringRef name) -{ - HostNativeThread::SetName(::pthread_self(), name); +void ThisThread::SetName(llvm::StringRef name) { + HostNativeThread::SetName(::pthread_self(), name); } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ - HostNativeThread::GetName(::pthread_self(), name); +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { + HostNativeThread::GetName(::pthread_self(), name); } diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index a6d0958..f6ec94d 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -17,16 +17,16 @@ #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" #include "lldb/Host/Config.h" #include "lldb/Host/IOObject.h" -#include "lldb/Host/SocketAddress.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/SocketAddress.h" #include "lldb/Host/StringConvert.h" #include "lldb/Utility/SelectHelper.h" // C Includes #include <errno.h> #include <fcntl.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <sys/types.h> #ifndef LLDB_DISABLE_POSIX @@ -54,526 +54,491 @@ using namespace lldb; using namespace lldb_private; -const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; -const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; -const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; -const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; -const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; -const char* ConnectionFileDescriptor::UDP_SCHEME = "udp"; -const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; -const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect"; -const char* ConnectionFileDescriptor::FD_SCHEME = "fd"; -const char* ConnectionFileDescriptor::FILE_SCHEME = "file"; +const char *ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; +const char *ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; +const char *ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; +const char *ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; +const char *ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; +const char *ConnectionFileDescriptor::UDP_SCHEME = "udp"; +const char *ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; +const char *ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = + "unix-abstract-connect"; +const char *ConnectionFileDescriptor::FD_SCHEME = "fd"; +const char *ConnectionFileDescriptor::FILE_SCHEME = "file"; namespace { -const char* -GetURLAddress(const char *url, const char *scheme) -{ - const auto prefix = std::string(scheme) + "://"; - if (strstr(url, prefix.c_str()) != url) - return nullptr; +const char *GetURLAddress(const char *url, const char *scheme) { + const auto prefix = std::string(scheme) + "://"; + if (strstr(url, prefix.c_str()) != url) + return nullptr; - return url + prefix.size(); + return url + prefix.size(); } - } ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), - m_child_processes_inherit(child_processes_inherit) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast<void *>(this)); + m_child_processes_inherit(child_processes_inherit) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", + static_cast<void *>(this)); } ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), - m_waiting_for_accept(false), - m_child_processes_inherit(false) -{ - m_write_sp.reset(new File(fd, owns_fd)); - m_read_sp.reset(new File(fd, false)); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", - static_cast<void *>(this), fd, owns_fd); - OpenCommandPipe(); + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), + m_waiting_for_accept(false), m_child_processes_inherit(false) { + m_write_sp.reset(new File(fd, owns_fd)); + m_read_sp.reset(new File(fd, false)); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " + "%i, owns_fd = %i)", + static_cast<void *>(this), fd, owns_fd); + OpenCommandPipe(); } ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), - m_waiting_for_accept(false), - m_child_processes_inherit(false) -{ - InitializeSocket(socket); + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), + m_waiting_for_accept(false), m_child_processes_inherit(false) { + InitializeSocket(socket); } -ConnectionFileDescriptor::~ConnectionFileDescriptor() -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this)); - Disconnect(NULL); - CloseCommandPipe(); +ConnectionFileDescriptor::~ConnectionFileDescriptor() { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", + static_cast<void *>(this)); + Disconnect(NULL); + CloseCommandPipe(); } -void -ConnectionFileDescriptor::OpenCommandPipe() -{ - CloseCommandPipe(); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - // Make the command file descriptor here: - Error result = m_pipe.CreateNew(m_child_processes_inherit); - if (!result.Success()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this), - result.AsCString()); - } - else - { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this), - m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); - } -} +void ConnectionFileDescriptor::OpenCommandPipe() { + CloseCommandPipe(); -void -ConnectionFileDescriptor::CloseCommandPipe() -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + // Make the command file descriptor here: + Error result = m_pipe.CreateNew(m_child_processes_inherit); + if (!result.Success()) { if (log) - log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast<void *>(this)); - - m_pipe.Close(); + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not " + "make pipe: %s", + static_cast<void *>(this), result.AsCString()); + } else { + if (log) + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success " + "readfd=%d writefd=%d", + static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), + m_pipe.GetWriteFileDescriptor()); + } } -bool -ConnectionFileDescriptor::IsConnected() const -{ - return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); -} +void ConnectionFileDescriptor::CloseCommandPipe() { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", + static_cast<void *>(this)); -ConnectionStatus -ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast<void *>(this), s); + m_pipe.Close(); +} - OpenCommandPipe(); +bool ConnectionFileDescriptor::IsConnected() const { + return (m_read_sp && m_read_sp->IsValid()) || + (m_write_sp && m_write_sp->IsValid()); +} - if (s && s[0]) - { - const char *addr = nullptr; - if ((addr = GetURLAddress(s, LISTEN_SCHEME))) - { - // listen://HOST:PORT - return SocketListenAndAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) - { - // unix://SOCKNAME - return NamedSocketAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) - { - // unix://SOCKNAME - return NamedSocketAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) - { - return ConnectTCP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) - { - return ConnectTCP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UDP_SCHEME))) - { - return ConnectUDP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) - { - // unix-connect://SOCKNAME - return NamedSocketConnect(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) - { - // unix-abstract-connect://SOCKNAME - return UnixAbstractSocketConnect(addr, error_ptr); - } +ConnectionStatus ConnectionFileDescriptor::Connect(const char *s, + Error *error_ptr) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", + static_cast<void *>(this), s); + + OpenCommandPipe(); + + if (s && s[0]) { + const char *addr = nullptr; + if ((addr = GetURLAddress(s, LISTEN_SCHEME))) { + // listen://HOST:PORT + return SocketListenAndAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) { + // unix://SOCKNAME + return NamedSocketAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) { + // unix://SOCKNAME + return NamedSocketAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) { + return ConnectTCP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) { + return ConnectTCP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UDP_SCHEME))) { + return ConnectUDP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) { + // unix-connect://SOCKNAME + return NamedSocketConnect(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) { + // unix-abstract-connect://SOCKNAME + return UnixAbstractSocketConnect(addr, error_ptr); + } #ifndef LLDB_DISABLE_POSIX - else if ((addr = GetURLAddress(s, FD_SCHEME))) - { - // Just passing a native file descriptor within this current process - // that is already opened (possibly from a service or other source). - bool success = false; - int fd = StringConvert::ToSInt32(addr, -1, 0, &success); - - if (success) - { - // 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) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); - m_read_sp.reset(); - 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. - // 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. - - std::unique_ptr<TCPSocket> tcp_socket; - tcp_socket.reset(new TCPSocket(fd, false)); - // 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); - if (is_socket) - { - m_read_sp = std::move(tcp_socket); - m_write_sp = m_read_sp; - } - else - { - m_read_sp.reset(new File(fd, false)); - m_write_sp.reset(new File(fd, false)); - } - m_uri.assign(addr); - return eConnectionStatusSuccess; - } - } - - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s); - m_read_sp.reset(); - m_write_sp.reset(); - return eConnectionStatusError; - } - else if ((addr = GetURLAddress(s, FILE_SCHEME))) - { - // file:///PATH - const char *path = addr; - int fd = -1; - do - { - fd = ::open(path, O_RDWR); - } while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - if (error_ptr) - error_ptr->SetErrorToErrno(); - return eConnectionStatusError; - } - - if (::isatty(fd)) - { - // Set up serial terminal emulation - struct termios options; - ::tcgetattr(fd, &options); - - // Set port speed to maximum - ::cfsetospeed(&options, B115200); - ::cfsetispeed(&options, B115200); - - // Raw input, disable echo and signals - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - - // Make sure only one character is needed to return from a read - options.c_cc[VMIN] = 1; - options.c_cc[VTIME] = 0; - - ::tcsetattr(fd, TCSANOW, &options); - } - - int flags = ::fcntl(fd, F_GETFL, 0); - if (flags >= 0) - { - if ((flags & O_NONBLOCK) == 0) - { - flags |= O_NONBLOCK; - ::fcntl(fd, F_SETFL, flags); - } - } - m_read_sp.reset(new File(fd, true)); + else if ((addr = GetURLAddress(s, FD_SCHEME))) { + // Just passing a native file descriptor within this current process + // that is already opened (possibly from a service or other source). + bool success = false; + int fd = StringConvert::ToSInt32(addr, -1, 0, &success); + + if (success) { + // 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) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); + m_read_sp.reset(); + 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. + // 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. + + std::unique_ptr<TCPSocket> tcp_socket; + tcp_socket.reset(new TCPSocket(fd, false)); + // 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); + if (is_socket) { + m_read_sp = std::move(tcp_socket); + m_write_sp = m_read_sp; + } else { + m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); - return eConnectionStatusSuccess; + } + m_uri.assign(addr); + return eConnectionStatusSuccess; } -#endif + } + + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", + s); + m_read_sp.reset(); + m_write_sp.reset(); + return eConnectionStatusError; + } else if ((addr = GetURLAddress(s, FILE_SCHEME))) { + // file:///PATH + const char *path = addr; + int fd = -1; + do { + fd = ::open(path, O_RDWR); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); + error_ptr->SetErrorToErrno(); return eConnectionStatusError; - } - if (error_ptr) - error_ptr->SetErrorString("invalid connect arguments"); - return eConnectionStatusError; -} + } -bool -ConnectionFileDescriptor::InterruptRead() -{ - size_t bytes_written = 0; - Error result = m_pipe.Write("i", 1, bytes_written); - return result.Success(); -} + if (::isatty(fd)) { + // Set up serial terminal emulation + struct termios options; + ::tcgetattr(fd, &options); -ConnectionStatus -ConnectionFileDescriptor::Disconnect(Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void *>(this)); + // Set port speed to maximum + ::cfsetospeed(&options, B115200); + ::cfsetispeed(&options, B115200); - ConnectionStatus status = eConnectionStatusSuccess; + // Raw input, disable echo and signals + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - if (!IsConnected()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void *>(this)); - return eConnectionStatusSuccess; - } + // Make sure only one character is needed to return from a read + options.c_cc[VMIN] = 1; + options.c_cc[VTIME] = 0; - if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - static_cast<Socket &>(*m_read_sp).PreDisconnect(); + ::tcsetattr(fd, TCSANOW, &options); + } - // 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; - - std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); - if (!locker.try_lock()) - { - if (m_pipe.CanWrite()) - { - size_t bytes_written = 0; - Error result = m_pipe.Write("q", 1, bytes_written); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, error = '%s'.", - static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), result.AsCString()); - } - else if (log) - { - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", - static_cast<void *>(this)); + int flags = ::fcntl(fd, F_GETFL, 0); + if (flags >= 0) { + if ((flags & O_NONBLOCK) == 0) { + flags |= O_NONBLOCK; + ::fcntl(fd, F_SETFL, flags); } - locker.lock(); + } + m_read_sp.reset(new File(fd, true)); + m_write_sp.reset(new File(fd, false)); + return eConnectionStatusSuccess; } - - Error error = m_read_sp->Close(); - Error error2 = m_write_sp->Close(); - if (error.Fail() || error2.Fail()) - status = eConnectionStatusError; +#endif if (error_ptr) - *error_ptr = error.Fail() ? error : error2; - - // Close any pipes we were using for async interrupts - m_pipe.Close(); - - m_uri.clear(); - m_shutting_down = false; - return status; + error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", + s); + return eConnectionStatusError; + } + if (error_ptr) + error_ptr->SetErrorString("invalid connect arguments"); + return eConnectionStatusError; } -size_t -ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - - std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); - if (!locker.try_lock()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast<void *>(this)); - if (error_ptr) - error_ptr->SetErrorString("failed to get the connection lock for read."); - - status = eConnectionStatusTimedOut; - return 0; - } - - if (m_shutting_down) - { - status = eConnectionStatusError; - return 0; - } +bool ConnectionFileDescriptor::InterruptRead() { + size_t bytes_written = 0; + Error result = m_pipe.Write("i", 1, bytes_written); + return result.Success(); +} - status = BytesAvailable(timeout_usec, error_ptr); - if (status != eConnectionStatusSuccess) - return 0; +ConnectionStatus ConnectionFileDescriptor::Disconnect(Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect ()", + static_cast<void *>(this)); - Error error; - size_t bytes_read = dst_len; - error = m_read_sp->Read(dst, bytes_read); + ConnectionStatus status = eConnectionStatusSuccess; + if (!IsConnected()) { if (log) - { - log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", - static_cast<void *>(this), static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), static_cast<void *>(dst), - static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read), error.AsCString()); - } - - if (bytes_read == 0) - { - error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. - status = eConnectionStatusEndOfFile; - } - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - uint32_t error_value = error.GetError(); - switch (error_value) - { - case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. - if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - status = eConnectionStatusTimedOut; - else - status = eConnectionStatusSuccess; - return 0; - - case EFAULT: // Buf points outside the allocated address space. - case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. - 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. - 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. - status = eConnectionStatusError; - break; // Break to close.... - - case ENOENT: // no such file or directory - case EBADF: // fildes is not a valid file or socket descriptor open for reading. - case ENXIO: // An action is requested of a device that does not exist.. - // A requested action cannot be performed by the device. - case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. - status = eConnectionStatusTimedOut; - return 0; - - default: - if (log) - log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast<void *>(this), - strerror(error_value)); - status = eConnectionStatusError; - break; // Break to close.... - } - - return 0; + log->Printf( + "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", + static_cast<void *>(this)); + return eConnectionStatusSuccess; + } + + if (m_read_sp && m_read_sp->IsValid() && + 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. + + m_shutting_down = true; + + std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); + if (!locker.try_lock()) { + if (m_pipe.CanWrite()) { + size_t bytes_written = 0; + Error result = m_pipe.Write("q", 1, bytes_written); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get " + "the lock, sent 'q' to %d, error = '%s'.", + static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), + result.AsCString()); + } else if (log) { + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " + "lock, but no command pipe is available.", + static_cast<void *>(this)); } - return bytes_read; + locker.lock(); + } + + Error error = m_read_sp->Close(); + Error error2 = m_write_sp->Close(); + if (error.Fail() || error2.Fail()) + status = eConnectionStatusError; + if (error_ptr) + *error_ptr = error.Fail() ? error : error2; + + // Close any pipes we were using for async interrupts + m_pipe.Close(); + + m_uri.clear(); + m_shutting_down = false; + return status; } -size_t -ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast<void *>(this), - static_cast<const void *>(src), static_cast<uint64_t>(src_len)); - - if (!IsConnected()) - { - if (error_ptr) - error_ptr->SetErrorString("not connected"); - status = eConnectionStatusNoConnection; - return 0; - } - - Error error; - - size_t bytes_sent = src_len; - error = m_write_sp->Write(src, bytes_sent); +size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, + uint32_t timeout_usec, + ConnectionStatus &status, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); + if (!locker.try_lock()) { if (log) - { - log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", - static_cast<void *>(this), static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), static_cast<const void *>(src), - static_cast<uint64_t>(src_len), static_cast<uint64_t>(bytes_sent), error.AsCString()); - } - + log->Printf("%p ConnectionFileDescriptor::Read () failed to get the " + "connection lock.", + static_cast<void *>(this)); if (error_ptr) - *error_ptr = error; + error_ptr->SetErrorString("failed to get the connection lock for read."); + + status = eConnectionStatusTimedOut; + return 0; + } + + if (m_shutting_down) { + status = eConnectionStatusError; + return 0; + } + + status = BytesAvailable(timeout_usec, error_ptr); + if (status != eConnectionStatusSuccess) + return 0; + + Error error; + size_t bytes_read = dst_len; + error = m_read_sp->Read(dst, bytes_read); + + if (log) { + log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 + ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", + static_cast<void *>(this), + static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), + static_cast<void *>(dst), static_cast<uint64_t>(dst_len), + static_cast<uint64_t>(bytes_read), error.AsCString()); + } + + if (bytes_read == 0) { + error.Clear(); // End-of-file. Do not automatically close; pass along for + // the end-of-file handlers. + status = eConnectionStatusEndOfFile; + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) { + uint32_t error_value = error.GetError(); + switch (error_value) { + case EAGAIN: // The file was marked for non-blocking I/O, and no data were + // ready to be read. + if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) + status = eConnectionStatusTimedOut; + else + status = eConnectionStatusSuccess; + return 0; + + case EFAULT: // Buf points outside the allocated address space. + case EINTR: // A read from a slow device was interrupted before any data + // arrived by the delivery of a signal. + 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. + 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. + status = eConnectionStatusError; + break; // Break to close.... + + case ENOENT: // no such file or directory + case EBADF: // fildes is not a valid file or socket descriptor open for + // reading. + case ENXIO: // An action is requested of a device that does not exist.. + // A requested action cannot be performed by the device. + case ECONNRESET: // The connection is closed by the peer during a read + // attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a + // socket. + status = eConnectionStatusTimedOut; + return 0; + + default: + if (log) + log->Printf( + "%p ConnectionFileDescriptor::Read (), unexpected error: %s", + static_cast<void *>(this), strerror(error_value)); + status = eConnectionStatusError; + break; // Break to close.... + } - if (error.Fail()) - { - switch (error.GetError()) - { - case EAGAIN: - case EINTR: - status = eConnectionStatusSuccess; - return 0; - - case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - default: - status = eConnectionStatusError; - break; // Break to close.... - } + return 0; + } + return bytes_read; +} - return 0; +size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, + ConnectionStatus &status, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf( + "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", + static_cast<void *>(this), static_cast<const void *>(src), + static_cast<uint64_t>(src_len)); + + if (!IsConnected()) { + if (error_ptr) + error_ptr->SetErrorString("not connected"); + status = eConnectionStatusNoConnection; + return 0; + } + + Error error; + + size_t bytes_sent = src_len; + error = m_write_sp->Write(src, bytes_sent); + + if (log) { + log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 + " (error = %s)", + static_cast<void *>(this), + static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), + static_cast<const void *>(src), static_cast<uint64_t>(src_len), + static_cast<uint64_t>(bytes_sent), error.AsCString()); + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) { + switch (error.GetError()) { + case EAGAIN: + case EINTR: + status = eConnectionStatusSuccess; + return 0; + + case ECONNRESET: // The connection is closed by the peer during a read + // attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + default: + status = eConnectionStatusError; + break; // Break to close.... } - status = eConnectionStatusSuccess; - return bytes_sent; -} + return 0; + } -std::string -ConnectionFileDescriptor::GetURI() -{ - return m_uri; + status = eConnectionStatusSuccess; + return bytes_sent; } -// This ConnectionFileDescriptor::BytesAvailable() uses select() via SelectHelper +std::string ConnectionFileDescriptor::GetURI() { return m_uri; } + +// This ConnectionFileDescriptor::BytesAvailable() uses select() via +// SelectHelper // // PROS: // - select is consistent across most unix platforms @@ -587,260 +552,247 @@ ConnectionFileDescriptor::GetURI() // be used or a new version of ConnectionFileDescriptor::BytesAvailable() // should be written for the system that is running into the limitations. +ConnectionStatus ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, + Error *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. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf( + "%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", + static_cast<void *>(this), timeout_usec); + + // 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(); + + if (handle != IOObject::kInvalidHandleValue) { + SelectHelper select_helper; + if (timeout_usec != UINT32_MAX) + select_helper.SetTimeout(std::chrono::microseconds(timeout_usec)); + + 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. + const bool have_pipe_fd = false; +#else + const bool have_pipe_fd = pipe_fd >= 0; +#endif + if (have_pipe_fd) + select_helper.FDSetRead(pipe_fd); -ConnectionStatus -ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *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. + while (handle == m_read_sp->GetWaitableHandle()) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec); + Error error = select_helper.Select(); + if (error_ptr) + *error_ptr = error; - // 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(); + if (error.Fail()) { + switch (error.GetError()) { + case EBADF: // One of the descriptor sets specified an invalid + // descriptor. + return eConnectionStatusLostConnection; + + case EINVAL: // The specified time limit is invalid. One of its + // components is negative or too large. + default: // Other unknown error + return eConnectionStatusError; + + case ETIMEDOUT: + return eConnectionStatusTimedOut; + + case EAGAIN: // The kernel was (perhaps temporarily) unable to + // 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. + break; // Lets keep reading to until we timeout + } + } else { + if (select_helper.FDIsSetRead(handle)) + 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: + char buffer[1]; - if (handle != IOObject::kInvalidHandleValue) - { - SelectHelper select_helper; - if (timeout_usec != UINT32_MAX) - select_helper.SetTimeout(std::chrono::microseconds(timeout_usec)); + ssize_t bytes_read; - 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. - const bool have_pipe_fd = false; -#else - const bool have_pipe_fd = pipe_fd >= 0; -#endif - if (have_pipe_fd) - select_helper.FDSetRead(pipe_fd); - - while (handle == m_read_sp->GetWaitableHandle()) - { - - Error error = select_helper.Select(); - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - switch (error.GetError()) - { - case EBADF: // One of the descriptor sets specified an invalid descriptor. - return eConnectionStatusLostConnection; - - case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. - default: // Other unknown error - return eConnectionStatusError; - - case ETIMEDOUT: - return eConnectionStatusTimedOut; - - case EAGAIN: // The kernel was (perhaps temporarily) unable to - // 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. - break; // Lets keep reading to until we timeout - } - } - else - { - if (select_helper.FDIsSetRead(handle)) - 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: - char buffer[1]; - - ssize_t bytes_read; - - do - { - bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); - - switch (buffer[0]) - { - case 'q': - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " - "got data: %c from the command channel.", - static_cast<void *>(this), buffer[0]); - return eConnectionStatusEndOfFile; - case 'i': - // Interrupt the current read - return eConnectionStatusInterrupted; - } - } - } + do { + bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); + } while (bytes_read < 0 && errno == EINTR); + + switch (buffer[0]) { + case 'q': + if (log) + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " + "got data: %c from the command channel.", + static_cast<void *>(this), buffer[0]); + return eConnectionStatusEndOfFile; + case 'i': + // Interrupt the current read + return eConnectionStatusInterrupted; + } } + } } + } - if (error_ptr) - error_ptr->SetErrorString("not connected"); - return eConnectionStatusLostConnection; + if (error_ptr) + error_ptr->SetErrorString("not connected"); + return eConnectionStatusLostConnection; } ConnectionStatus -ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = + Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = + Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } lldb::ConnectionStatus -ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = Socket::UnixAbstractConnect(socket_name, + m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) -{ - m_port_predicate.SetValue(0, eBroadcastNever); - - Socket *socket = nullptr; - m_waiting_for_accept = true; - Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; +ConnectionFileDescriptor::SocketListenAndAccept(const char *s, + Error *error_ptr) { + m_port_predicate.SetValue(0, eBroadcastNever); + + Socket *socket = nullptr; + m_waiting_for_accept = true; + Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, + &m_port_predicate); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; - std::unique_ptr<Socket> listening_socket_up; + std::unique_ptr<Socket> listening_socket_up; - listening_socket_up.reset(socket); - socket = nullptr; - error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); - listening_socket_up.reset(); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; + listening_socket_up.reset(socket); + socket = nullptr; + error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); + listening_socket_up.reset(); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; - InitializeSocket(socket); - return eConnectionStatusSuccess; + InitializeSocket(socket); + return eConnectionStatusSuccess; } -ConnectionStatus -ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(s); - return eConnectionStatusSuccess; +ConnectionStatus ConnectionFileDescriptor::ConnectTCP(const char *s, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } -ConnectionStatus -ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) -{ - Socket *send_socket = nullptr; - Socket *recv_socket = nullptr; - Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(send_socket); - m_read_sp.reset(recv_socket); - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(s); - return eConnectionStatusSuccess; +ConnectionStatus ConnectionFileDescriptor::ConnectUDP(const char *s, + Error *error_ptr) { + Socket *send_socket = nullptr; + Socket *recv_socket = nullptr; + Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, + recv_socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(send_socket); + m_read_sp.reset(recv_socket); + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(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(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; } -bool -ConnectionFileDescriptor::GetChildProcessesInherit() const -{ - return m_child_processes_inherit; +bool ConnectionFileDescriptor::GetChildProcessesInherit() const { + return m_child_processes_inherit; } -void -ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) -{ - m_child_processes_inherit = child_processes_inherit; +void ConnectionFileDescriptor::SetChildProcessesInherit( + bool child_processes_inherit) { + m_child_processes_inherit = child_processes_inherit; } -void -ConnectionFileDescriptor::InitializeSocket(Socket* socket) -{ - assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); - TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket); - - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - StreamString strm; - strm.Printf("connect://%s:%u",tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber()); - m_uri.swap(strm.GetString()); +void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { + assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); + TCPSocket *tcp_socket = static_cast<TCPSocket *>(socket); + + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + StreamString strm; + strm.Printf("connect://%s:%u", tcp_socket->GetRemoteIPAddress().c_str(), + tcp_socket->GetRemotePortNumber()); + m_uri.swap(strm.GetString()); } diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 9dc1471..cb0a1d0 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -21,113 +21,100 @@ using namespace lldb_private; #ifdef __ANDROID__ // Android does not have SUN_LEN #ifndef SUN_LEN -#define SUN_LEN(ptr) (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)) +#define SUN_LEN(ptr) \ + (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)) #endif #endif // #ifdef __ANDROID__ namespace { const int kDomain = AF_UNIX; -const int kType = SOCK_STREAM; +const int kType = SOCK_STREAM; -bool SetSockAddr(llvm::StringRef name, - const size_t name_offset, - sockaddr_un* saddr_un, - socklen_t& saddr_un_len) -{ - if (name.size() + name_offset > sizeof(saddr_un->sun_path)) - return false; +bool SetSockAddr(llvm::StringRef name, const size_t name_offset, + sockaddr_un *saddr_un, socklen_t &saddr_un_len) { + if (name.size() + name_offset > sizeof(saddr_un->sun_path)) + return false; - memset(saddr_un, 0, sizeof(*saddr_un)); - saddr_un->sun_family = kDomain; + memset(saddr_un, 0, sizeof(*saddr_un)); + saddr_un->sun_family = kDomain; - memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); + memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); - // For domain sockets we can use SUN_LEN in order to calculate size of - // sockaddr_un, but for abstract sockets we have to calculate size manually - // because of leading null symbol. - if (name_offset == 0) - saddr_un_len = SUN_LEN(saddr_un); - else - saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); + // For domain sockets we can use SUN_LEN in order to calculate size of + // sockaddr_un, but for abstract sockets we have to calculate size manually + // because of leading null symbol. + if (name_offset == 0) + saddr_un_len = SUN_LEN(saddr_un); + else + saddr_un_len = + offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un->sun_len = saddr_un_len; + saddr_un->sun_len = saddr_un_len; #endif - return true; + return true; } - } DomainSocket::DomainSocket(NativeSocket socket) - : Socket(socket, ProtocolUnixDomain, true) -{ -} + : Socket(socket, ProtocolUnixDomain, true) {} DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) - : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) -{ -} - -DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error) - : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true) -{ -} - -Error -DomainSocket::Connect(llvm::StringRef name) -{ - sockaddr_un saddr_un; - socklen_t saddr_un_len; - if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) - return Error("Failed to set socket address"); - - Error error; - if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0) - SetLastError (error); + : DomainSocket( + CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} + +DomainSocket::DomainSocket(SocketProtocol protocol, + bool child_processes_inherit, Error &error) + : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), + protocol, true) {} + +Error DomainSocket::Connect(llvm::StringRef name) { + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); + + Error error; + if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < + 0) + SetLastError(error); - return error; + return error; } -Error -DomainSocket::Listen(llvm::StringRef name, int backlog) -{ - sockaddr_un saddr_un; - socklen_t saddr_un_len; - if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) - return Error("Failed to set socket address"); +Error DomainSocket::Listen(llvm::StringRef name, int backlog) { + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); - DeleteSocketFile(name); + DeleteSocketFile(name); - Error error; - if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0) - if (::listen(GetNativeSocket(), backlog) == 0) - return error; + Error error; + if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == + 0) + if (::listen(GetNativeSocket(), backlog) == 0) + return error; - SetLastError(error); - return error; + SetLastError(error); + return error; } -Error -DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error); - if (error.Success()) - socket = new DomainSocket(conn_fd); +Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { + Error error; + auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, + child_processes_inherit, error); + if (error.Success()) + socket = new DomainSocket(conn_fd); - return error; + return error; } -size_t -DomainSocket::GetNameOffset() const -{ - return 0; -} +size_t DomainSocket::GetNameOffset() const { return 0; } -void -DomainSocket::DeleteSocketFile(llvm::StringRef name) -{ - FileSystem::Unlink(FileSpec{name, true}); +void DomainSocket::DeleteSocketFile(llvm::StringRef name) { + FileSystem::Unlink(FileSpec{name, true}); } diff --git a/lldb/source/Host/posix/FileSystem.cpp b/lldb/source/Host/posix/FileSystem.cpp index c8fa1bc..aaa53ce0 100644 --- a/lldb/source/Host/posix/FileSystem.cpp +++ b/lldb/source/Host/posix/FileSystem.cpp @@ -16,9 +16,9 @@ #include <sys/stat.h> #include <sys/types.h> #ifdef __linux__ -#include <sys/statfs.h> -#include <sys/mount.h> #include <linux/magic.h> +#include <sys/mount.h> +#include <sys/statfs.h> #endif #if defined(__NetBSD__) #include <sys/statvfs.h> @@ -32,282 +32,231 @@ using namespace lldb; using namespace lldb_private; -const char * -FileSystem::DEV_NULL = "/dev/null"; +const char *FileSystem::DEV_NULL = "/dev/null"; -FileSpec::PathSyntax -FileSystem::GetNativePathSyntax() -{ - return FileSpec::ePathSyntaxPosix; +FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { + return FileSpec::ePathSyntaxPosix; } -Error -FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) -{ - if (file_spec) - { - Error error; - if (::mkdir(file_spec.GetCString(), file_permissions) == -1) - { - error.SetErrorToErrno(); - errno = 0; - switch (error.GetError()) - { - case ENOENT: - { - // Parent directory doesn't exist, so lets make it if we can - // Make the parent directory and try again - FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false}; - error = MakeDirectory(parent_file_spec, file_permissions); - if (error.Fail()) - return error; - // Try and make the directory again now that the parent directory was made successfully - if (::mkdir(file_spec.GetCString(), file_permissions) == -1) - { - error.SetErrorToErrno(); - } - return error; - } - break; - case EEXIST: - { - if (file_spec.IsDirectory()) - return Error(); // It is a directory and it already exists - } - break; - } +Error FileSystem::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { + if (file_spec) { + Error error; + if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { + error.SetErrorToErrno(); + errno = 0; + switch (error.GetError()) { + case ENOENT: { + // Parent directory doesn't exist, so lets make it if we can + // Make the parent directory and try again + FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false}; + error = MakeDirectory(parent_file_spec, file_permissions); + if (error.Fail()) + return error; + // Try and make the directory again now that the parent directory was + // made successfully + if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { + error.SetErrorToErrno(); } return error; + } break; + case EEXIST: { + if (file_spec.IsDirectory()) + return Error(); // It is a directory and it already exists + } break; + } } - return Error("empty path"); + return error; + } + return Error("empty path"); } -Error -FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) -{ - Error error; - if (file_spec) - { - if (recurse) - { - // Save all sub directories in a list so we don't recursively call this function - // and possibly run out of file descriptors if the directory is too deep. - std::vector<FileSpec> sub_directories; - - FileSpec::ForEachItemInDirectory (file_spec.GetCString(), [&error, &sub_directories](FileSpec::FileType file_type, const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult { - if (file_type == FileSpec::eFileTypeDirectory) - { - // Save all directorires and process them after iterating through this directory - sub_directories.push_back(spec); - } - else - { - // Update sub_spec to point to the current file and delete it - error = FileSystem::Unlink(spec); - } - // If anything went wrong, stop iterating, else process the next file - if (error.Fail()) - return FileSpec::eEnumerateDirectoryResultQuit; - else - return FileSpec::eEnumerateDirectoryResultNext; - }); +Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { + Error error; + if (file_spec) { + if (recurse) { + // Save all sub directories in a list so we don't recursively call this + // function + // and possibly run out of file descriptors if the directory is too deep. + std::vector<FileSpec> sub_directories; - if (error.Success()) - { - // Now delete all sub directories with separate calls that aren't - // recursively calling into this function _while_ this function is - // iterating through the current directory. - for (const auto &sub_directory : sub_directories) - { - error = DeleteDirectory(sub_directory, recurse); - if (error.Fail()) - break; - } + FileSpec::ForEachItemInDirectory( + file_spec.GetCString(), + [&error, &sub_directories]( + FileSpec::FileType file_type, + const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult { + if (file_type == FileSpec::eFileTypeDirectory) { + // Save all directorires and process them after iterating through + // this directory + sub_directories.push_back(spec); + } else { + // Update sub_spec to point to the current file and delete it + error = FileSystem::Unlink(spec); } - } + // If anything went wrong, stop iterating, else process the next + // file + if (error.Fail()) + return FileSpec::eEnumerateDirectoryResultQuit; + else + return FileSpec::eEnumerateDirectoryResultNext; + }); - if (error.Success()) - { - if (::rmdir(file_spec.GetCString()) != 0) - error.SetErrorToErrno(); + if (error.Success()) { + // Now delete all sub directories with separate calls that aren't + // recursively calling into this function _while_ this function is + // iterating through the current directory. + for (const auto &sub_directory : sub_directories) { + error = DeleteDirectory(sub_directory, recurse); + if (error.Fail()) + break; } + } } - else - { - error.SetErrorString("empty path"); - } - return error; -} -Error -FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) -{ - Error error; - struct stat file_stats; - if (::stat(file_spec.GetCString(), &file_stats) == 0) - { - // The bits in "st_mode" currently match the definitions - // for the file mode bits in unix. - file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - else - { + if (error.Success()) { + if (::rmdir(file_spec.GetCString()) != 0) error.SetErrorToErrno(); } - return error; + } else { + error.SetErrorString("empty path"); + } + return error; } -Error -FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) -{ - Error error; - if (::chmod(file_spec.GetCString(), file_permissions) != 0) - error.SetErrorToErrno(); - return error; +Error FileSystem::GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions) { + Error error; + struct stat file_stats; + if (::stat(file_spec.GetCString(), &file_stats) == 0) { + // The bits in "st_mode" currently match the definitions + // for the file mode bits in unix. + file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } else { + error.SetErrorToErrno(); + } + return error; } -lldb::user_id_t -FileSystem::GetFileSize(const FileSpec &file_spec) -{ - return file_spec.GetByteSize(); +Error FileSystem::SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions) { + Error error; + if (::chmod(file_spec.GetCString(), file_permissions) != 0) + error.SetErrorToErrno(); + return error; } -bool -FileSystem::GetFileExists(const FileSpec &file_spec) -{ - return file_spec.Exists(); +lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { + return file_spec.GetByteSize(); } -Error -FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - if (::link(dst.GetCString(), src.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +bool FileSystem::GetFileExists(const FileSpec &file_spec) { + return file_spec.Exists(); } -int -FileSystem::GetHardlinkCount(const FileSpec &file_spec) -{ - struct stat file_stat; - if (::stat(file_spec.GetCString(), &file_stat) == 0) - return file_stat.st_nlink; +Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { + Error error; + if (::link(dst.GetCString(), src.GetCString()) == -1) + error.SetErrorToErrno(); + return error; +} + +int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { + struct stat file_stat; + if (::stat(file_spec.GetCString(), &file_stat) == 0) + return file_stat.st_nlink; - return -1; + return -1; } -Error -FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - if (::symlink(dst.GetCString(), src.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { + Error error; + if (::symlink(dst.GetCString(), src.GetCString()) == -1) + error.SetErrorToErrno(); + return error; } -Error -FileSystem::Unlink(const FileSpec &file_spec) -{ - Error error; - if (::unlink(file_spec.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +Error FileSystem::Unlink(const FileSpec &file_spec) { + Error error; + if (::unlink(file_spec.GetCString()) == -1) + error.SetErrorToErrno(); + return error; } -Error -FileSystem::Readlink(const FileSpec &src, FileSpec &dst) -{ - Error error; - char buf[PATH_MAX]; - ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1); - if (count < 0) - error.SetErrorToErrno(); - else - { - buf[count] = '\0'; // Success - dst.SetFile(buf, false); - } - return error; +Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { + Error error; + char buf[PATH_MAX]; + ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1); + if (count < 0) + error.SetErrorToErrno(); + else { + buf[count] = '\0'; // Success + dst.SetFile(buf, false); + } + return error; } -Error -FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) -{ - char resolved_path[PATH_MAX]; - if (!src.GetPath (resolved_path, sizeof (resolved_path))) - { - return Error("Couldn't get the canonical path for %s", src.GetCString()); - } - - char real_path[PATH_MAX + 1]; - if (realpath(resolved_path, real_path) == nullptr) - { - Error err; - err.SetErrorToErrno(); - return err; - } - - dst = FileSpec(real_path, false); - - return Error(); +Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { + char resolved_path[PATH_MAX]; + if (!src.GetPath(resolved_path, sizeof(resolved_path))) { + return Error("Couldn't get the canonical path for %s", src.GetCString()); + } + + char real_path[PATH_MAX + 1]; + if (realpath(resolved_path, real_path) == nullptr) { + Error err; + err.SetErrorToErrno(); + return err; + } + + dst = FileSpec(real_path, false); + + return Error(); } #if defined(__NetBSD__) -static bool IsLocal(const struct statvfs& info) -{ - return (info.f_flag & MNT_LOCAL) != 0; +static bool IsLocal(const struct statvfs &info) { + return (info.f_flag & MNT_LOCAL) != 0; } #else -static bool IsLocal(const struct statfs& info) -{ +static bool IsLocal(const struct statfs &info) { #ifdef __linux__ - #define CIFS_MAGIC_NUMBER 0xFF534D42 - switch ((uint32_t)info.f_type) - { - case NFS_SUPER_MAGIC: - case SMB_SUPER_MAGIC: - case CIFS_MAGIC_NUMBER: - return false; - default: - return true; - } +#define CIFS_MAGIC_NUMBER 0xFF534D42 + switch ((uint32_t)info.f_type) { + case NFS_SUPER_MAGIC: + case SMB_SUPER_MAGIC: + case CIFS_MAGIC_NUMBER: + return false; + default: + return true; + } #else - return (info.f_flags & MNT_LOCAL) != 0; + return (info.f_flags & MNT_LOCAL) != 0; #endif } #endif #if defined(__NetBSD__) -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - struct statvfs statfs_info; - std::string path (spec.GetPath()); - if (statvfs(path.c_str(), &statfs_info) == 0) - return ::IsLocal(statfs_info); - return false; +bool FileSystem::IsLocal(const FileSpec &spec) { + struct statvfs statfs_info; + std::string path(spec.GetPath()); + if (statvfs(path.c_str(), &statfs_info) == 0) + return ::IsLocal(statfs_info); + return false; } #else -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - struct statfs statfs_info; - std::string path (spec.GetPath()); - if (statfs(path.c_str(), &statfs_info) == 0) - return ::IsLocal(statfs_info); - return false; +bool FileSystem::IsLocal(const FileSpec &spec) { + struct statfs statfs_info; + std::string path(spec.GetPath()); + if (statfs(path.c_str(), &statfs_info) == 0) + return ::IsLocal(statfs_info); + return false; } #endif -FILE * -FileSystem::Fopen(const char *path, const char *mode) -{ - return ::fopen(path, mode); +FILE *FileSystem::Fopen(const char *path, const char *mode) { + return ::fopen(path, mode); } -int -FileSystem::Stat(const char *path, struct stat *stats) -{ - return ::stat(path, stats); +int FileSystem::Stat(const char *path, struct stat *stats) { + return ::stat(path, stats); } diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp index d0ef2ca..9ff9662 100644 --- a/lldb/source/Host/posix/HostInfoPosix.cpp +++ b/lldb/source/Host/posix/HostInfoPosix.cpp @@ -28,27 +28,20 @@ using namespace lldb_private; -size_t -HostInfoPosix::GetPageSize() -{ - return ::getpagesize(); -} - -bool -HostInfoPosix::GetHostname(std::string &s) -{ - char hostname[PATH_MAX]; - hostname[sizeof(hostname) - 1] = '\0'; - if (::gethostname(hostname, sizeof(hostname) - 1) == 0) - { - struct hostent *h = ::gethostbyname(hostname); - if (h) - s.assign(h->h_name); - else - s.assign(hostname); - return true; - } - return false; +size_t HostInfoPosix::GetPageSize() { return ::getpagesize(); } + +bool HostInfoPosix::GetHostname(std::string &s) { + char hostname[PATH_MAX]; + hostname[sizeof(hostname) - 1] = '\0'; + if (::gethostname(hostname, sizeof(hostname) - 1) == 0) { + struct hostent *h = ::gethostbyname(hostname); + if (h) + s.assign(h->h_name); + else + s.assign(hostname); + return true; + } + return false; } #ifdef __ANDROID_NDK__ @@ -62,194 +55,164 @@ HostInfoPosix::GetHostname(std::string &s) static std::mutex s_getpwuid_lock; #endif -const char * -HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name) -{ +const char *HostInfoPosix::LookupUserName(uint32_t uid, + std::string &user_name) { #ifdef USE_GETPWUID - // getpwuid_r is missing from android-9 - // make getpwuid thread safe with a mutex - std::lock_guard<std::mutex> lock(s_getpwuid_lock); - struct passwd *user_info_ptr = ::getpwuid(uid); - if (user_info_ptr) - { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + // getpwuid_r is missing from android-9 + // make getpwuid thread safe with a mutex + std::lock_guard<std::mutex> lock(s_getpwuid_lock); + struct passwd *user_info_ptr = ::getpwuid(uid); + if (user_info_ptr) { + user_name.assign(user_info_ptr->pw_name); + return user_name.c_str(); + } #else - struct passwd user_info; - struct passwd *user_info_ptr = &user_info; - char user_buffer[PATH_MAX]; - size_t user_buffer_size = sizeof(user_buffer); - if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0) - { - if (user_info_ptr) - { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + struct passwd user_info; + struct passwd *user_info_ptr = &user_info; + char user_buffer[PATH_MAX]; + size_t user_buffer_size = sizeof(user_buffer); + if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, + &user_info_ptr) == 0) { + if (user_info_ptr) { + user_name.assign(user_info_ptr->pw_name); + return user_name.c_str(); } + } #endif - user_name.clear(); - return nullptr; + user_name.clear(); + return nullptr; } -const char * -HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name) -{ +const char *HostInfoPosix::LookupGroupName(uint32_t gid, + std::string &group_name) { #ifndef __ANDROID__ - char group_buffer[PATH_MAX]; - size_t group_buffer_size = sizeof(group_buffer); - struct group group_info; - struct group *group_info_ptr = &group_info; - // Try the threadsafe version first - if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0) - { - if (group_info_ptr) - { - group_name.assign(group_info_ptr->gr_name); - return group_name.c_str(); - } + char group_buffer[PATH_MAX]; + size_t group_buffer_size = sizeof(group_buffer); + struct group group_info; + struct group *group_info_ptr = &group_info; + // Try the threadsafe version first + if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, + &group_info_ptr) == 0) { + if (group_info_ptr) { + group_name.assign(group_info_ptr->gr_name); + return group_name.c_str(); } - else - { - // The threadsafe version isn't currently working for me on darwin, but the 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); - return group_name.c_str(); - } + } else { + // The threadsafe version isn't currently working for me on darwin, but the + // 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); + return group_name.c_str(); } - group_name.clear(); + } + group_name.clear(); #else - assert(false && "getgrgid_r() not supported on Android"); + assert(false && "getgrgid_r() not supported on Android"); #endif - return NULL; + return NULL; } -uint32_t -HostInfoPosix::GetUserID() -{ - return getuid(); -} +uint32_t HostInfoPosix::GetUserID() { return getuid(); } -uint32_t -HostInfoPosix::GetGroupID() -{ - return getgid(); -} +uint32_t HostInfoPosix::GetGroupID() { return getgid(); } -uint32_t -HostInfoPosix::GetEffectiveUserID() -{ - return geteuid(); -} +uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); } -uint32_t -HostInfoPosix::GetEffectiveGroupID() -{ - return getegid(); -} +uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } -FileSpec -HostInfoPosix::GetDefaultShell() -{ - return FileSpec("/bin/sh", false); -} +FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh", false); } -bool -HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); +bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; + 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)); + char raw_path[PATH_MAX]; + lldb_file_spec.GetPath(raw_path, sizeof(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. + if (log) + log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to " + "derive the bin path (ePathTypeSupportExecutableDir) from " + "this path: %s", + raw_path); + char *lib_pos = ::strstr(raw_path, "/lib"); + if (lib_pos != nullptr) { + // Now write in bin in place of lib. + ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin"); - // 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. if (log) - log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from " - "this path: %s", - raw_path); - char *lib_pos = ::strstr(raw_path, "/lib"); - if (lib_pos != nullptr) - { - // Now write in bin in place of lib. - ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin"); - - if (log) - log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path); - } - else - { - if (log) - log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction", - __FUNCTION__); - } - file_spec.GetDirectory().SetCString(raw_path); - return (bool)file_spec.GetDirectory(); + log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, + raw_path); + } else { + if (log) + log->Printf("Host::%s() failed to find /lib/liblldb within the shared " + "lib path, bailing on bin path construction", + __FUNCTION__); + } + file_spec.GetDirectory().SetCString(raw_path); + return (bool)file_spec.GetDirectory(); } -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::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) -{ +bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) { #ifndef LLDB_DISABLE_PYTHON - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; + 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)); + 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; + // 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"; + 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); + // 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; + file_spec.GetDirectory().SetCString(raw_path); + return true; #endif #else - return false; + return false; #endif } -bool -HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var) -{ - if (const char *pvar = ::getenv(var_name.c_str())) - { - var = std::string(pvar); - return true; - } - return false; +bool HostInfoPosix::GetEnvironmentVar(const std::string &var_name, + std::string &var) { + if (const char *pvar = ::getenv(var_name.c_str())) { + var = std::string(pvar); + return true; + } + return false; } diff --git a/lldb/source/Host/posix/HostProcessPosix.cpp b/lldb/source/Host/posix/HostProcessPosix.cpp index 93844d9..9dd9fef 100644 --- a/lldb/source/Host/posix/HostProcessPosix.cpp +++ b/lldb/source/Host/posix/HostProcessPosix.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Host.h" -#include "lldb/Host/posix/HostProcessPosix.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/posix/HostProcessPosix.h" #include "llvm/ADT/STLExtras.h" @@ -17,97 +17,77 @@ using namespace lldb_private; -namespace -{ - const int kInvalidPosixProcess = 0; +namespace { +const int kInvalidPosixProcess = 0; } HostProcessPosix::HostProcessPosix() - : HostNativeProcessBase(kInvalidPosixProcess) -{ -} + : HostNativeProcessBase(kInvalidPosixProcess) {} HostProcessPosix::HostProcessPosix(lldb::process_t process) - : HostNativeProcessBase(process) -{ -} + : HostNativeProcessBase(process) {} -HostProcessPosix::~HostProcessPosix() -{ -} +HostProcessPosix::~HostProcessPosix() {} -Error HostProcessPosix::Signal(int signo) const -{ - if (m_process == kInvalidPosixProcess) - { - Error error; - error.SetErrorString("HostProcessPosix refers to an invalid process"); - return error; - } +Error HostProcessPosix::Signal(int signo) const { + if (m_process == kInvalidPosixProcess) { + Error error; + error.SetErrorString("HostProcessPosix refers to an invalid process"); + return error; + } - return HostProcessPosix::Signal(m_process, signo); + return HostProcessPosix::Signal(m_process, signo); } -Error HostProcessPosix::Signal(lldb::process_t process, int signo) -{ - Error error; +Error HostProcessPosix::Signal(lldb::process_t process, int signo) { + Error error; - if (-1 == ::kill(process, signo)) - error.SetErrorToErrno(); + if (-1 == ::kill(process, signo)) + error.SetErrorToErrno(); - return error; + return error; } -Error HostProcessPosix::Terminate() -{ - return Signal(SIGKILL); -} +Error HostProcessPosix::Terminate() { return Signal(SIGKILL); } -Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const -{ - Error error; +Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const { + Error error; - // Use special code here because proc/[pid]/exe is a symbolic link. - char link_path[PATH_MAX]; - if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1) - { - error.SetErrorString("Unable to build /proc/<pid>/exe string"); - return error; - } - - error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec); - if (!error.Success()) - return error; - - // If the binary has been deleted, the link name has " (deleted)" appended. - // Remove if there. - if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)")) - { - const char *filename = file_spec.GetFilename().GetCString(); - static const size_t deleted_len = strlen(" (deleted)"); - const size_t len = file_spec.GetFilename().GetLength(); - file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len); - } + // Use special code here because proc/[pid]/exe is a symbolic link. + char link_path[PATH_MAX]; + if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1) { + error.SetErrorString("Unable to build /proc/<pid>/exe string"); return error; -} + } -lldb::pid_t HostProcessPosix::GetProcessId() const -{ - return m_process; + error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec); + if (!error.Success()) + return error; + + // If the binary has been deleted, the link name has " (deleted)" appended. + // Remove if there. + if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)")) { + const char *filename = file_spec.GetFilename().GetCString(); + static const size_t deleted_len = strlen(" (deleted)"); + const size_t len = file_spec.GetFilename().GetLength(); + file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len); + } + return error; } -bool HostProcessPosix::IsRunning() const -{ - if (m_process == kInvalidPosixProcess) - return false; +lldb::pid_t HostProcessPosix::GetProcessId() const { return m_process; } + +bool HostProcessPosix::IsRunning() const { + if (m_process == kInvalidPosixProcess) + return false; - // Send this process the null signal. If it succeeds the process is running. - Error error = Signal(0); - return error.Success(); + // Send this process the null signal. If it succeeds the process is running. + Error error = Signal(0); + return error.Success(); } -HostThread -HostProcessPosix::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - return Host::StartMonitoringChildProcess(callback, m_process, monitor_signals); +HostThread HostProcessPosix::StartMonitoring( + const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { + return Host::StartMonitoringChildProcess(callback, m_process, + monitor_signals); } diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp index f1a6d6f..ac39899 100644 --- a/lldb/source/Host/posix/HostThreadPosix.cpp +++ b/lldb/source/Host/posix/HostThreadPosix.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" #include "lldb/Host/posix/HostThreadPosix.h" +#include "lldb/Core/Error.h" #include <errno.h> #include <pthread.h> @@ -16,67 +16,50 @@ using namespace lldb; using namespace lldb_private; -HostThreadPosix::HostThreadPosix() -{ -} +HostThreadPosix::HostThreadPosix() {} HostThreadPosix::HostThreadPosix(lldb::thread_t thread) - : HostNativeThreadBase(thread) -{ -} + : HostNativeThreadBase(thread) {} -HostThreadPosix::~HostThreadPosix() -{ -} +HostThreadPosix::~HostThreadPosix() {} -Error -HostThreadPosix::Join(lldb::thread_result_t *result) -{ - Error error; - if (IsJoinable()) - { - int err = ::pthread_join(m_thread, result); - error.SetError(err, lldb::eErrorTypePOSIX); - } - else - { - if (result) - *result = NULL; - error.SetError(EINVAL, eErrorTypePOSIX); - } +Error HostThreadPosix::Join(lldb::thread_result_t *result) { + Error error; + if (IsJoinable()) { + int err = ::pthread_join(m_thread, result); + error.SetError(err, lldb::eErrorTypePOSIX); + } else { + if (result) + *result = NULL; + error.SetError(EINVAL, eErrorTypePOSIX); + } - Reset(); - return error; + Reset(); + return error; } -Error -HostThreadPosix::Cancel() -{ - Error error; - if (IsJoinable()) - { +Error HostThreadPosix::Cancel() { + Error error; + if (IsJoinable()) { #ifndef __ANDROID__ #ifndef __FreeBSD__ - assert(false && "someone is calling HostThread::Cancel()"); + assert(false && "someone is calling HostThread::Cancel()"); #endif - int err = ::pthread_cancel(m_thread); - error.SetError(err, eErrorTypePOSIX); + int err = ::pthread_cancel(m_thread); + error.SetError(err, eErrorTypePOSIX); #else - error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); + error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); #endif - } - return error; + } + return error; } -Error -HostThreadPosix::Detach() -{ - Error error; - if (IsJoinable()) - { - int err = ::pthread_detach(m_thread); - error.SetError(err, eErrorTypePOSIX); - } - Reset(); - return error; +Error HostThreadPosix::Detach() { + Error error; + if (IsJoinable()) { + int err = ::pthread_detach(m_thread); + error.SetError(err, eErrorTypePOSIX); + } + Reset(); + return error; } diff --git a/lldb/source/Host/posix/LockFilePosix.cpp b/lldb/source/Host/posix/LockFilePosix.cpp index e52b648..d1cc6171 100644 --- a/lldb/source/Host/posix/LockFilePosix.cpp +++ b/lldb/source/Host/posix/LockFilePosix.cpp @@ -14,64 +14,47 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error fileLock (int fd, int cmd, int lock_type, const uint64_t start, const uint64_t len) -{ - struct flock fl; +Error fileLock(int fd, int cmd, int lock_type, const uint64_t start, + const uint64_t len) { + struct flock fl; - fl.l_type = lock_type; - fl.l_whence = SEEK_SET; - fl.l_start = start; - fl.l_len = len; - fl.l_pid = ::getpid (); + fl.l_type = lock_type; + fl.l_whence = SEEK_SET; + fl.l_start = start; + fl.l_len = len; + fl.l_pid = ::getpid(); - Error error; - if (::fcntl (fd, cmd, &fl) == -1) - error.SetErrorToErrno (); + Error error; + if (::fcntl(fd, cmd, &fl) == -1) + error.SetErrorToErrno(); - return error; + return error; } -} // namespace +} // namespace -LockFilePosix::LockFilePosix (int fd) - : LockFileBase (fd) -{ -} +LockFilePosix::LockFilePosix(int fd) : LockFileBase(fd) {} -LockFilePosix::~LockFilePosix () -{ - Unlock (); -} +LockFilePosix::~LockFilePosix() { Unlock(); } -Error -LockFilePosix::DoWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLKW, F_WRLCK, start, len); +Error LockFilePosix::DoWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLKW, F_WRLCK, start, len); } -Error -LockFilePosix::DoTryWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLK, F_WRLCK, start, len); +Error LockFilePosix::DoTryWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLK, F_WRLCK, start, len); } -Error -LockFilePosix::DoReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLKW, F_RDLCK, start, len); +Error LockFilePosix::DoReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLKW, F_RDLCK, start, len); } -Error -LockFilePosix::DoTryReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLK, F_RDLCK, start, len); +Error LockFilePosix::DoTryReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLK, F_RDLCK, start, len); } -Error -LockFilePosix::DoUnlock () -{ - return fileLock (m_fd, F_SETLK, F_UNLCK, m_start, m_len); +Error LockFilePosix::DoUnlock() { + return fileLock(m_fd, F_SETLK, F_UNLCK, m_start, m_len); } diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index 897f2d1..b6325a5 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -18,176 +18,162 @@ using namespace lldb_private; static sig_atomic_t g_signal_flags[NSIG]; -static void -SignalHandler(int signo, siginfo_t *info, void *) -{ - assert(signo < NSIG); - g_signal_flags[signo] = 1; +static void SignalHandler(int signo, siginfo_t *info, void *) { + assert(signo < NSIG); + g_signal_flags[signo] = 1; } - -MainLoopPosix::~MainLoopPosix() -{ - assert(m_read_fds.size() == 0); - assert(m_signals.size() == 0); +MainLoopPosix::~MainLoopPosix() { + assert(m_read_fds.size() == 0); + assert(m_signals.size() == 0); } MainLoopPosix::ReadHandleUP -MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Error &error) -{ - if (!object_sp || !object_sp->IsValid()) - { - error.SetErrorString("IO object is not valid."); - return nullptr; - } - - const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; - if (! inserted) - { - error.SetErrorStringWithFormat("File descriptor %d already monitored.", - object_sp->GetWaitableHandle()); - return nullptr; - } - - return CreateReadHandle(object_sp); +MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, + const Callback &callback, Error &error) { + if (!object_sp || !object_sp->IsValid()) { + error.SetErrorString("IO object is not valid."); + return nullptr; + } + + const bool inserted = + m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; + if (!inserted) { + error.SetErrorStringWithFormat("File descriptor %d already monitored.", + object_sp->GetWaitableHandle()); + return nullptr; + } + + return CreateReadHandle(object_sp); } -// We shall block the signal, then install the signal handler. The signal will be unblocked in +// We shall block the signal, then install the signal handler. The signal will +// be unblocked in // the Run() function to check for signal delivery. MainLoopPosix::SignalHandleUP -MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error) -{ - if (m_signals.find(signo) != m_signals.end()) - { - error.SetErrorStringWithFormat("Signal %d already monitored.", signo); - return nullptr; - } +MainLoopPosix::RegisterSignal(int signo, const Callback &callback, + Error &error) { + if (m_signals.find(signo) != m_signals.end()) { + error.SetErrorStringWithFormat("Signal %d already monitored.", signo); + return nullptr; + } + + SignalInfo info; + info.callback = callback; + struct sigaction new_action; + new_action.sa_sigaction = &SignalHandler; + new_action.sa_flags = SA_SIGINFO; + sigemptyset(&new_action.sa_mask); + sigaddset(&new_action.sa_mask, signo); + + sigset_t old_set; + if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) { + error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", + ret); + return nullptr; + } + + info.was_blocked = sigismember(&old_set, signo); + if (sigaction(signo, &new_action, &info.old_action) == -1) { + error.SetErrorToErrno(); + if (!info.was_blocked) + pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); + return nullptr; + } + + m_signals.insert({signo, info}); + g_signal_flags[signo] = 0; + + return SignalHandleUP(new SignalHandle(*this, signo)); +} - SignalInfo info; - info.callback = callback; - struct sigaction new_action; - new_action.sa_sigaction = &SignalHandler; - new_action.sa_flags = SA_SIGINFO; - sigemptyset(&new_action.sa_mask); - sigaddset(&new_action.sa_mask, signo); - - sigset_t old_set; - if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) - { - error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", ret); - return nullptr; - } +void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { + bool erased = m_read_fds.erase(handle); + UNUSED_IF_ASSERT_DISABLED(erased); + assert(erased); +} - info.was_blocked = sigismember(&old_set, signo); - if (sigaction(signo, &new_action, &info.old_action) == -1) - { - error.SetErrorToErrno(); - if (!info.was_blocked) - pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); - return nullptr; - } +void MainLoopPosix::UnregisterSignal(int signo) { + // We undo the actions of RegisterSignal on a best-effort basis. + auto it = m_signals.find(signo); + assert(it != m_signals.end()); - m_signals.insert({signo, info}); - g_signal_flags[signo] = 0; + sigaction(signo, &it->second.old_action, nullptr); - return SignalHandleUP(new SignalHandle(*this, signo)); -} + sigset_t set; + sigemptyset(&set); + sigaddset(&set, signo); + pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, + nullptr); -void -MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) -{ - bool erased = m_read_fds.erase(handle); - UNUSED_IF_ASSERT_DISABLED(erased); - assert(erased); + m_signals.erase(it); } -void -MainLoopPosix::UnregisterSignal(int signo) -{ - // We undo the actions of RegisterSignal on a best-effort basis. - auto it = m_signals.find(signo); - assert(it != m_signals.end()); +Error MainLoopPosix::Run() { + std::vector<int> signals; + sigset_t sigmask; + std::vector<int> read_fds; + fd_set read_fd_set; + m_terminate_request = false; + + // run until termination or until we run out of things to listen to + while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { + // To avoid problems with callbacks changing the things we're supposed to + // listen to, we + // will store the *real* list of events separately. + signals.clear(); + read_fds.clear(); + FD_ZERO(&read_fd_set); + int nfds = 0; + + if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask)) + return Error("pthread_sigmask failed with error %d\n", ret); + + for (const auto &fd : m_read_fds) { + read_fds.push_back(fd.first); + FD_SET(fd.first, &read_fd_set); + nfds = std::max(nfds, fd.first + 1); + } - sigaction(signo, &it->second.old_action, nullptr); + for (const auto &sig : m_signals) { + signals.push_back(sig.first); + sigdelset(&sigmask, sig.first); + } - sigset_t set; - sigemptyset(&set); - sigaddset(&set, signo); - pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr); + if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == + -1 && + errno != EINTR) + return Error(errno, eErrorTypePOSIX); - m_signals.erase(it); -} + for (int sig : signals) { + if (g_signal_flags[sig] == 0) + continue; // No signal + g_signal_flags[sig] = 0; + + auto it = m_signals.find(sig); + if (it == m_signals.end()) + continue; // Signal must have gotten unregistered in the meantime + + it->second.callback(*this); // Do the work -Error -MainLoopPosix::Run() -{ - std::vector<int> signals; - sigset_t sigmask; - std::vector<int> read_fds; - fd_set read_fd_set; - m_terminate_request = false; - - // run until termination or until we run out of things to listen to - while (! m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) - { - // To avoid problems with callbacks changing the things we're supposed to listen to, we - // will store the *real* list of events separately. - signals.clear(); - read_fds.clear(); - FD_ZERO(&read_fd_set); - int nfds = 0; - - if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask)) - return Error("pthread_sigmask failed with error %d\n", ret); - - for (const auto &fd: m_read_fds) - { - read_fds.push_back(fd.first); - FD_SET(fd.first, &read_fd_set); - nfds = std::max(nfds, fd.first+1); - } - - for (const auto &sig: m_signals) - { - signals.push_back(sig.first); - sigdelset(&sigmask, sig.first); - } - - if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR) - return Error(errno, eErrorTypePOSIX); - - for (int sig: signals) - { - if (g_signal_flags[sig] == 0) - continue; // No signal - g_signal_flags[sig] = 0; - - auto it = m_signals.find(sig); - if (it == m_signals.end()) - continue; // Signal must have gotten unregistered in the meantime - - it->second.callback(*this); // Do the work - - if (m_terminate_request) - return Error(); - } - - for (int fd: read_fds) - { - if (!FD_ISSET(fd, &read_fd_set)) - continue; // Not ready - - auto it = m_read_fds.find(fd); - if (it == m_read_fds.end()) - continue; // File descriptor must have gotten unregistered in the meantime - - it->second(*this); // Do the work - - if (m_terminate_request) - return Error(); - } + if (m_terminate_request) + return Error(); } - return Error(); -} + for (int fd : read_fds) { + if (!FD_ISSET(fd, &read_fd_set)) + continue; // Not ready + + auto it = m_read_fds.find(fd); + if (it == m_read_fds.end()) + continue; // File descriptor must have gotten unregistered in the + // meantime + + it->second(*this); // Do the work + if (m_terminate_request) + return Error(); + } + } + return Error(); +} diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp index 6695bbf..a653b3e 100644 --- a/lldb/source/Host/posix/PipePosix.cpp +++ b/lldb/source/Host/posix/PipePosix.cpp @@ -26,9 +26,9 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> -#include <unistd.h> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> using namespace lldb; using namespace lldb_private; @@ -39,343 +39,280 @@ enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE // pipe2 is supported by a limited set of platforms // TODO: Add more platforms that support pipe2. -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__) +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ + defined(__NetBSD__) #define PIPE2_SUPPORTED 1 #else #define PIPE2_SUPPORTED 0 #endif -namespace -{ +namespace { constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100; #if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED -bool SetCloexecFlag(int fd) -{ - int flags = ::fcntl(fd, F_GETFD); - if (flags == -1) - return false; - return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); +bool SetCloexecFlag(int fd) { + int flags = ::fcntl(fd, F_GETFD); + if (flags == -1) + return false; + return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); } #endif -std::chrono::time_point<std::chrono::steady_clock> -Now() -{ - return std::chrono::steady_clock::now(); +std::chrono::time_point<std::chrono::steady_clock> Now() { + return std::chrono::steady_clock::now(); } - } PipePosix::PipePosix() - : m_fds{ - PipePosix::kInvalidDescriptor, - PipePosix::kInvalidDescriptor - } {} + : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {} -PipePosix::PipePosix(int read_fd, int write_fd) - : m_fds{read_fd, write_fd} {} +PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {} PipePosix::PipePosix(PipePosix &&pipe_posix) : PipeBase{std::move(pipe_posix)}, - m_fds{ - pipe_posix.ReleaseReadFileDescriptor(), - pipe_posix.ReleaseWriteFileDescriptor() - } {} - -PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) -{ - PipeBase::operator=(std::move(pipe_posix)); - m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor(); - m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor(); - return *this; + m_fds{pipe_posix.ReleaseReadFileDescriptor(), + pipe_posix.ReleaseWriteFileDescriptor()} {} + +PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) { + PipeBase::operator=(std::move(pipe_posix)); + m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor(); + m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor(); + return *this; } -PipePosix::~PipePosix() -{ - Close(); -} +PipePosix::~PipePosix() { Close(); } -Error -PipePosix::CreateNew(bool child_processes_inherit) -{ - if (CanRead() || CanWrite()) - return Error(EINVAL, eErrorTypePOSIX); +Error PipePosix::CreateNew(bool child_processes_inherit) { + if (CanRead() || CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); - Error error; + Error error; #if PIPE2_SUPPORTED - if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) - return error; + if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) + return error; #else - if (::pipe(m_fds) == 0) - { + if (::pipe(m_fds) == 0) { #ifdef FD_CLOEXEC - if (!child_processes_inherit) - { - if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) - { - error.SetErrorToErrno(); - Close(); - return error; - } - } -#endif + if (!child_processes_inherit) { + if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) { + error.SetErrorToErrno(); + Close(); return error; + } } #endif - - error.SetErrorToErrno(); - m_fds[READ] = PipePosix::kInvalidDescriptor; - m_fds[WRITE] = PipePosix::kInvalidDescriptor; return error; + } +#endif + + error.SetErrorToErrno(); + m_fds[READ] = PipePosix::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return error; } -Error -PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error("Pipe is already opened"); +Error PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); - Error error; - if (::mkfifo(name.data(), 0660) != 0) - error.SetErrorToErrno(); + Error error; + if (::mkfifo(name.data(), 0660) != 0) + error.SetErrorToErrno(); - return error; + return error; } -Error -PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name) -{ - llvm::SmallString<PATH_MAX> named_pipe_path; - llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); - FileSpec tmpdir_file_spec; - tmpdir_file_spec.Clear(); - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } - else - { - tmpdir_file_spec.AppendPathComponent("/tmp"); - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } - - // 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. - Error error; - do { - llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), named_pipe_path); - error = CreateNew(named_pipe_path, child_process_inherit); - } while (error.GetError() == EEXIST); - - if (error.Success()) - name = named_pipe_path; - return error; +Error PipePosix::CreateWithUniqueName(llvm::StringRef prefix, + bool child_process_inherit, + llvm::SmallVectorImpl<char> &name) { + llvm::SmallString<PATH_MAX> named_pipe_path; + llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); + FileSpec tmpdir_file_spec; + tmpdir_file_spec.Clear(); + if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } else { + tmpdir_file_spec.AppendPathComponent("/tmp"); + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + + // 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. + Error error; + do { + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), + named_pipe_path); + error = CreateNew(named_pipe_path, child_process_inherit); + } while (error.GetError() == EEXIST); + + if (error.Success()) + name = named_pipe_path; + return error; } -Error -PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error("Pipe is already opened"); +Error PipePosix::OpenAsReader(llvm::StringRef name, + bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); - int flags = O_RDONLY | O_NONBLOCK; - if (!child_process_inherit) - flags |= O_CLOEXEC; + int flags = O_RDONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; - Error error; - int fd = ::open(name.data(), flags); - if (fd != -1) - m_fds[READ] = fd; - else - error.SetErrorToErrno(); + Error error; + int fd = ::open(name.data(), flags); + if (fd != -1) + m_fds[READ] = fd; + else + error.SetErrorToErrno(); - return error; + return error; } -Error -PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) -{ - if (CanRead() || CanWrite()) - return Error("Pipe is already opened"); - - int flags = O_WRONLY | O_NONBLOCK; - if (!child_process_inherit) - flags |= O_CLOEXEC; - - using namespace std::chrono; - const auto finish_time = Now() + timeout; - - while (!CanWrite()) - { - if (timeout != microseconds::zero()) - { - const auto dur = duration_cast<microseconds>(finish_time - Now()).count(); - if (dur <= 0) - return Error("timeout exceeded - reader hasn't opened so far"); - } - - errno = 0; - int fd = ::open(name.data(), flags); - if (fd == -1) - { - const auto errno_copy = errno; - // We may get ENXIO if a reader side of the pipe hasn't opened yet. - if (errno_copy != ENXIO) - return Error(errno_copy, eErrorTypePOSIX); - - std::this_thread::sleep_for(milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS)); - } - else - { - m_fds[WRITE] = fd; - } +Error PipePosix::OpenAsWriterWithTimeout( + llvm::StringRef name, bool child_process_inherit, + const std::chrono::microseconds &timeout) { + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); + + int flags = O_WRONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; + + using namespace std::chrono; + const auto finish_time = Now() + timeout; + + while (!CanWrite()) { + if (timeout != microseconds::zero()) { + const auto dur = duration_cast<microseconds>(finish_time - Now()).count(); + if (dur <= 0) + return Error("timeout exceeded - reader hasn't opened so far"); } - return Error(); -} + errno = 0; + int fd = ::open(name.data(), flags); + if (fd == -1) { + const auto errno_copy = errno; + // We may get ENXIO if a reader side of the pipe hasn't opened yet. + if (errno_copy != ENXIO) + return Error(errno_copy, eErrorTypePOSIX); + + std::this_thread::sleep_for( + milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS)); + } else { + m_fds[WRITE] = fd; + } + } -int -PipePosix::GetReadFileDescriptor() const -{ - return m_fds[READ]; + return Error(); } -int -PipePosix::GetWriteFileDescriptor() const -{ - return m_fds[WRITE]; -} +int PipePosix::GetReadFileDescriptor() const { return m_fds[READ]; } -int -PipePosix::ReleaseReadFileDescriptor() -{ - const int fd = m_fds[READ]; - m_fds[READ] = PipePosix::kInvalidDescriptor; - return fd; +int PipePosix::GetWriteFileDescriptor() const { return m_fds[WRITE]; } + +int PipePosix::ReleaseReadFileDescriptor() { + const int fd = m_fds[READ]; + m_fds[READ] = PipePosix::kInvalidDescriptor; + return fd; } -int -PipePosix::ReleaseWriteFileDescriptor() -{ - const int fd = m_fds[WRITE]; - m_fds[WRITE] = PipePosix::kInvalidDescriptor; - return fd; +int PipePosix::ReleaseWriteFileDescriptor() { + const int fd = m_fds[WRITE]; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return fd; } -void -PipePosix::Close() -{ - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); +void PipePosix::Close() { + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); } -Error -PipePosix::Delete(llvm::StringRef name) -{ - return FileSystem::Unlink(FileSpec{name.data(), true}); +Error PipePosix::Delete(llvm::StringRef name) { + return FileSystem::Unlink(FileSpec{name.data(), true}); } -bool -PipePosix::CanRead() const -{ - return m_fds[READ] != PipePosix::kInvalidDescriptor; +bool PipePosix::CanRead() const { + return m_fds[READ] != PipePosix::kInvalidDescriptor; } -bool -PipePosix::CanWrite() const -{ - return m_fds[WRITE] != PipePosix::kInvalidDescriptor; +bool PipePosix::CanWrite() const { + return m_fds[WRITE] != PipePosix::kInvalidDescriptor; } -void -PipePosix::CloseReadFileDescriptor() -{ - if (CanRead()) - { - close(m_fds[READ]); - m_fds[READ] = PipePosix::kInvalidDescriptor; - } +void PipePosix::CloseReadFileDescriptor() { + if (CanRead()) { + close(m_fds[READ]); + m_fds[READ] = PipePosix::kInvalidDescriptor; + } } -void -PipePosix::CloseWriteFileDescriptor() -{ - if (CanWrite()) - { - close(m_fds[WRITE]); - m_fds[WRITE] = PipePosix::kInvalidDescriptor; - } +void PipePosix::CloseWriteFileDescriptor() { + if (CanWrite()) { + close(m_fds[WRITE]); + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + } } -Error -PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) -{ - bytes_read = 0; - if (!CanRead()) - return Error(EINVAL, eErrorTypePOSIX); - - const int fd = GetReadFileDescriptor(); - - SelectHelper select_helper; - select_helper.SetTimeout(timeout); - select_helper.FDSetRead(fd); - - Error error; - while (error.Success()) - { - error = select_helper.Select(); - if (error.Success()) - { - auto result = ::read(fd, reinterpret_cast<char*>(buf) + bytes_read, size - bytes_read); - if (result != -1) - { - bytes_read += result; - if (bytes_read == size || result == 0) - break; - } - else - { - error.SetErrorToErrno(); - break; - } - } +Error PipePosix::ReadWithTimeout(void *buf, size_t size, + const std::chrono::microseconds &timeout, + size_t &bytes_read) { + bytes_read = 0; + if (!CanRead()) + return Error(EINVAL, eErrorTypePOSIX); + + const int fd = GetReadFileDescriptor(); + + SelectHelper select_helper; + select_helper.SetTimeout(timeout); + select_helper.FDSetRead(fd); + + Error error; + while (error.Success()) { + error = select_helper.Select(); + if (error.Success()) { + auto result = ::read(fd, reinterpret_cast<char *>(buf) + bytes_read, + size - bytes_read); + if (result != -1) { + bytes_read += result; + if (bytes_read == size || result == 0) + break; + } else { + error.SetErrorToErrno(); + break; + } } - return error; + } + return error; } -Error -PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) -{ - bytes_written = 0; - if (!CanWrite()) - return Error(EINVAL, eErrorTypePOSIX); - - const int fd = GetWriteFileDescriptor(); - SelectHelper select_helper; - select_helper.SetTimeout(std::chrono::seconds(0)); - select_helper.FDSetWrite(fd); - - Error error; - while (error.Success()) - { - error = select_helper.Select(); - if (error.Success()) - { - auto result = ::write(fd, reinterpret_cast<const char*>(buf) + bytes_written, size - bytes_written); - if (result != -1) - { - bytes_written += result; - if (bytes_written == size) - break; - } - else - { - error.SetErrorToErrno(); - } - } +Error PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) { + bytes_written = 0; + if (!CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); + + const int fd = GetWriteFileDescriptor(); + SelectHelper select_helper; + select_helper.SetTimeout(std::chrono::seconds(0)); + select_helper.FDSetWrite(fd); + + Error error; + while (error.Success()) { + error = select_helper.Select(); + if (error.Success()) { + auto result = + ::write(fd, reinterpret_cast<const char *>(buf) + bytes_written, + size - bytes_written); + if (result != -1) { + bytes_written += result; + if (bytes_written == size) + break; + } else { + error.SetErrorToErrno(); + } } - return error; + } + return error; } diff --git a/lldb/source/Host/posix/ProcessLauncherPosix.cpp b/lldb/source/Host/posix/ProcessLauncherPosix.cpp index dd5c512..f90bf0c 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosix.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosix.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/posix/ProcessLauncherPosix.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Host/posix/ProcessLauncherPosix.h" #include "lldb/Target/ProcessLaunchInfo.h" @@ -19,15 +19,16 @@ using namespace lldb; using namespace lldb_private; HostProcess -ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - lldb::pid_t pid; - char exe_path[PATH_MAX]; +ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + lldb::pid_t pid; + char exe_path[PATH_MAX]; - launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this - // ProcessLauncher when it wants a posix_spawn launch. - error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); - return HostProcess(pid); + // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make + // MacOSX re-use this + // ProcessLauncher when it wants a posix_spawn launch. + error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); + return HostProcess(pid); } diff --git a/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp b/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp index 9743ed4..e89e174 100644 --- a/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp +++ b/lldb/source/Host/windows/ConnectionGenericFileWindows.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/TimeValue.h" -#include "lldb/Host/windows/ConnectionGenericFileWindows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -19,345 +19,319 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -// This is a simple helper class to package up the information needed to return from a Read/Write -// operation function. Since there is a lot of code to be run before exit regardless of whether the -// operation succeeded or failed, combined with many possible return paths, this is the cleanest +namespace { +// This is a simple helper class to package up the information needed to return +// from a Read/Write +// operation function. Since there is a lot of code to be run before exit +// regardless of whether the +// operation succeeded or failed, combined with many possible return paths, this +// is the cleanest // way to represent it. -class ReturnInfo -{ - public: - void - Set(size_t bytes, ConnectionStatus status, DWORD error_code) - { - m_error.SetError(error_code, eErrorTypeWin32); - m_bytes = bytes; - m_status = status; - } - - void - Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) - { - m_error.SetErrorString(error_msg.data()); - m_bytes = bytes; - m_status = status; - } - - size_t - GetBytes() const - { - return m_bytes; - } - ConnectionStatus - GetStatus() const - { - return m_status; - } - const Error & - GetError() const - { - return m_error; - } - - private: - Error m_error; - size_t m_bytes; - ConnectionStatus m_status; +class ReturnInfo { +public: + void Set(size_t bytes, ConnectionStatus status, DWORD error_code) { + m_error.SetError(error_code, eErrorTypeWin32); + m_bytes = bytes; + m_status = status; + } + + void Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) { + m_error.SetErrorString(error_msg.data()); + m_bytes = bytes; + m_status = status; + } + + size_t GetBytes() const { return m_bytes; } + ConnectionStatus GetStatus() const { return m_status; } + const Error &GetError() const { return m_error; } + +private: + Error m_error; + size_t m_bytes; + ConnectionStatus m_status; }; } ConnectionGenericFile::ConnectionGenericFile() - : m_file(INVALID_HANDLE_VALUE) - , m_owns_file(false) -{ - ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - InitializeEventHandles(); + : m_file(INVALID_HANDLE_VALUE), m_owns_file(false) { + ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + InitializeEventHandles(); } ConnectionGenericFile::ConnectionGenericFile(lldb::file_t file, bool owns_file) - : m_file(file) - , m_owns_file(owns_file) -{ - ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - InitializeEventHandles(); + : m_file(file), m_owns_file(owns_file) { + ::ZeroMemory(&m_overlapped, sizeof(m_overlapped)); + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + InitializeEventHandles(); } -ConnectionGenericFile::~ConnectionGenericFile() -{ - if (m_owns_file && IsConnected()) - ::CloseHandle(m_file); +ConnectionGenericFile::~ConnectionGenericFile() { + if (m_owns_file && IsConnected()) + ::CloseHandle(m_file); - ::CloseHandle(m_event_handles[kBytesAvailableEvent]); - ::CloseHandle(m_event_handles[kInterruptEvent]); + ::CloseHandle(m_event_handles[kBytesAvailableEvent]); + ::CloseHandle(m_event_handles[kInterruptEvent]); } -void -ConnectionGenericFile::InitializeEventHandles() -{ - m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL); - - // Note, we should use a manual reset event for the hEvent argument of the OVERLAPPED. This - // is because both WaitForMultipleObjects and GetOverlappedResult (if you set the bWait - // argument to TRUE) will wait for the event to be signalled. If we use an auto-reset event, - // WaitForMultipleObjects will reset the event, return successfully, and then - // GetOverlappedResult will block since the event is no longer signalled. - m_event_handles[kBytesAvailableEvent] = ::CreateEvent(NULL, TRUE, FALSE, NULL); +void ConnectionGenericFile::InitializeEventHandles() { + m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL); + + // Note, we should use a manual reset event for the hEvent argument of the + // OVERLAPPED. This + // is because both WaitForMultipleObjects and GetOverlappedResult (if you set + // the bWait + // argument to TRUE) will wait for the event to be signalled. If we use an + // auto-reset event, + // WaitForMultipleObjects will reset the event, return successfully, and then + // GetOverlappedResult will block since the event is no longer signalled. + m_event_handles[kBytesAvailableEvent] = + ::CreateEvent(NULL, TRUE, FALSE, NULL); } -bool -ConnectionGenericFile::IsConnected() const -{ - return m_file && (m_file != INVALID_HANDLE_VALUE); +bool ConnectionGenericFile::IsConnected() const { + return m_file && (m_file != INVALID_HANDLE_VALUE); } -lldb::ConnectionStatus -ConnectionGenericFile::Connect(const char *s, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionGenericFile::Connect (url = '%s')", static_cast<void *>(this), s); - - if (strstr(s, "file://") != s) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); - return eConnectionStatusError; - } +lldb::ConnectionStatus ConnectionGenericFile::Connect(const char *s, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionGenericFile::Connect (url = '%s')", + static_cast<void *>(this), s); - if (IsConnected()) - { - ConnectionStatus status = Disconnect(error_ptr); - if (status != eConnectionStatusSuccess) - return status; - } - - // file://PATH - const char *path = s + strlen("file://"); - // Open the file for overlapped access. If it does not exist, create it. We open it overlapped - // so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read - // to be interrupted by an event object. - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - if (error_ptr) - error_ptr->SetError(1, eErrorTypeGeneric); - return eConnectionStatusError; - } - m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, - FILE_FLAG_OVERLAPPED, NULL); - if (m_file == INVALID_HANDLE_VALUE) - { - if (error_ptr) - error_ptr->SetError(::GetLastError(), eErrorTypeWin32); - return eConnectionStatusError; - } + if (strstr(s, "file://") != s) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", + s); + return eConnectionStatusError; + } + + if (IsConnected()) { + ConnectionStatus status = Disconnect(error_ptr); + if (status != eConnectionStatusSuccess) + return status; + } + + // file://PATH + const char *path = s + strlen("file://"); + // Open the file for overlapped access. If it does not exist, create it. We + // open it overlapped + // so that we can issue asynchronous reads and then use WaitForMultipleObjects + // to allow the read + // to be interrupted by an event object. + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + if (error_ptr) + error_ptr->SetError(1, eErrorTypeGeneric); + return eConnectionStatusError; + } + m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, + FILE_FLAG_OVERLAPPED, NULL); + if (m_file == INVALID_HANDLE_VALUE) { + if (error_ptr) + error_ptr->SetError(::GetLastError(), eErrorTypeWin32); + return eConnectionStatusError; + } - m_owns_file = true; - m_uri.assign(s); - return eConnectionStatusSuccess; + m_owns_file = true; + m_uri.assign(s); + return eConnectionStatusSuccess; } -lldb::ConnectionStatus -ConnectionGenericFile::Disconnect(Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionGenericFile::Disconnect ()", static_cast<void *>(this)); - - if (!IsConnected()) - return eConnectionStatusSuccess; - - // Reset the handle so that after we unblock any pending reads, subsequent calls to Read() will - // see a disconnected state. - HANDLE old_file = m_file; - m_file = INVALID_HANDLE_VALUE; +lldb::ConnectionStatus ConnectionGenericFile::Disconnect(Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionGenericFile::Disconnect ()", + static_cast<void *>(this)); - // Set the disconnect event so that any blocking reads unblock, then cancel any pending IO operations. - ::CancelIoEx(old_file, &m_overlapped); - - // Close the file handle if we owned it, but don't close the event handles. We could always - // reconnect with the same Connection instance. - if (m_owns_file) - ::CloseHandle(old_file); - - ::ZeroMemory(&m_file_position, sizeof(m_file_position)); - m_owns_file = false; - m_uri.clear(); + if (!IsConnected()) return eConnectionStatusSuccess; + + // Reset the handle so that after we unblock any pending reads, subsequent + // calls to Read() will + // see a disconnected state. + HANDLE old_file = m_file; + m_file = INVALID_HANDLE_VALUE; + + // Set the disconnect event so that any blocking reads unblock, then cancel + // any pending IO operations. + ::CancelIoEx(old_file, &m_overlapped); + + // Close the file handle if we owned it, but don't close the event handles. + // We could always + // reconnect with the same Connection instance. + if (m_owns_file) + ::CloseHandle(old_file); + + ::ZeroMemory(&m_file_position, sizeof(m_file_position)); + m_owns_file = false; + m_uri.clear(); + return eConnectionStatusSuccess; } -size_t -ConnectionGenericFile::Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr) -{ - ReturnInfo return_info; - BOOL result = 0; - DWORD bytes_read = 0; +size_t ConnectionGenericFile::Read(void *dst, size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr) { + ReturnInfo return_info; + BOOL result = 0; + DWORD bytes_read = 0; - if (error_ptr) - error_ptr->Clear(); + if (error_ptr) + error_ptr->Clear(); - if (!IsConnected()) - { - return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + if (!IsConnected()) { + return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + goto finish; + } + + m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent]; + + result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped); + if (result || ::GetLastError() == ERROR_IO_PENDING) { + if (!result) { + // The expected return path. The operation is pending. Wait for the + // operation to complete + // or be interrupted. + TimeValue time_value; + time_value.OffsetWithMicroSeconds(timeout_usec); + DWORD milliseconds = time_value.milliseconds(); + DWORD wait_result = + ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles), + m_event_handles, FALSE, milliseconds); + // All of the events are manual reset events, so make sure we reset them + // to non-signalled. + switch (wait_result) { + case WAIT_OBJECT_0 + kBytesAvailableEvent: + break; + case WAIT_OBJECT_0 + kInterruptEvent: + return_info.Set(0, eConnectionStatusInterrupted, 0); goto finish; - } - - m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent]; - - result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped); - if (result || ::GetLastError() == ERROR_IO_PENDING) - { - if (!result) - { - // The expected return path. The operation is pending. Wait for the operation to complete - // or be interrupted. - TimeValue time_value; - time_value.OffsetWithMicroSeconds(timeout_usec); - DWORD milliseconds = time_value.milliseconds(); - DWORD wait_result = ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles), m_event_handles, FALSE, milliseconds); - // All of the events are manual reset events, so make sure we reset them to non-signalled. - switch (wait_result) - { - case WAIT_OBJECT_0 + kBytesAvailableEvent: - break; - case WAIT_OBJECT_0 + kInterruptEvent: - return_info.Set(0, eConnectionStatusInterrupted, 0); - goto finish; - case WAIT_TIMEOUT: - return_info.Set(0, eConnectionStatusTimedOut, 0); - goto finish; - case WAIT_FAILED: - return_info.Set(0, eConnectionStatusError, ::GetLastError()); - goto finish; - } - } - // The data is ready. Figure out how much was read and return; - if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) - { - DWORD result_error = ::GetLastError(); - // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a blocking read. - // This triggers a call to CancelIoEx, which causes the operation to complete and the - // result to be ERROR_OPERATION_ABORTED. - if (result_error == ERROR_HANDLE_EOF || result_error == ERROR_OPERATION_ABORTED || result_error == ERROR_BROKEN_PIPE) - return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); - else - return_info.Set(bytes_read, eConnectionStatusError, result_error); - } - else if (bytes_read == 0) - return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); - else - return_info.Set(bytes_read, eConnectionStatusSuccess, 0); - + case WAIT_TIMEOUT: + return_info.Set(0, eConnectionStatusTimedOut, 0); goto finish; - } - else if (::GetLastError() == ERROR_BROKEN_PIPE) - { - // The write end of a pipe was closed. This is equivalent to EOF. - return_info.Set(0, eConnectionStatusEndOfFile, 0); - } - else - { - // An unknown error occurred. Fail out. + case WAIT_FAILED: return_info.Set(0, eConnectionStatusError, ::GetLastError()); + goto finish; + } } + // The data is ready. Figure out how much was read and return; + if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) { + DWORD result_error = ::GetLastError(); + // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a + // blocking read. + // This triggers a call to CancelIoEx, which causes the operation to + // complete and the + // result to be ERROR_OPERATION_ABORTED. + if (result_error == ERROR_HANDLE_EOF || + result_error == ERROR_OPERATION_ABORTED || + result_error == ERROR_BROKEN_PIPE) + return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); + else + return_info.Set(bytes_read, eConnectionStatusError, result_error); + } else if (bytes_read == 0) + return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0); + else + return_info.Set(bytes_read, eConnectionStatusSuccess, 0); + goto finish; + } else if (::GetLastError() == ERROR_BROKEN_PIPE) { + // The write end of a pipe was closed. This is equivalent to EOF. + return_info.Set(0, eConnectionStatusEndOfFile, 0); + } else { + // An unknown error occurred. Fail out. + return_info.Set(0, eConnectionStatusError, ::GetLastError()); + } + goto finish; finish: - status = return_info.GetStatus(); - if (error_ptr) - *error_ptr = return_info.GetError(); - - // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here so that any - // subsequent operations don't immediately see bytes available. - ResetEvent(m_event_handles[kBytesAvailableEvent]); - - IncrementFilePointer(return_info.GetBytes()); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - { - log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR ", dst = %" PRIxPTR ", dst_len = %" PRIu64 - ") => %" PRIu64 ", error = %s", - this, m_file, dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(return_info.GetBytes()), - return_info.GetError().AsCString()); - } - - return return_info.GetBytes(); + status = return_info.GetStatus(); + if (error_ptr) + *error_ptr = return_info.GetError(); + + // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here + // so that any + // subsequent operations don't immediately see bytes available. + ResetEvent(m_event_handles[kBytesAvailableEvent]); + + IncrementFilePointer(return_info.GetBytes()); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) { + log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR + ", dst = %" PRIxPTR ", dst_len = %" PRIu64 ") => %" PRIu64 + ", error = %s", + this, m_file, dst, static_cast<uint64_t>(dst_len), + static_cast<uint64_t>(return_info.GetBytes()), + return_info.GetError().AsCString()); + } + + return return_info.GetBytes(); } -size_t -ConnectionGenericFile::Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr) -{ - ReturnInfo return_info; - DWORD bytes_written = 0; - BOOL result = 0; - - if (error_ptr) - error_ptr->Clear(); +size_t ConnectionGenericFile::Write(const void *src, size_t src_len, + lldb::ConnectionStatus &status, + Error *error_ptr) { + ReturnInfo return_info; + DWORD bytes_written = 0; + BOOL result = 0; - if (!IsConnected()) - { - return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); - goto finish; - } + if (error_ptr) + error_ptr->Clear(); - m_overlapped.hEvent = NULL; + if (!IsConnected()) { + return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE); + goto finish; + } - // Writes are not interruptible like reads are, so just block until it's done. - result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped); - if (!result && ::GetLastError() != ERROR_IO_PENDING) - { - return_info.Set(0, eConnectionStatusError, ::GetLastError()); - goto finish; - } + m_overlapped.hEvent = NULL; - if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE)) - { - return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError()); - goto finish; - } + // Writes are not interruptible like reads are, so just block until it's done. + result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped); + if (!result && ::GetLastError() != ERROR_IO_PENDING) { + return_info.Set(0, eConnectionStatusError, ::GetLastError()); + goto finish; + } - return_info.Set(bytes_written, eConnectionStatusSuccess, 0); + if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE)) { + return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError()); goto finish; + } + + return_info.Set(bytes_written, eConnectionStatusSuccess, 0); + goto finish; finish: - status = return_info.GetStatus(); - if (error_ptr) - *error_ptr = return_info.GetError(); - - IncrementFilePointer(return_info.GetBytes()); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - { - log->Printf("%" PRIxPTR " ConnectionGenericFile::Write() handle = %" PRIxPTR ", src = %" PRIxPTR ", src_len = %" PRIu64 - ") => %" PRIu64 ", error = %s", - this, m_file, src, static_cast<uint64_t>(src_len), static_cast<uint64_t>(return_info.GetBytes()), - return_info.GetError().AsCString()); - } - return return_info.GetBytes(); + status = return_info.GetStatus(); + if (error_ptr) + *error_ptr = return_info.GetError(); + + IncrementFilePointer(return_info.GetBytes()); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) { + log->Printf("%" PRIxPTR + " ConnectionGenericFile::Write() handle = %" PRIxPTR + ", src = %" PRIxPTR ", src_len = %" PRIu64 ") => %" PRIu64 + ", error = %s", + this, m_file, src, static_cast<uint64_t>(src_len), + static_cast<uint64_t>(return_info.GetBytes()), + return_info.GetError().AsCString()); + } + return return_info.GetBytes(); } -std::string -ConnectionGenericFile::GetURI() -{ - return m_uri; -} +std::string ConnectionGenericFile::GetURI() { return m_uri; } -bool -ConnectionGenericFile::InterruptRead() -{ - return ::SetEvent(m_event_handles[kInterruptEvent]); +bool ConnectionGenericFile::InterruptRead() { + return ::SetEvent(m_event_handles[kInterruptEvent]); } -void -ConnectionGenericFile::IncrementFilePointer(DWORD amount) -{ - LARGE_INTEGER old_pos; - old_pos.HighPart = m_overlapped.OffsetHigh; - old_pos.LowPart = m_overlapped.Offset; - old_pos.QuadPart += amount; - m_overlapped.Offset = old_pos.LowPart; - m_overlapped.OffsetHigh = old_pos.HighPart; +void ConnectionGenericFile::IncrementFilePointer(DWORD amount) { + LARGE_INTEGER old_pos; + old_pos.HighPart = m_overlapped.OffsetHigh; + old_pos.LowPart = m_overlapped.Offset; + old_pos.QuadPart += amount; + m_overlapped.Offset = old_pos.LowPart; + m_overlapped.OffsetHigh = old_pos.HighPart; } diff --git a/lldb/source/Host/windows/EditLineWin.cpp b/lldb/source/Host/windows/EditLineWin.cpp index 55fe52d..3e21ff4 100644 --- a/lldb/source/Host/windows/EditLineWin.cpp +++ b/lldb/source/Host/windows/EditLineWin.cpp @@ -8,428 +8,345 @@ //===----------------------------------------------------------------------===// // this file is only relevant for Visual C++ -#if defined( _WIN32 ) +#if defined(_WIN32) #include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/editlinewin.h" -#include <vector> #include <assert.h> +#include <vector> // edit line EL_ADDFN function pointer type -typedef unsigned char(*el_addfn_func)(EditLine *e, int ch); -typedef const char* (*el_prompt_func)(EditLine *); +typedef unsigned char (*el_addfn_func)(EditLine *e, int ch); +typedef const char *(*el_prompt_func)(EditLine *); // edit line wrapper binding container -struct el_binding -{ - // - const char *name; - const char *help; - // function pointer to callback routine - el_addfn_func func; - // ascii key this function is bound to - const char *key; +struct el_binding { + // + const char *name; + const char *help; + // function pointer to callback routine + el_addfn_func func; + // ascii key this function is bound to + const char *key; }; // stored key bindings -static std::vector<el_binding*> _bindings; +static std::vector<el_binding *> _bindings; -//TODO: this should in fact be related to the exact edit line context we create +// TODO: this should in fact be related to the exact edit line context we create static void *clientData = NULL; // store the current prompt string // default to what we expect to receive anyway static const char *_prompt = "(lldb) "; -#if !defined( _WIP_INPUT_METHOD ) +#if !defined(_WIP_INPUT_METHOD) -static char * -el_get_s (char *buffer, int chars) -{ - return gets_s(buffer, chars); -} +static char *el_get_s(char *buffer, int chars) { return gets_s(buffer, chars); } #else -static void -con_output (char _in) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get the cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // output this char - WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written ); - // advance cursor position - info.dwCursorPosition.X++; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); +static void con_output(char _in) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get the cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // output this char + WriteConsoleOutputCharacterA(hout, &_in, 1, info.dwCursorPosition, &written); + // advance cursor position + info.dwCursorPosition.X++; + SetConsoleCursorPosition(hout, info.dwCursorPosition); } -static void -con_backspace (void) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // nudge cursor backwards - info.dwCursorPosition.X--; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); - // blank out the last character - WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written ); +static void con_backspace(void) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // nudge cursor backwards + info.dwCursorPosition.X--; + SetConsoleCursorPosition(hout, info.dwCursorPosition); + // blank out the last character + WriteConsoleOutputCharacterA(hout, " ", 1, info.dwCursorPosition, &written); } -static void -con_return (void) -{ - HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE ); - DWORD written = 0; - // get cursor position - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo( hout, &info ); - // move onto the new line - info.dwCursorPosition.X = 0; - info.dwCursorPosition.Y++; - SetConsoleCursorPosition( hout, info.dwCursorPosition ); +static void con_return(void) { + HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written = 0; + // get cursor position + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(hout, &info); + // move onto the new line + info.dwCursorPosition.X = 0; + info.dwCursorPosition.Y++; + SetConsoleCursorPosition(hout, info.dwCursorPosition); } -static bool -runBind (char _key) -{ - for ( int i=0; i<_bindings.size(); i++ ) - { - el_binding *bind = _bindings[i]; - if ( bind->key[0] == _key ) - { - bind->func( (EditLine*) -1, _key ); - return true; - } +static bool runBind(char _key) { + for (int i = 0; i < _bindings.size(); i++) { + el_binding *bind = _bindings[i]; + if (bind->key[0] == _key) { + bind->func((EditLine *)-1, _key); + return true; } - return false; + } + return false; } // replacement get_s which is EL_BIND aware -static char * -el_get_s (char *buffer, int chars) -{ +static char *el_get_s(char *buffer, int chars) { + // + char *head = buffer; + // + for (;; Sleep(10)) { // - char *head = buffer; + INPUT_RECORD _record; // - for ( ;; Sleep( 10 ) ) - { - // - INPUT_RECORD _record; - // - DWORD _read = 0; - if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE ) - break; - // if we didn't read a key - if ( _read == 0 ) - continue; - // only interested in key events - if ( _record.EventType != KEY_EVENT ) - continue; - // is the key down - if (! _record.Event.KeyEvent.bKeyDown ) - continue; - // read the ascii key character - char _key = _record.Event.KeyEvent.uChar.AsciiChar; - // non ascii conformant key press - if ( _key == 0 ) - { - // check the scan code - // if VK_UP scroll back through history - // if VK_DOWN scroll forward through history - continue; - } - // try to execute any bind this key may have - if ( runBind( _key ) ) - continue; - // if we read a return key - if ( _key == '\n' || _key == '\r' ) - { - con_return( ); - break; - } - // key is backspace - if ( _key == 0x8 ) - { - // avoid deleting past beginning - if ( head > buffer ) - { - con_backspace( ); - head--; - } - continue; - } - - // add this key to the input buffer - if ( (head-buffer) < (chars-1) ) - { - con_output( _key ); - *(head++) = _key; - } + DWORD _read = 0; + if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE), &_record, 1, + &_read) == FALSE) + break; + // if we didn't read a key + if (_read == 0) + continue; + // only interested in key events + if (_record.EventType != KEY_EVENT) + continue; + // is the key down + if (!_record.Event.KeyEvent.bKeyDown) + continue; + // read the ascii key character + char _key = _record.Event.KeyEvent.uChar.AsciiChar; + // non ascii conformant key press + if (_key == 0) { + // check the scan code + // if VK_UP scroll back through history + // if VK_DOWN scroll forward through history + continue; + } + // try to execute any bind this key may have + if (runBind(_key)) + continue; + // if we read a return key + if (_key == '\n' || _key == '\r') { + con_return(); + break; + } + // key is backspace + if (_key == 0x8) { + // avoid deleting past beginning + if (head > buffer) { + con_backspace(); + head--; + } + continue; } - // insert end of line character - *head = '\0'; - return buffer; + // add this key to the input buffer + if ((head - buffer) < (chars - 1)) { + con_output(_key); + *(head++) = _key; + } + } + // insert end of line character + *head = '\0'; + + return buffer; } #endif // edit line initialize -EditLine * -el_init (const char *, FILE *, FILE *, FILE *) -{ - // - SetConsoleTitleA( "lldb" ); - // return dummy handle - return (EditLine*) -1; +EditLine *el_init(const char *, FILE *, FILE *, FILE *) { + // + SetConsoleTitleA("lldb"); + // return dummy handle + return (EditLine *)-1; } -const char * -el_gets (EditLine *el, int *length) -{ - // print the prompt if we have one - if ( _prompt != NULL ) - printf("%s", _prompt); - // create a buffer for the user input - char *buffer = new char[ MAX_PATH ]; - // try to get user input string - if ( el_get_s( buffer, MAX_PATH ) ) - { - // get the string length in 'length' - while ( buffer[ *length ] != '\0' ) - (*length)++; - // return the input buffer - // remember that this memory has the be free'd somewhere - return buffer; - } - else - { - // on error - delete [] buffer; - return NULL; - } +const char *el_gets(EditLine *el, int *length) { + // print the prompt if we have one + if (_prompt != NULL) + printf("%s", _prompt); + // create a buffer for the user input + char *buffer = new char[MAX_PATH]; + // try to get user input string + if (el_get_s(buffer, MAX_PATH)) { + // get the string length in 'length' + while (buffer[*length] != '\0') + (*length)++; + // return the input buffer + // remember that this memory has the be free'd somewhere + return buffer; + } else { + // on error + delete[] buffer; + return NULL; + } } -int -el_set (EditLine *el, int code, ...) -{ - va_list vl; - va_start(vl, code); - // - switch ( code ) - { - // edit line set prompt message - case ( EL_PROMPT ): - { - // EL_PROMPT, char *(*f)( EditLine *) - // define a prompt printing function as 'f', which is to return a string that - // contains the prompt. - - // get the function pointer from the arg list - void *func_vp = (void*)va_arg(vl, el_prompt_func); - // cast to suitable prototype - el_prompt_func func_fp = (el_prompt_func)func_vp; - // call to get the prompt as a string - _prompt = func_fp( el ); - } - break; - - case (EL_PROMPT_ESC) : - { - // EL_PROMPT, char *(*f)( EditLine *) - // define a prompt printing function as 'f', which is to return a string that - // contains the prompt. - - // get the function pointer from the arg list - void *func_vp = (void*)va_arg(vl, el_prompt_func); - va_arg(vl, int); - // call to get the prompt as a string - el_prompt_func func_fp = (el_prompt_func)func_vp; - _prompt = func_fp(el); - } - break; - - case ( EL_EDITOR ): - { - // EL_EDITOR, const char *mode - // set editing mode to "emacs" or "vi" - } - break; - case ( EL_HIST ): - { - // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr - // defines which history function to use, which is usually history(). Ptr should be the - // value returned by history_init(). - } - break; - case ( EL_ADDFN ): - { - // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch) - // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is - // entered. 'help' is a description of 'name'. at invocation time, 'ch' is the key which caused the invocation. the - // return value of 'func()' should be one of: - // CC_NORM add a normal character - // CC_NEWLINE end of line was entered - // CC_EOF EOF was entered - // CC_ARGHACK expecting further command input as arguments, do nothing visually. - // CC_REFRESH refresh display. - // CC_REFRESH_BEEP refresh display and beep. - // CC_CURSOR cursor moved so update and perform CC_REFRESH - // CC_REDISPLAY redisplay entire input line. this is useful if a key binding outputs extra information. - // CC_ERROR an error occurred. beep and flush tty. - // CC_FATAL fatal error, reset tty to known state. - - el_binding *binding = new el_binding; - binding->name = va_arg( vl, const char *); - binding->help = va_arg( vl, const char *); - binding->func = va_arg( vl, el_addfn_func ); - binding->key = 0; - // add this to the bindings list - _bindings.push_back( binding ); - } - break; - case ( EL_BIND ): - { - // EL_BIND, const char *, ..., NULL - // perform the BIND built-in command. Refer to editrc(5) for more information. - - const char *name = va_arg( vl, const char* ); - - for ( int i=0; i<_bindings.size(); i++ ) - { - el_binding *bind = _bindings[i]; - if ( strcmp( bind->name, name ) == 0 ) - { - bind->key = va_arg( vl, const char * ); - break; - } - } - - } - break; - case ( EL_CLIENTDATA ): - { - clientData = va_arg(vl, void*); - } +int el_set(EditLine *el, int code, ...) { + va_list vl; + va_start(vl, code); + // + switch (code) { + // edit line set prompt message + case (EL_PROMPT): { + // EL_PROMPT, char *(*f)( EditLine *) + // define a prompt printing function as 'f', which is to return a + // string that + // contains the prompt. + + // get the function pointer from the arg list + void *func_vp = (void *)va_arg(vl, el_prompt_func); + // cast to suitable prototype + el_prompt_func func_fp = (el_prompt_func)func_vp; + // call to get the prompt as a string + _prompt = func_fp(el); + } break; + + case (EL_PROMPT_ESC): { + // EL_PROMPT, char *(*f)( EditLine *) + // define a prompt printing function as 'f', which is to return a + // string that + // contains the prompt. + + // get the function pointer from the arg list + void *func_vp = (void *)va_arg(vl, el_prompt_func); + va_arg(vl, int); + // call to get the prompt as a string + el_prompt_func func_fp = (el_prompt_func)func_vp; + _prompt = func_fp(el); + } break; + + case (EL_EDITOR): { + // EL_EDITOR, const char *mode + // set editing mode to "emacs" or "vi" + } break; + case (EL_HIST): { + // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr + // defines which history function to use, which is usually history(). + // Ptr should be the + // value returned by history_init(). + } break; + case (EL_ADDFN): { + // EL_ADDFN, const char *name, const char *help, unsigned char + // (*func)(EditLine *e, int ch) + // add a user defined function, func), referred to as 'name' which is + // invoked when a key which is bound to 'name' is + // entered. 'help' is a description of 'name'. at invocation time, 'ch' + // is the key which caused the invocation. the + // return value of 'func()' should be one of: + // CC_NORM add a normal character + // CC_NEWLINE end of line was entered + // CC_EOF EOF was entered + // CC_ARGHACK expecting further command input as arguments, do + // nothing visually. + // CC_REFRESH refresh display. + // CC_REFRESH_BEEP refresh display and beep. + // CC_CURSOR cursor moved so update and perform CC_REFRESH + // CC_REDISPLAY redisplay entire input line. this is useful + // if a key binding outputs extra information. + // CC_ERROR an error occurred. beep and flush tty. + // CC_FATAL fatal error, reset tty to known state. + + el_binding *binding = new el_binding; + binding->name = va_arg(vl, const char *); + binding->help = va_arg(vl, const char *); + binding->func = va_arg(vl, el_addfn_func); + binding->key = 0; + // add this to the bindings list + _bindings.push_back(binding); + } break; + case (EL_BIND): { + // EL_BIND, const char *, ..., NULL + // perform the BIND built-in command. Refer to editrc(5) for more + // information. + + const char *name = va_arg(vl, const char *); + + for (int i = 0; i < _bindings.size(); i++) { + el_binding *bind = _bindings[i]; + if (strcmp(bind->name, name) == 0) { + bind->key = va_arg(vl, const char *); break; + } } - return 0; -} -void -el_end (EditLine *el) -{ - //assert( !"Not implemented!" ); + } break; + case (EL_CLIENTDATA): { + clientData = va_arg(vl, void *); + } break; + } + return 0; } -void -el_reset (EditLine *) -{ - assert( !"Not implemented!" ); +void el_end(EditLine *el) { + // assert( !"Not implemented!" ); } -int -el_getc (EditLine *, char *) -{ - assert( !"Not implemented!" ); - return 0; -} +void el_reset(EditLine *) { assert(!"Not implemented!"); } -void -el_push (EditLine *, const char *) -{ +int el_getc(EditLine *, char *) { + assert(!"Not implemented!"); + return 0; } -void -el_beep (EditLine *) -{ - Beep( 1000, 500 ); -} +void el_push(EditLine *, const char *) {} -int -el_parse (EditLine *, int, const char **) -{ - assert( !"Not implemented!" ); - return 0; -} +void el_beep(EditLine *) { Beep(1000, 500); } -int -el_get (EditLine *el, int code, ...) -{ - va_list vl; - va_start( vl, code ); - - switch ( code ) - { - case ( EL_CLIENTDATA ): - { - void **dout = va_arg( vl, void** ); - *dout = clientData; - } - break; - default: - assert( !"Not implemented!" ); - } - return 0; +int el_parse(EditLine *, int, const char **) { + assert(!"Not implemented!"); + return 0; } -int -el_source (EditLine *el, const char *file) -{ - // init edit line by reading the contents of 'file' - // nothing to do here on windows... - return 0; +int el_get(EditLine *el, int code, ...) { + va_list vl; + va_start(vl, code); + + switch (code) { + case (EL_CLIENTDATA): { + void **dout = va_arg(vl, void **); + *dout = clientData; + } break; + default: + assert(!"Not implemented!"); + } + return 0; } -void -el_resize (EditLine *) -{ - assert( !"Not implemented!" ); +int el_source(EditLine *el, const char *file) { + // init edit line by reading the contents of 'file' + // nothing to do here on windows... + return 0; } -const LineInfo * -el_line (EditLine *el) -{ - return 0; -} +void el_resize(EditLine *) { assert(!"Not implemented!"); } -int -el_insertstr (EditLine *, const char *) -{ -// assert( !"Not implemented!" ); - return 0; -} +const LineInfo *el_line(EditLine *el) { return 0; } -void -el_deletestr (EditLine *, int) -{ - assert( !"Not implemented!" ); +int el_insertstr(EditLine *, const char *) { + // assert( !"Not implemented!" ); + return 0; } -History * -history_init (void) -{ - // return dummy handle - return (History*) -1; +void el_deletestr(EditLine *, int) { assert(!"Not implemented!"); } + +History *history_init(void) { + // return dummy handle + return (History *)-1; } -void -history_end (History *) -{ -// assert( !"Not implemented!" ); +void history_end(History *) { + // assert( !"Not implemented!" ); } -int -history (History *, HistEvent *, int op, ...) -{ - // perform operation 'op' on the history list with - // optional arguments as needed by the operation. - return 0; +int history(History *, HistEvent *, int op, ...) { + // perform operation 'op' on the history list with + // optional arguments as needed by the operation. + return 0; } #endif diff --git a/lldb/source/Host/windows/FileSystem.cpp b/lldb/source/Host/windows/FileSystem.cpp index a3e0e4f..36e567f 100644 --- a/lldb/source/Host/windows/FileSystem.cpp +++ b/lldb/source/Host/windows/FileSystem.cpp @@ -21,273 +21,241 @@ using namespace lldb_private; -const char * -FileSystem::DEV_NULL = "nul"; +const char *FileSystem::DEV_NULL = "nul"; -const char *FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding"; +const char *FileSystem::PATH_CONVERSION_ERROR = + "Error converting path between UTF-8 and native encoding"; -FileSpec::PathSyntax -FileSystem::GetNativePathSyntax() -{ - return FileSpec::ePathSyntaxWindows; +FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { + return FileSpec::ePathSyntaxWindows; } -Error -FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) -{ - // On Win32, the mode parameter is ignored, as Windows files and directories support a - // different permission model than POSIX. - Error error; - const auto err_code = llvm::sys::fs::create_directories(file_spec.GetPath(), true); - if (err_code) - { - error.SetErrorString(err_code.message().c_str()); - } - - return error; +Error FileSystem::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { + // On Win32, the mode parameter is ignored, as Windows files and directories + // support a + // different permission model than POSIX. + Error error; + const auto err_code = + llvm::sys::fs::create_directories(file_spec.GetPath(), true); + if (err_code) { + error.SetErrorString(err_code.message().c_str()); + } + + return error; } -Error -FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) -{ - Error error; - std::wstring path_buffer; - if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - if (!recurse) - { - BOOL result = ::RemoveDirectoryW(path_buffer.c_str()); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - } - else - { - // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to - // indicate the end of the list. The first null terminator is there only in the backing - // store but not the actual vector contents, and so we need to push twice. - path_buffer.push_back(0); - path_buffer.push_back(0); - - SHFILEOPSTRUCTW shfos = {0}; - shfos.wFunc = FO_DELETE; - shfos.pFrom = (LPCWSTR)path_buffer.data(); - shfos.fFlags = FOF_NO_UI; - - int result = ::SHFileOperationW(&shfos); - // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values. - if (result != 0) - error.SetErrorStringWithFormat("SHFileOperation failed"); - } +Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { + Error error; + std::wstring path_buffer; + if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) { + error.SetErrorString(PATH_CONVERSION_ERROR); return error; + } + if (!recurse) { + BOOL result = ::RemoveDirectoryW(path_buffer.c_str()); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + } else { + // SHFileOperation() accepts a list of paths, and so must be + // double-null-terminated to + // indicate the end of the list. The first null terminator is there only in + // the backing + // store but not the actual vector contents, and so we need to push twice. + path_buffer.push_back(0); + path_buffer.push_back(0); + + SHFILEOPSTRUCTW shfos = {0}; + shfos.wFunc = FO_DELETE; + shfos.pFrom = (LPCWSTR)path_buffer.data(); + shfos.fFlags = FOF_NO_UI; + + int result = ::SHFileOperationW(&shfos); + // TODO(zturner): Correctly handle the intricacies of SHFileOperation return + // values. + if (result != 0) + error.SetErrorStringWithFormat("SHFileOperation failed"); + } + return error; } -Error -FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) -{ - Error error; - // Beware that Windows's permission model is different from Unix's, and it's - // not clear if this API is supposed to check ACLs. To match the caller's - // expectations as closely as possible, we'll use Microsoft's _stat, which - // attempts to emulate POSIX stat. This should be good enough for basic - // checks like FileSpec::Readable. - struct _stat file_stats; - if (::_stat(file_spec.GetCString(), &file_stats) == 0) - { - // The owner permission bits in "st_mode" currently match the definitions - // for the owner file mode bits. - file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC); - } - else - { - error.SetErrorToErrno(); - } - - return error; +Error FileSystem::GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions) { + Error error; + // Beware that Windows's permission model is different from Unix's, and it's + // not clear if this API is supposed to check ACLs. To match the caller's + // expectations as closely as possible, we'll use Microsoft's _stat, which + // attempts to emulate POSIX stat. This should be good enough for basic + // checks like FileSpec::Readable. + struct _stat file_stats; + if (::_stat(file_spec.GetCString(), &file_stats) == 0) { + // The owner permission bits in "st_mode" currently match the definitions + // for the owner file mode bits. + file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC); + } else { + error.SetErrorToErrno(); + } + + return error; } -Error -FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) -{ - Error error; - error.SetErrorStringWithFormat("%s is not supported on this host", LLVM_PRETTY_FUNCTION); - return error; +Error FileSystem::SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions) { + Error error; + error.SetErrorStringWithFormat("%s is not supported on this host", + LLVM_PRETTY_FUNCTION); + return error; } -lldb::user_id_t -FileSystem::GetFileSize(const FileSpec &file_spec) -{ - return file_spec.GetByteSize(); +lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { + return file_spec.GetByteSize(); } -bool -FileSystem::GetFileExists(const FileSpec &file_spec) -{ - return file_spec.Exists(); +bool FileSystem::GetFileExists(const FileSpec &file_spec) { + return file_spec.Exists(); } -Error -FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - std::wstring wsrc, wdst; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) - error.SetErrorString(PATH_CONVERSION_ERROR); - else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr)) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; +Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { + Error error; + std::wstring wsrc, wdst; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || + !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) + error.SetErrorString(PATH_CONVERSION_ERROR); + else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr)) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -int -FileSystem::GetHardlinkCount(const FileSpec &file_spec) -{ - std::wstring path; - if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) - return -1; +int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { + std::wstring path; + if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) + return -1; - HANDLE file_handle = ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, nullptr); + HANDLE file_handle = + ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file_handle == INVALID_HANDLE_VALUE) - return -1; + if (file_handle == INVALID_HANDLE_VALUE) + return -1; - AutoHandle auto_file_handle(file_handle); - BY_HANDLE_FILE_INFORMATION file_info; - if (::GetFileInformationByHandle(file_handle, &file_info)) - return file_info.nNumberOfLinks; + AutoHandle auto_file_handle(file_handle); + BY_HANDLE_FILE_INFORMATION file_info; + if (::GetFileInformationByHandle(file_handle, &file_info)) + return file_info.nNumberOfLinks; - return -1; + return -1; } -Error -FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - std::wstring wsrc, wdst; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) - error.SetErrorString(PATH_CONVERSION_ERROR); - if (error.Fail()) - return error; - DWORD attrib = ::GetFileAttributesW(wdst.c_str()); - if (attrib == INVALID_FILE_ATTRIBUTES) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); - DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; - BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); +Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { + Error error; + std::wstring wsrc, wdst; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || + !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) + error.SetErrorString(PATH_CONVERSION_ERROR); + if (error.Fail()) + return error; + DWORD attrib = ::GetFileAttributesW(wdst.c_str()); + if (attrib == INVALID_FILE_ATTRIBUTES) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; + } + bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); + DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; + BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -Error -FileSystem::Unlink(const FileSpec &file_spec) -{ - Error error; - std::wstring path; - if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - BOOL result = ::DeleteFileW(path.c_str()); - if (!result) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); +Error FileSystem::Unlink(const FileSpec &file_spec) { + Error error; + std::wstring path; + if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) { + error.SetErrorString(PATH_CONVERSION_ERROR); return error; + } + BOOL result = ::DeleteFileW(path.c_str()); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; } -Error -FileSystem::Readlink(const FileSpec &src, FileSpec &dst) -{ - Error error; - std::wstring wsrc; - if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) - { - error.SetErrorString(PATH_CONVERSION_ERROR); - return error; - } - - HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (h == INVALID_HANDLE_VALUE) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - - std::vector<wchar_t> buf(PATH_MAX + 1); - // Subtract 1 from the path length since this function does not add a null terminator. - DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); - std::string path; - if (result == 0) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - else if (!llvm::convertWideToUTF8(buf.data(), path)) - error.SetErrorString(PATH_CONVERSION_ERROR); - else - dst.SetFile(path, false); - - ::CloseHandle(h); +Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { + Error error; + std::wstring wsrc; + if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) { + error.SetErrorString(PATH_CONVERSION_ERROR); + return error; + } + + HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (h == INVALID_HANDLE_VALUE) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; + } + + std::vector<wchar_t> buf(PATH_MAX + 1); + // Subtract 1 from the path length since this function does not add a null + // terminator. + DWORD result = ::GetFinalPathNameByHandleW( + h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + std::string path; + if (result == 0) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + else if (!llvm::convertWideToUTF8(buf.data(), path)) + error.SetErrorString(PATH_CONVERSION_ERROR); + else + dst.SetFile(path, false); + + ::CloseHandle(h); + return error; } -Error -FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) -{ - return Error("ResolveSymbolicLink() isn't implemented on Windows"); +Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { + return Error("ResolveSymbolicLink() isn't implemented on Windows"); } -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - if (spec) - { - // TODO: return true if the file is on a locally mounted file system - return true; - } +bool FileSystem::IsLocal(const FileSpec &spec) { + if (spec) { + // TODO: return true if the file is on a locally mounted file system + return true; + } - return false; + return false; } -FILE * -FileSystem::Fopen(const char *path, const char *mode) -{ - std::wstring wpath, wmode; - if (!llvm::ConvertUTF8toWide(path, wpath)) - return nullptr; - if (!llvm::ConvertUTF8toWide(mode, wmode)) - return nullptr; - FILE *file; - if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) - return nullptr; - return file; +FILE *FileSystem::Fopen(const char *path, const char *mode) { + std::wstring wpath, wmode; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return nullptr; + if (!llvm::ConvertUTF8toWide(mode, wmode)) + return nullptr; + FILE *file; + if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) + return nullptr; + return file; } -int -FileSystem::Stat(const char *path, struct stat *stats) -{ - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) - { - errno = EINVAL; - return -EINVAL; - } - int stat_result; +int FileSystem::Stat(const char *path, struct stat *stats) { + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) { + errno = EINVAL; + return -EINVAL; + } + int stat_result; #ifdef _USE_32BIT_TIME_T - struct _stat32 file_stats; - stat_result = ::_wstat32(wpath.c_str(), &file_stats); + struct _stat32 file_stats; + stat_result = ::_wstat32(wpath.c_str(), &file_stats); #else - struct _stat64i32 file_stats; - stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); + struct _stat64i32 file_stats; + stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); #endif - if (stat_result == 0) - { - static_assert(sizeof(struct stat) == sizeof(file_stats), - "stat and _stat32/_stat64i32 must have the same layout"); - *stats = *reinterpret_cast<struct stat *>(&file_stats); - } - return stat_result; + if (stat_result == 0) { + static_assert(sizeof(struct stat) == sizeof(file_stats), + "stat and _stat32/_stat64i32 must have the same layout"); + *stats = *reinterpret_cast<struct stat *>(&file_stats); + } + return stat_result; } diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp index 1b4eeb8..9fbea89 100644 --- a/lldb/source/Host/windows/Host.cpp +++ b/lldb/source/Host/windows/Host.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// // C Includes -#include <stdio.h> -#include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/AutoHandle.h" +#include "lldb/Host/windows/windows.h" +#include <stdio.h> // C++ Includes // Other libraries and framework includes @@ -19,12 +19,12 @@ #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "llvm/Support/ConvertUTF.h" @@ -34,305 +34,270 @@ using namespace lldb; using namespace lldb_private; -namespace -{ - bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) - { - // Open the PE File as a binary file, and parse just enough information to determine the - // machine type. - File imageBinary( - executable.GetPath().c_str(), - File::eOpenOptionRead, - lldb::eFilePermissionsUserRead); - imageBinary.SeekFromStart(0x3c); - int32_t peOffset = 0; - uint32_t peHead = 0; - uint16_t machineType = 0; - size_t readSize = sizeof(peOffset); - imageBinary.Read(&peOffset, readSize); - imageBinary.SeekFromStart(peOffset); - imageBinary.Read(&peHead, readSize); - if (peHead != 0x00004550) // "PE\0\0", little-endian - return false; // Error: Can't find PE header - readSize = 2; - imageBinary.Read(&machineType, readSize); - triple.setVendor(llvm::Triple::PC); - triple.setOS(llvm::Triple::Win32); - triple.setArch(llvm::Triple::UnknownArch); - if (machineType == 0x8664) - triple.setArch(llvm::Triple::x86_64); - else if (machineType == 0x14c) - triple.setArch(llvm::Triple::x86); - - return true; - } +namespace { +bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) { + // Open the PE File as a binary file, and parse just enough information to + // determine the + // machine type. + File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead, + lldb::eFilePermissionsUserRead); + imageBinary.SeekFromStart(0x3c); + int32_t peOffset = 0; + uint32_t peHead = 0; + uint16_t machineType = 0; + size_t readSize = sizeof(peOffset); + imageBinary.Read(&peOffset, readSize); + imageBinary.SeekFromStart(peOffset); + imageBinary.Read(&peHead, readSize); + if (peHead != 0x00004550) // "PE\0\0", little-endian + return false; // Error: Can't find PE header + readSize = 2; + imageBinary.Read(&machineType, readSize); + triple.setVendor(llvm::Triple::PC); + triple.setOS(llvm::Triple::Win32); + triple.setArch(llvm::Triple::UnknownArch); + if (machineType == 0x8664) + triple.setArch(llvm::Triple::x86_64); + else if (machineType == 0x14c) + triple.setArch(llvm::Triple::x86); + + return true; +} - bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) - { - // Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB. - std::vector<wchar_t> buffer(PATH_MAX); - DWORD dwSize = buffer.size(); - if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize)) - return false; - return llvm::convertWideToUTF8(buffer.data(), path); - } +bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) { + // Get the process image path. MAX_PATH isn't long enough, paths can actually + // be up to 32KB. + std::vector<wchar_t> buffer(PATH_MAX); + DWORD dwSize = buffer.size(); + if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize)) + return false; + return llvm::convertWideToUTF8(buffer.data(), path); +} - void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process) - { - // We may not have permissions to read the path from the process. So start off by - // setting the executable file to whatever Toolhelp32 gives us, and then try to - // enhance this with more detailed information, but fail gracefully. - std::string executable; - llvm::Triple triple; - triple.setVendor(llvm::Triple::PC); - triple.setOS(llvm::Triple::Win32); - triple.setArch(llvm::Triple::UnknownArch); - if (GetExecutableForProcess(handle, executable)) - { - FileSpec executableFile(executable.c_str(), false); - process.SetExecutableFile(executableFile, true); - GetTripleForProcess(executableFile, triple); - } - process.SetArchitecture(ArchSpec(triple)); - - // TODO(zturner): Add the ability to get the process user name. - } +void GetProcessExecutableAndTriple(const AutoHandle &handle, + ProcessInstanceInfo &process) { + // We may not have permissions to read the path from the process. So start + // off by + // setting the executable file to whatever Toolhelp32 gives us, and then try + // to + // enhance this with more detailed information, but fail gracefully. + std::string executable; + llvm::Triple triple; + triple.setVendor(llvm::Triple::PC); + triple.setOS(llvm::Triple::Win32); + triple.setArch(llvm::Triple::UnknownArch); + if (GetExecutableForProcess(handle, executable)) { + FileSpec executableFile(executable.c_str(), false); + process.SetExecutableFile(executableFile, true); + GetTripleForProcess(executableFile, triple); + } + process.SetArchitecture(ArchSpec(triple)); + + // TODO(zturner): Add the ability to get the process user name. +} } -lldb::DataBufferSP -Host::GetAuxvData(lldb_private::Process *process) -{ - return 0; +lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { + return 0; } -lldb::tid_t -Host::GetCurrentThreadID() -{ - return lldb::tid_t(::GetCurrentThreadId()); +lldb::tid_t Host::GetCurrentThreadID() { + return lldb::tid_t(::GetCurrentThreadId()); } -lldb::thread_t -Host::GetCurrentThread () -{ - return lldb::thread_t(::GetCurrentThread()); +lldb::thread_t Host::GetCurrentThread() { + return lldb::thread_t(::GetCurrentThread()); } lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) -{ - return TlsAlloc(); +Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { + return TlsAlloc(); } -void* -Host::ThreadLocalStorageGet(lldb::thread_key_t key) -{ - return ::TlsGetValue (key); +void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { + return ::TlsGetValue(key); } -void -Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) -{ - ::TlsSetValue (key, value); +void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { + ::TlsSetValue(key, value); } -void -Host::Kill(lldb::pid_t pid, int signo) -{ - TerminateProcess((HANDLE) pid, 1); +void Host::Kill(lldb::pid_t pid, int signo) { + TerminateProcess((HANDLE)pid, 1); } +const char *Host::GetSignalAsCString(int signo) { return NULL; } + +FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { + FileSpec module_filespec; + + HMODULE hmodule = NULL; + if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)host_addr, &hmodule)) + return module_filespec; -const char * -Host::GetSignalAsCString(int signo) -{ - return NULL; + std::vector<wchar_t> buffer(PATH_MAX); + DWORD chars_copied = 0; + do { + chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size()); + if (chars_copied == buffer.size() && + ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + buffer.resize(buffer.size() * 2); + } while (chars_copied >= buffer.size()); + std::string path; + if (!llvm::convertWideToUTF8(buffer.data(), path)) + return module_filespec; + module_filespec.SetFile(path, false); + return module_filespec; } -FileSpec -Host::GetModuleFileSpecForHostAddress (const void *host_addr) -{ - FileSpec module_filespec; +uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + process_infos.Clear(); - HMODULE hmodule = NULL; - if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule)) - return module_filespec; + AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (!snapshot.IsValid()) + return 0; - std::vector<wchar_t> buffer(PATH_MAX); - DWORD chars_copied = 0; + PROCESSENTRY32W pe = {0}; + pe.dwSize = sizeof(PROCESSENTRY32W); + if (Process32FirstW(snapshot.get(), &pe)) { do { - chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size()); - if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) - buffer.resize(buffer.size() * 2); - } while (chars_copied >= buffer.size()); - std::string path; - if (!llvm::convertWideToUTF8(buffer.data(), path)) - return module_filespec; - module_filespec.SetFile(path, false); - return module_filespec; + AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, + pe.th32ProcessID), + nullptr); + + ProcessInstanceInfo process; + std::string exeFile; + llvm::convertWideToUTF8(pe.szExeFile, exeFile); + process.SetExecutableFile(FileSpec(exeFile, false), true); + process.SetProcessID(pe.th32ProcessID); + process.SetParentProcessID(pe.th32ParentProcessID); + GetProcessExecutableAndTriple(handle, process); + + if (match_info.MatchAllProcesses() || match_info.Matches(process)) + process_infos.Append(process); + } while (Process32NextW(snapshot.get(), &pe)); + } + return process_infos.GetSize(); } -uint32_t -Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) -{ - process_infos.Clear(); - - AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); - if (!snapshot.IsValid()) - return 0; - - PROCESSENTRY32W pe = {0}; - pe.dwSize = sizeof(PROCESSENTRY32W); - if (Process32FirstW(snapshot.get(), &pe)) - { - do - { - AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr); - - ProcessInstanceInfo process; - std::string exeFile; - llvm::convertWideToUTF8(pe.szExeFile, exeFile); - process.SetExecutableFile(FileSpec(exeFile, false), true); - process.SetProcessID(pe.th32ProcessID); - process.SetParentProcessID(pe.th32ParentProcessID); - GetProcessExecutableAndTriple(handle, process); - - if (match_info.MatchAllProcesses() || match_info.Matches(process)) - process_infos.Append(process); - } while (Process32NextW(snapshot.get(), &pe)); - } - return process_infos.GetSize(); -} +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.Clear(); -bool -Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.Clear(); - - AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), - nullptr); - if (!handle.IsValid()) - return false; - - process_info.SetProcessID(pid); - GetProcessExecutableAndTriple(handle, process_info); - - // Need to read the PEB to get parent process and command line arguments. - return true; + AutoHandle handle( + ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), + nullptr); + if (!handle.IsValid()) + return false; + + process_info.SetProcessID(pid); + GetProcessExecutableAndTriple(handle, process_info); + + // Need to read the PEB to get parent process and command line arguments. + return true; } -HostThread -Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, - bool monitor_signals) -{ - return HostThread(); +HostThread Host::StartMonitoringChildProcess( + const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, + bool monitor_signals) { + return HostThread(); } -Error -Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) -{ - Error error; - if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) - { - FileSpec expand_tool_spec; - if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec)) - { - error.SetErrorString("could not find support executable directory for the lldb-argdumper tool"); - return error; - } - expand_tool_spec.AppendPathComponent("lldb-argdumper.exe"); - if (!expand_tool_spec.Exists()) - { - error.SetErrorString("could not find the lldb-argdumper tool"); - return error; - } - - std::string quoted_cmd_string; - launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string); - std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/'); - StreamString expand_command; - - expand_command.Printf("\"%s\" %s", - expand_tool_spec.GetPath().c_str(), - quoted_cmd_string.c_str()); - - int status; - std::string output; - RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), &status, nullptr, &output, 10); - - if (status != 0) - { - error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", status); - return error; - } - - auto data_sp = StructuredData::ParseJSON(output); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto dict_sp = data_sp->GetAsDictionary(); - if (!data_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); - if (!args_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - auto args_array_sp = args_sp->GetAsArray(); - if (!args_array_sp) - { - error.SetErrorString("invalid JSON"); - return error; - } - - launch_info.GetArguments().Clear(); - - for (size_t i = 0; - i < args_array_sp->GetSize(); - i++) - { - auto item_sp = args_array_sp->GetItemAtIndex(i); - if (!item_sp) - continue; - auto str_sp = item_sp->GetAsString(); - if (!str_sp) - continue; - - launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); - } +Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + Error error; + if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { + FileSpec expand_tool_spec; + if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, + expand_tool_spec)) { + error.SetErrorString("could not find support executable directory for " + "the lldb-argdumper tool"); + return error; + } + expand_tool_spec.AppendPathComponent("lldb-argdumper.exe"); + if (!expand_tool_spec.Exists()) { + error.SetErrorString("could not find the lldb-argdumper tool"); + return error; + } + + std::string quoted_cmd_string; + launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string); + std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/'); + StreamString expand_command; + + expand_command.Printf("\"%s\" %s", expand_tool_spec.GetPath().c_str(), + quoted_cmd_string.c_str()); + + int status; + std::string output; + RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), + &status, nullptr, &output, 10); + + if (status != 0) { + error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", + status); + return error; + } + + auto data_sp = StructuredData::ParseJSON(output); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + auto dict_sp = data_sp->GetAsDictionary(); + if (!data_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); + if (!args_sp) { + error.SetErrorString("invalid JSON"); + return error; } - - return error; + + auto args_array_sp = args_sp->GetAsArray(); + if (!args_array_sp) { + error.SetErrorString("invalid JSON"); + return error; + } + + launch_info.GetArguments().Clear(); + + for (size_t i = 0; i < args_array_sp->GetSize(); i++) { + auto item_sp = args_array_sp->GetItemAtIndex(i); + if (!item_sp) + continue; + auto str_sp = item_sp->GetAsString(); + if (!str_sp) + continue; + + launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str()); + } + } + + return error; } -size_t -Host::GetEnvironment(StringList &env) -{ - // The environment block on Windows is a contiguous buffer of NULL terminated strings, - // where the end of the environment block is indicated by two consecutive NULLs. - LPWCH environment_block = ::GetEnvironmentStringsW(); - env.Clear(); - while (*environment_block != L'\0') - { - std::string current_var; - auto current_var_size = wcslen(environment_block) + 1; - if (!llvm::convertWideToUTF8(environment_block, current_var)) - { - environment_block += current_var_size; - continue; - } - if (current_var[0] != '=') - env.AppendString(current_var); - - environment_block += current_var_size; +size_t Host::GetEnvironment(StringList &env) { + // The environment block on Windows is a contiguous buffer of NULL terminated + // strings, + // where the end of the environment block is indicated by two consecutive + // NULLs. + LPWCH environment_block = ::GetEnvironmentStringsW(); + env.Clear(); + while (*environment_block != L'\0') { + std::string current_var; + auto current_var_size = wcslen(environment_block) + 1; + if (!llvm::convertWideToUTF8(environment_block, current_var)) { + environment_block += current_var_size; + continue; } - return env.GetSize(); + if (current_var[0] != '=') + env.AppendString(current_var); + + environment_block += current_var_size; + } + return env.GetSize(); } diff --git a/lldb/source/Host/windows/HostInfoWindows.cpp b/lldb/source/Host/windows/HostInfoWindows.cpp index 6b21902..a965ec0 100644 --- a/lldb/source/Host/windows/HostInfoWindows.cpp +++ b/lldb/source/Host/windows/HostInfoWindows.cpp @@ -24,127 +24,108 @@ using namespace lldb_private; FileSpec HostInfoWindows::m_program_filespec; -void -HostInfoWindows::Initialize() -{ - ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); - HostInfoBase::Initialize(); +void HostInfoWindows::Initialize() { + ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); + HostInfoBase::Initialize(); } -void -HostInfoWindows::Terminate() -{ - HostInfoBase::Terminate(); - ::CoUninitialize(); +void HostInfoWindows::Terminate() { + HostInfoBase::Terminate(); + ::CoUninitialize(); } -size_t -HostInfoWindows::GetPageSize() -{ - SYSTEM_INFO systemInfo; - GetNativeSystemInfo(&systemInfo); - return systemInfo.dwPageSize; +size_t HostInfoWindows::GetPageSize() { + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&systemInfo); + return systemInfo.dwPageSize; } -bool -HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) -{ - OSVERSIONINFOEX info; +bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + OSVERSIONINFOEX info; - ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); #pragma warning(push) #pragma warning(disable : 4996) - // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in favor of the - // new Windows Version Helper APIs. Since we don't specify a minimum SDK version, it's easier - // to simply disable the warning rather than try to support both APIs. - if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) - { - return false; - } + // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in + // favor of the + // new Windows Version Helper APIs. Since we don't specify a minimum SDK + // version, it's easier + // to simply disable the warning rather than try to support both APIs. + if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) { + return false; + } #pragma warning(pop) - major = info.dwMajorVersion; - minor = info.dwMinorVersion; - update = info.wServicePackMajor; + major = info.dwMajorVersion; + minor = info.dwMinorVersion; + update = info.wServicePackMajor; - return true; + return true; } -bool -HostInfoWindows::GetOSBuildString(std::string &s) -{ - s.clear(); - uint32_t major, minor, update; - if (!GetOSVersion(major, minor, update)) - return false; - - llvm::raw_string_ostream stream(s); - stream << "Windows NT " << major << "." << minor << "." << update; - return true; +bool HostInfoWindows::GetOSBuildString(std::string &s) { + s.clear(); + uint32_t major, minor, update; + if (!GetOSVersion(major, minor, update)) + return false; + + llvm::raw_string_ostream stream(s); + stream << "Windows NT " << major << "." << minor << "." << update; + return true; } -bool -HostInfoWindows::GetOSKernelDescription(std::string &s) -{ - return GetOSBuildString(s); +bool HostInfoWindows::GetOSKernelDescription(std::string &s) { + return GetOSBuildString(s); } -bool -HostInfoWindows::GetHostname(std::string &s) -{ - wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; - if (!::GetComputerNameW(buffer, &dwSize)) - return false; +bool HostInfoWindows::GetHostname(std::string &s) { + wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; + if (!::GetComputerNameW(buffer, &dwSize)) + return false; - return llvm::convertWideToUTF8(buffer, s); + return llvm::convertWideToUTF8(buffer, s); } -FileSpec -HostInfoWindows::GetProgramFileSpec() -{ - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - std::vector<wchar_t> buffer(PATH_MAX); - ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); - std::string path; - llvm::convertWideToUTF8(buffer.data(), path); - m_program_filespec.SetFile(path, false); - }); - return m_program_filespec; +FileSpec HostInfoWindows::GetProgramFileSpec() { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + std::vector<wchar_t> buffer(PATH_MAX); + ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); + std::string path; + llvm::convertWideToUTF8(buffer.data(), path); + m_program_filespec.SetFile(path, false); + }); + return m_program_filespec; } -FileSpec -HostInfoWindows::GetDefaultShell() -{ - std::string shell; - GetEnvironmentVar("ComSpec", shell); - return FileSpec(shell, false); +FileSpec HostInfoWindows::GetDefaultShell() { + std::string shell; + GetEnvironmentVar("ComSpec", shell); + return FileSpec(shell, false); } -bool -HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) -{ - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; - llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString()); - llvm::sys::path::remove_filename(path); - llvm::sys::path::append(path, "lib", "site-packages"); - std::replace(path.begin(), path.end(), '\\', '/'); - file_spec.GetDirectory().SetString(path.c_str()); - return true; +bool HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) { + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; + llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString()); + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, "lib", "site-packages"); + std::replace(path.begin(), path.end(), '\\', '/'); + file_spec.GetDirectory().SetString(path.c_str()); + return true; } -bool -HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var) -{ - std::wstring wvar_name; - if (!llvm::ConvertUTF8toWide(var_name, wvar_name)) - return false; - - if (const wchar_t *wvar = _wgetenv(wvar_name.c_str())) - return llvm::convertWideToUTF8(wvar, var); +bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name, + std::string &var) { + std::wstring wvar_name; + if (!llvm::ConvertUTF8toWide(var_name, wvar_name)) return false; + + if (const wchar_t *wvar = _wgetenv(wvar_name.c_str())) + return llvm::convertWideToUTF8(wvar, var); + return false; } diff --git a/lldb/source/Host/windows/HostProcessWindows.cpp b/lldb/source/Host/windows/HostProcessWindows.cpp index 2878171..81c81a7 100644 --- a/lldb/source/Host/windows/HostProcessWindows.cpp +++ b/lldb/source/Host/windows/HostProcessWindows.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/windows.h" -#include "lldb/Host/windows/HostProcessWindows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" @@ -20,123 +20,101 @@ using namespace lldb_private; -namespace -{ -struct MonitorInfo -{ - Host::MonitorChildProcessCallback callback; - HANDLE process_handle; +namespace { +struct MonitorInfo { + Host::MonitorChildProcessCallback callback; + HANDLE process_handle; }; } HostProcessWindows::HostProcessWindows() - : HostNativeProcessBase() - , m_owns_handle(true) -{ -} + : HostNativeProcessBase(), m_owns_handle(true) {} HostProcessWindows::HostProcessWindows(lldb::process_t process) - : HostNativeProcessBase(process) - , m_owns_handle(true) -{ -} + : HostNativeProcessBase(process), m_owns_handle(true) {} -HostProcessWindows::~HostProcessWindows() -{ - Close(); -} +HostProcessWindows::~HostProcessWindows() { Close(); } -void -HostProcessWindows::SetOwnsHandle(bool owns) -{ - m_owns_handle = owns; -} +void HostProcessWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; } -Error HostProcessWindows::Terminate() -{ - Error error; - if (m_process == nullptr) - error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); +Error HostProcessWindows::Terminate() { + Error error; + if (m_process == nullptr) + error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); - if (!::TerminateProcess(m_process, 0)) - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + if (!::TerminateProcess(m_process, 0)) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + return error; } -Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const -{ - Error error; - if (m_process == nullptr) - error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); - - std::vector<wchar_t> wpath(PATH_MAX); - if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) - { - std::string path; - if (llvm::convertWideToUTF8(wpath.data(), path)) - file_spec.SetFile(path, false); - else - error.SetErrorString("Error converting path to UTF-8"); - } +Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const { + Error error; + if (m_process == nullptr) + error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); + + std::vector<wchar_t> wpath(PATH_MAX); + if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) { + std::string path; + if (llvm::convertWideToUTF8(wpath.data(), path)) + file_spec.SetFile(path, false); else - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + error.SetErrorString("Error converting path to UTF-8"); + } else + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + return error; } -lldb::pid_t HostProcessWindows::GetProcessId() const -{ - return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); +lldb::pid_t HostProcessWindows::GetProcessId() const { + return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); } -bool HostProcessWindows::IsRunning() const -{ - if (m_process == nullptr) - return false; +bool HostProcessWindows::IsRunning() const { + if (m_process == nullptr) + return false; - DWORD code = 0; - if (!::GetExitCodeProcess(m_process, &code)) - return false; + DWORD code = 0; + if (!::GetExitCodeProcess(m_process, &code)) + return false; - return (code == STILL_ACTIVE); + return (code == STILL_ACTIVE); } -HostThread -HostProcessWindows::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - HostThread monitor_thread; - MonitorInfo *info = new MonitorInfo; - info->callback = callback; - - // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that - // the monitor thread can have ownership over its own copy of the handle. - HostThread result; - if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) - result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); - return result; +HostThread HostProcessWindows::StartMonitoring( + const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { + HostThread monitor_thread; + MonitorInfo *info = new MonitorInfo; + info->callback = callback; + + // Since the life of this HostProcessWindows instance and the life of the + // process may be different, duplicate the handle so that + // the monitor thread can have ownership over its own copy of the handle. + HostThread result; + if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), + &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + result = ThreadLauncher::LaunchThread("ChildProcessMonitor", + HostProcessWindows::MonitorThread, + info, nullptr); + return result; } -lldb::thread_result_t -HostProcessWindows::MonitorThread(void *thread_arg) -{ - DWORD exit_code; - - MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); - if (info) - { - ::WaitForSingleObject(info->process_handle, INFINITE); - ::GetExitCodeProcess(info->process_handle, &exit_code); - info->callback(::GetProcessId(info->process_handle), true, 0, exit_code); - ::CloseHandle(info->process_handle); - delete (info); - } - return 0; +lldb::thread_result_t HostProcessWindows::MonitorThread(void *thread_arg) { + DWORD exit_code; + + MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); + if (info) { + ::WaitForSingleObject(info->process_handle, INFINITE); + ::GetExitCodeProcess(info->process_handle, &exit_code); + info->callback(::GetProcessId(info->process_handle), true, 0, exit_code); + ::CloseHandle(info->process_handle); + delete (info); + } + return 0; } -void HostProcessWindows::Close() -{ - if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) - ::CloseHandle(m_process); - m_process = nullptr; +void HostProcessWindows::Close() { + if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) + ::CloseHandle(m_process); + m_process = nullptr; } diff --git a/lldb/source/Host/windows/HostThreadWindows.cpp b/lldb/source/Host/windows/HostThreadWindows.cpp index d59064f..41be21b 100644 --- a/lldb/source/Host/windows/HostThreadWindows.cpp +++ b/lldb/source/Host/windows/HostThreadWindows.cpp @@ -9,90 +9,63 @@ #include "lldb/Core/Error.h" -#include "lldb/Host/windows/windows.h" #include "lldb/Host/windows/HostThreadWindows.h" +#include "lldb/Host/windows/windows.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; using namespace lldb_private; -namespace -{ -void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode) -{ - ::ExitThread(dwExitCode); +namespace { +void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode) { + ::ExitThread(dwExitCode); } } HostThreadWindows::HostThreadWindows() - : HostNativeThreadBase() - , m_owns_handle(true) -{ -} + : HostNativeThreadBase(), m_owns_handle(true) {} HostThreadWindows::HostThreadWindows(lldb::thread_t thread) - : HostNativeThreadBase(thread) - , m_owns_handle(true) -{ -} - -HostThreadWindows::~HostThreadWindows() -{ - Reset(); -} - -void -HostThreadWindows::SetOwnsHandle(bool owns) -{ - m_owns_handle = owns; -} - -Error -HostThreadWindows::Join(lldb::thread_result_t *result) -{ - Error error; - if (IsJoinable()) - { - DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE); - if (WAIT_OBJECT_0 == wait_result && result) - { - DWORD exit_code = 0; - if (!::GetExitCodeThread(m_thread, &exit_code)) - *result = 0; - *result = exit_code; - } - else if (WAIT_OBJECT_0 != wait_result) - error.SetError(::GetLastError(), eErrorTypeWin32); - } - else - error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - Reset (); - return error; + : HostNativeThreadBase(thread), m_owns_handle(true) {} + +HostThreadWindows::~HostThreadWindows() { Reset(); } + +void HostThreadWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; } + +Error HostThreadWindows::Join(lldb::thread_result_t *result) { + Error error; + if (IsJoinable()) { + DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE); + if (WAIT_OBJECT_0 == wait_result && result) { + DWORD exit_code = 0; + if (!::GetExitCodeThread(m_thread, &exit_code)) + *result = 0; + *result = exit_code; + } else if (WAIT_OBJECT_0 != wait_result) + error.SetError(::GetLastError(), eErrorTypeWin32); + } else + error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + Reset(); + return error; } -Error -HostThreadWindows::Cancel() -{ - Error error; +Error HostThreadWindows::Cancel() { + Error error; - DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0); - error.SetError(result, eErrorTypeWin32); - return error; + DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0); + error.SetError(result, eErrorTypeWin32); + return error; } -lldb::tid_t -HostThreadWindows::GetThreadId() const -{ - return ::GetThreadId(m_thread); +lldb::tid_t HostThreadWindows::GetThreadId() const { + return ::GetThreadId(m_thread); } -void -HostThreadWindows::Reset() -{ - if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD) - ::CloseHandle(m_thread); +void HostThreadWindows::Reset() { + if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD) + ::CloseHandle(m_thread); - HostNativeThreadBase::Reset(); + HostNativeThreadBase::Reset(); } diff --git a/lldb/source/Host/windows/LockFileWindows.cpp b/lldb/source/Host/windows/LockFileWindows.cpp index 161d3db..e951c1b 100644 --- a/lldb/source/Host/windows/LockFileWindows.cpp +++ b/lldb/source/Host/windows/LockFileWindows.cpp @@ -14,80 +14,65 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error fileLock (HANDLE file_handle, DWORD flags, const uint64_t start, const uint64_t len) -{ - if (start != 0) - return Error ("Non-zero start lock regions are not supported"); +Error fileLock(HANDLE file_handle, DWORD flags, const uint64_t start, + const uint64_t len) { + if (start != 0) + return Error("Non-zero start lock regions are not supported"); - OVERLAPPED overlapped = {0}; + OVERLAPPED overlapped = {0}; - if (!::LockFileEx (file_handle, flags, 0, len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) - return Error (::GetLastError (), eErrorTypeWin32); + if (!::LockFileEx(file_handle, flags, 0, len, 0, &overlapped) && + ::GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); - DWORD bytes; - if (!::GetOverlappedResult (file_handle, &overlapped, &bytes, TRUE)) - return Error (::GetLastError (), eErrorTypeWin32); + DWORD bytes; + if (!::GetOverlappedResult(file_handle, &overlapped, &bytes, TRUE)) + return Error(::GetLastError(), eErrorTypeWin32); - return Error (); + return Error(); } -} // namespace +} // namespace -LockFileWindows::LockFileWindows (int fd) - : LockFileBase (fd), - m_file (reinterpret_cast<HANDLE> (_get_osfhandle (fd))) -{ -} +LockFileWindows::LockFileWindows(int fd) + : LockFileBase(fd), m_file(reinterpret_cast<HANDLE>(_get_osfhandle(fd))) {} -LockFileWindows::~LockFileWindows () -{ - Unlock (); -} +LockFileWindows::~LockFileWindows() { Unlock(); } -bool -LockFileWindows::IsValidFile () const -{ - return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE; +bool LockFileWindows::IsValidFile() const { + return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE; } -Error -LockFileWindows::DoWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len); +Error LockFileWindows::DoWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len); } -Error -LockFileWindows::DoTryWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, start, len); +Error LockFileWindows::DoTryWriteLock(const uint64_t start, + const uint64_t len) { + return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, + start, len); } -Error -LockFileWindows::DoReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, 0, start, len); +Error LockFileWindows::DoReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, 0, start, len); } -Error -LockFileWindows::DoTryReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len); +Error LockFileWindows::DoTryReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len); } -Error -LockFileWindows::DoUnlock () -{ - OVERLAPPED overlapped = {0}; +Error LockFileWindows::DoUnlock() { + OVERLAPPED overlapped = {0}; - if (!::UnlockFileEx (m_file, 0, m_len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) - return Error (::GetLastError (), eErrorTypeWin32); + if (!::UnlockFileEx(m_file, 0, m_len, 0, &overlapped) && + ::GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); - DWORD bytes; - if (!::GetOverlappedResult (m_file, &overlapped, &bytes, TRUE)) - return Error (::GetLastError (), eErrorTypeWin32); + DWORD bytes; + if (!::GetOverlappedResult(m_file, &overlapped, &bytes, TRUE)) + return Error(::GetLastError(), eErrorTypeWin32); - return Error (); + return Error(); } diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp index 6ed8d0e..b63f3bc 100644 --- a/lldb/source/Host/windows/PipeWindows.cpp +++ b/lldb/source/Host/windows/PipeWindows.cpp @@ -23,316 +23,273 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { std::atomic<uint32_t> g_pipe_serial(0); } -PipeWindows::PipeWindows() -{ - m_read = INVALID_HANDLE_VALUE; - m_write = INVALID_HANDLE_VALUE; +PipeWindows::PipeWindows() { + m_read = INVALID_HANDLE_VALUE; + m_write = INVALID_HANDLE_VALUE; - m_read_fd = -1; - m_write_fd = -1; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); -} - -PipeWindows::~PipeWindows() -{ - Close(); + m_read_fd = -1; + m_write_fd = -1; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } -Error -PipeWindows::CreateNew(bool child_process_inherit) -{ - // Even for anonymous pipes, we open a named pipe. This is because you cannot get - // overlapped i/o on Windows without using a named pipe. So we synthesize a unique - // name. - uint32_t serial = g_pipe_serial.fetch_add(1); - std::string pipe_name; - llvm::raw_string_ostream pipe_name_stream(pipe_name); - pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial; - pipe_name_stream.flush(); - - return CreateNew(pipe_name.c_str(), child_process_inherit); +PipeWindows::~PipeWindows() { Close(); } + +Error PipeWindows::CreateNew(bool child_process_inherit) { + // Even for anonymous pipes, we open a named pipe. This is because you cannot + // get + // overlapped i/o on Windows without using a named pipe. So we synthesize a + // unique + // name. + uint32_t serial = g_pipe_serial.fetch_add(1); + std::string pipe_name; + llvm::raw_string_ostream pipe_name_stream(pipe_name); + pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial; + pipe_name_stream.flush(); + + return CreateNew(pipe_name.c_str(), child_process_inherit); } -Error -PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) -{ - if (name.empty()) - return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); - - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - - std::string pipe_path = "\\\\.\\Pipe\\"; - pipe_path.append(name); - - // Always open for overlapped i/o. We implement blocking manually in Read and Write. - DWORD read_mode = FILE_FLAG_OVERLAPPED; - m_read = ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, - 1024, 120 * 1000, NULL); - if (INVALID_HANDLE_VALUE == m_read) - return Error(::GetLastError(), eErrorTypeWin32); - m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - - // Open the write end of the pipe. - Error result = OpenNamedPipe(name, child_process_inherit, false); - if (!result.Success()) - { - CloseReadFileDescriptor(); - return result; - } - +Error PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) { + if (name.empty()) + return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); + + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); + + std::string pipe_path = "\\\\.\\Pipe\\"; + pipe_path.append(name); + + // Always open for overlapped i/o. We implement blocking manually in Read and + // Write. + DWORD read_mode = FILE_FLAG_OVERLAPPED; + m_read = ::CreateNamedPipeA( + pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, + PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL); + if (INVALID_HANDLE_VALUE == m_read) + return Error(::GetLastError(), eErrorTypeWin32); + m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + + // Open the write end of the pipe. + Error result = OpenNamedPipe(name, child_process_inherit, false); + if (!result.Success()) { + CloseReadFileDescriptor(); return result; + } + + return result; } -Error -PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name) -{ - llvm::SmallString<128> pipe_name; - Error error; - ::UUID unique_id; - RPC_CSTR unique_string; - RPC_STATUS status = ::UuidCreate(&unique_id); - if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) - status = ::UuidToStringA(&unique_id, &unique_string); - if (status == RPC_S_OK) - { - pipe_name = prefix; - pipe_name += "-"; - pipe_name += reinterpret_cast<char *>(unique_string); - ::RpcStringFreeA(&unique_string); - error = CreateNew(pipe_name, child_process_inherit); - } - else - { - error.SetError(status, eErrorTypeWin32); - } - if (error.Success()) - name = pipe_name; - return error; +Error PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, + bool child_process_inherit, + llvm::SmallVectorImpl<char> &name) { + llvm::SmallString<128> pipe_name; + Error error; + ::UUID unique_id; + RPC_CSTR unique_string; + RPC_STATUS status = ::UuidCreate(&unique_id); + if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) + status = ::UuidToStringA(&unique_id, &unique_string); + if (status == RPC_S_OK) { + pipe_name = prefix; + pipe_name += "-"; + pipe_name += reinterpret_cast<char *>(unique_string); + ::RpcStringFreeA(&unique_string); + error = CreateNew(pipe_name, child_process_inherit); + } else { + error.SetError(status, eErrorTypeWin32); + } + if (error.Success()) + name = pipe_name; + return error; } -Error -PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); +Error PipeWindows::OpenAsReader(llvm::StringRef name, + bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - return OpenNamedPipe(name, child_process_inherit, true); + return OpenNamedPipe(name, child_process_inherit, true); } -Error -PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) -{ - if (CanRead() || CanWrite()) - return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); +Error PipeWindows::OpenAsWriterWithTimeout( + llvm::StringRef name, bool child_process_inherit, + const std::chrono::microseconds &timeout) { + if (CanRead() || CanWrite()) + return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); - return OpenNamedPipe(name, child_process_inherit, false); + return OpenNamedPipe(name, child_process_inherit, false); } -Error -PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, bool is_read) -{ - if (name.empty()) - return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); +Error PipeWindows::OpenNamedPipe(llvm::StringRef name, + bool child_process_inherit, bool is_read) { + if (name.empty()) + return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); - assert(is_read ? !CanRead() : !CanWrite()); + assert(is_read ? !CanRead() : !CanWrite()); - SECURITY_ATTRIBUTES attributes = {0}; - attributes.bInheritHandle = child_process_inherit; + SECURITY_ATTRIBUTES attributes = {0}; + attributes.bInheritHandle = child_process_inherit; - std::string pipe_path = "\\\\.\\Pipe\\"; - pipe_path.append(name); + std::string pipe_path = "\\\\.\\Pipe\\"; + pipe_path.append(name); - if (is_read) - { - m_read = - ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == m_read) - return Error(::GetLastError(), eErrorTypeWin32); + if (is_read) { + m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == m_read) + return Error(::GetLastError(), eErrorTypeWin32); - m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); + m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - else - { - m_write = - ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == m_write) - return Error(::GetLastError(), eErrorTypeWin32); + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + } else { + m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == m_write) + return Error(::GetLastError(), eErrorTypeWin32); - m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); + m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); - } + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + } - return Error(); + return Error(); } -int -PipeWindows::GetReadFileDescriptor() const -{ - return m_read_fd; -} +int PipeWindows::GetReadFileDescriptor() const { return m_read_fd; } -int -PipeWindows::GetWriteFileDescriptor() const -{ - return m_write_fd; -} +int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; } -int -PipeWindows::ReleaseReadFileDescriptor() -{ - if (!CanRead()) - return -1; - int result = m_read_fd; - m_read_fd = -1; - if (m_read_overlapped.hEvent) - ::CloseHandle(m_read_overlapped.hEvent); - m_read = INVALID_HANDLE_VALUE; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); - return result; +int PipeWindows::ReleaseReadFileDescriptor() { + if (!CanRead()) + return -1; + int result = m_read_fd; + m_read_fd = -1; + if (m_read_overlapped.hEvent) + ::CloseHandle(m_read_overlapped.hEvent); + m_read = INVALID_HANDLE_VALUE; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); + return result; } -int -PipeWindows::ReleaseWriteFileDescriptor() -{ - if (!CanWrite()) - return -1; - int result = m_write_fd; - m_write_fd = -1; - m_write = INVALID_HANDLE_VALUE; - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); - return result; +int PipeWindows::ReleaseWriteFileDescriptor() { + if (!CanWrite()) + return -1; + int result = m_write_fd; + m_write_fd = -1; + m_write = INVALID_HANDLE_VALUE; + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + return result; } -void -PipeWindows::CloseReadFileDescriptor() -{ - if (!CanRead()) - return; - - if (m_read_overlapped.hEvent) - ::CloseHandle(m_read_overlapped.hEvent); - _close(m_read_fd); - m_read = INVALID_HANDLE_VALUE; - m_read_fd = -1; - ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); +void PipeWindows::CloseReadFileDescriptor() { + if (!CanRead()) + return; + + if (m_read_overlapped.hEvent) + ::CloseHandle(m_read_overlapped.hEvent); + _close(m_read_fd); + m_read = INVALID_HANDLE_VALUE; + m_read_fd = -1; + ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); } -void -PipeWindows::CloseWriteFileDescriptor() -{ - if (!CanWrite()) - return; +void PipeWindows::CloseWriteFileDescriptor() { + if (!CanWrite()) + return; - _close(m_write_fd); - m_write = INVALID_HANDLE_VALUE; - m_write_fd = -1; - ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); + _close(m_write_fd); + m_write = INVALID_HANDLE_VALUE; + m_write_fd = -1; + ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); } -void -PipeWindows::Close() -{ - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); +void PipeWindows::Close() { + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); } -Error -PipeWindows::Delete(llvm::StringRef name) -{ - return Error(); -} +Error PipeWindows::Delete(llvm::StringRef name) { return Error(); } -bool -PipeWindows::CanRead() const -{ - return (m_read != INVALID_HANDLE_VALUE); -} +bool PipeWindows::CanRead() const { return (m_read != INVALID_HANDLE_VALUE); } -bool -PipeWindows::CanWrite() const -{ - return (m_write != INVALID_HANDLE_VALUE); -} +bool PipeWindows::CanWrite() const { return (m_write != INVALID_HANDLE_VALUE); } HANDLE -PipeWindows::GetReadNativeHandle() -{ - return m_read; -} +PipeWindows::GetReadNativeHandle() { return m_read; } HANDLE -PipeWindows::GetWriteNativeHandle() -{ - return m_write; -} - -Error -PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read) -{ - if (!CanRead()) - return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - bytes_read = 0; - DWORD sys_bytes_read = size; - BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, &m_read_overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) - return Error(::GetLastError(), eErrorTypeWin32); - - DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; - DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); - if (wait_result != WAIT_OBJECT_0) - { - // The operation probably failed. However, if it timed out, we need to cancel the I/O. - // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx, - // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. - // If that happens, the original operation should be considered to have been successful. - bool failed = true; - DWORD failure_error = ::GetLastError(); - if (wait_result == WAIT_TIMEOUT) - { - BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); - if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) - failed = false; - } - if (failed) - return Error(failure_error, eErrorTypeWin32); +PipeWindows::GetWriteNativeHandle() { return m_write; } + +Error PipeWindows::ReadWithTimeout(void *buf, size_t size, + const std::chrono::microseconds &duration, + size_t &bytes_read) { + if (!CanRead()) + return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + bytes_read = 0; + DWORD sys_bytes_read = size; + BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, + &m_read_overlapped); + if (!result && GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); + + DWORD timeout = (duration == std::chrono::microseconds::zero()) + ? INFINITE + : duration.count() * 1000; + DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); + if (wait_result != WAIT_OBJECT_0) { + // The operation probably failed. However, if it timed out, we need to + // cancel the I/O. + // Between the time we returned from WaitForSingleObject and the time we + // call CancelIoEx, + // the operation may complete. If that hapens, CancelIoEx will fail and + // return ERROR_NOT_FOUND. + // If that happens, the original operation should be considered to have been + // successful. + bool failed = true; + DWORD failure_error = ::GetLastError(); + if (wait_result == WAIT_TIMEOUT) { + BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); + if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) + failed = false; } - - // Now we call GetOverlappedResult setting bWait to false, since we've already waited - // as long as we're willing to. - if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) - return Error(::GetLastError(), eErrorTypeWin32); - - bytes_read = sys_bytes_read; - return Error(); + if (failed) + return Error(failure_error, eErrorTypeWin32); + } + + // Now we call GetOverlappedResult setting bWait to false, since we've already + // waited + // as long as we're willing to. + if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) + return Error(::GetLastError(), eErrorTypeWin32); + + bytes_read = sys_bytes_read; + return Error(); } -Error -PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) -{ - if (!CanWrite()) - return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); - - DWORD sys_bytes_written = 0; - BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, &m_write_overlapped); - if (!write_result && GetLastError() != ERROR_IO_PENDING) - return Error(::GetLastError(), eErrorTypeWin32); - - BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE); - if (!result) - return Error(::GetLastError(), eErrorTypeWin32); - return Error(); +Error PipeWindows::Write(const void *buf, size_t num_bytes, + size_t &bytes_written) { + if (!CanWrite()) + return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); + + DWORD sys_bytes_written = 0; + BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, + &m_write_overlapped); + if (!write_result && GetLastError() != ERROR_IO_PENDING) + return Error(::GetLastError(), eErrorTypeWin32); + + BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, + &sys_bytes_written, TRUE); + if (!result) + return Error(::GetLastError(), eErrorTypeWin32); + return Error(); } diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp index caf0fc7..ef3656a 100644 --- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp +++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostProcess.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" +#include "lldb/Host/HostProcess.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "llvm/ADT/SmallVector.h" @@ -20,127 +20,130 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -void -CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) -{ - if (env.GetArgumentCount() == 0) - return; - - // Environment buffer is a null terminated list of null terminated strings - for (int i = 0; i < env.GetArgumentCount(); ++i) - { - std::wstring warg; - if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) - { - buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1)); - } +namespace { +void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) { + if (env.GetArgumentCount() == 0) + return; + + // Environment buffer is a null terminated list of null terminated strings + for (int i = 0; i < env.GetArgumentCount(); ++i) { + std::wstring warg; + if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) { + buffer.insert(buffer.end(), (char *)warg.c_str(), + (char *)(warg.c_str() + warg.size() + 1)); } - // One null wchar_t (to end the block) is two null bytes - buffer.push_back(0); - buffer.push_back(0); + } + // One null wchar_t (to end the block) is two null bytes + buffer.push_back(0); + buffer.push_back(0); } } HostProcess -ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - error.Clear(); - - std::string executable; - std::string commandLine; - std::vector<char> environment; - STARTUPINFO startupinfo = {0}; - PROCESS_INFORMATION pi = {0}; - - HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); - HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); - HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); - - startupinfo.cb = sizeof(startupinfo); - startupinfo.dwFlags |= STARTF_USESTDHANDLES; - startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); - startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); - startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); - - const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); - if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true")) - { - startupinfo.dwFlags |= STARTF_USESHOWWINDOW; - startupinfo.wShowWindow = SW_HIDE; - } - - DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; - if (launch_info.GetFlags().Test(eLaunchFlagDebug)) - flags |= DEBUG_ONLY_THIS_PROCESS; - - auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); - LPVOID env_block = nullptr; - ::CreateEnvironmentBuffer(env, environment); - if (!environment.empty()) - env_block = environment.data(); - - executable = launch_info.GetExecutableFile().GetPath(); - launch_info.GetArguments().GetQuotedCommandString(commandLine); - - std::wstring wexecutable, wcommandLine, wworkingDirectory; - llvm::ConvertUTF8toWide(executable, wexecutable); - llvm::ConvertUTF8toWide(commandLine, wcommandLine); - llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory); - - wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it - BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, - wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi); - if (result) - { - // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. - ::CloseHandle(pi.hThread); - } - - if (stdin_handle) - ::CloseHandle(stdin_handle); - if (stdout_handle) - ::CloseHandle(stdout_handle); - if (stderr_handle) - ::CloseHandle(stderr_handle); - - if (!result) - error.SetError(::GetLastError(), eErrorTypeWin32); - return HostProcess(pi.hProcess); +ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + error.Clear(); + + std::string executable; + std::string commandLine; + std::vector<char> environment; + STARTUPINFO startupinfo = {0}; + PROCESS_INFORMATION pi = {0}; + + HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); + HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); + HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); + + startupinfo.cb = sizeof(startupinfo); + startupinfo.dwFlags |= STARTF_USESTDHANDLES; + startupinfo.hStdError = + stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); + startupinfo.hStdInput = + stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); + startupinfo.hStdOutput = + stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); + + const char *hide_console_var = + getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); + if (hide_console_var && + llvm::StringRef(hide_console_var).equals_lower("true")) { + startupinfo.dwFlags |= STARTF_USESHOWWINDOW; + startupinfo.wShowWindow = SW_HIDE; + } + + DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= DEBUG_ONLY_THIS_PROCESS; + + auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); + LPVOID env_block = nullptr; + ::CreateEnvironmentBuffer(env, environment); + if (!environment.empty()) + env_block = environment.data(); + + executable = launch_info.GetExecutableFile().GetPath(); + launch_info.GetArguments().GetQuotedCommandString(commandLine); + + std::wstring wexecutable, wcommandLine, wworkingDirectory; + llvm::ConvertUTF8toWide(executable, wexecutable); + llvm::ConvertUTF8toWide(commandLine, wcommandLine); + llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), + wworkingDirectory); + + wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because + // CreateProcessW can modify it + BOOL result = ::CreateProcessW( + wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, + wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), + &startupinfo, &pi); + if (result) { + // Do not call CloseHandle on pi.hProcess, since we want to pass that back + // through the HostProcess. + ::CloseHandle(pi.hThread); + } + + if (stdin_handle) + ::CloseHandle(stdin_handle); + if (stdout_handle) + ::CloseHandle(stdout_handle); + if (stderr_handle) + ::CloseHandle(stderr_handle); + + if (!result) + error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(pi.hProcess); } HANDLE -ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) -{ - const FileAction *action = launch_info.GetFileActionForFD(fd); - if (action == nullptr) - return NULL; - SECURITY_ATTRIBUTES secattr = {0}; - secattr.nLength = sizeof(SECURITY_ATTRIBUTES); - secattr.bInheritHandle = TRUE; - - const char *path = action->GetPath(); - DWORD access = 0; - DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - DWORD create = 0; - DWORD flags = 0; - if (fd == STDIN_FILENO) - { - access = GENERIC_READ; - create = OPEN_EXISTING; - flags = FILE_ATTRIBUTE_READONLY; - } - if (fd == STDOUT_FILENO || fd == STDERR_FILENO) - { - access = GENERIC_WRITE; - create = CREATE_ALWAYS; - if (fd == STDERR_FILENO) - flags = FILE_FLAG_WRITE_THROUGH; - } - - std::wstring wpath; - llvm::ConvertUTF8toWide(path, wpath); - HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL); - return (result == INVALID_HANDLE_VALUE) ? NULL : result; +ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, + int fd) { + const FileAction *action = launch_info.GetFileActionForFD(fd); + if (action == nullptr) + return NULL; + SECURITY_ATTRIBUTES secattr = {0}; + secattr.nLength = sizeof(SECURITY_ATTRIBUTES); + secattr.bInheritHandle = TRUE; + + const char *path = action->GetPath(); + DWORD access = 0; + DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + DWORD create = 0; + DWORD flags = 0; + if (fd == STDIN_FILENO) { + access = GENERIC_READ; + create = OPEN_EXISTING; + flags = FILE_ATTRIBUTE_READONLY; + } + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + access = GENERIC_WRITE; + create = CREATE_ALWAYS; + if (fd == STDERR_FILENO) + flags = FILE_FLAG_WRITE_THROUGH; + } + + std::wstring wpath; + llvm::ConvertUTF8toWide(path, wpath); + HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, + flags, NULL); + return (result == INVALID_HANDLE_VALUE) ? NULL : result; } diff --git a/lldb/source/Host/windows/ProcessRunLock.cpp b/lldb/source/Host/windows/ProcessRunLock.cpp index 1f21552..590007b 100644 --- a/lldb/source/Host/windows/ProcessRunLock.cpp +++ b/lldb/source/Host/windows/ProcessRunLock.cpp @@ -1,106 +1,83 @@ #include "lldb/Host/ProcessRunLock.h" #include "lldb/Host/windows/windows.h" -namespace -{ +namespace { #if defined(__MINGW32__) // Taken from WinNT.h -typedef struct _RTL_SRWLOCK { - PVOID Ptr; -} RTL_SRWLOCK, *PRTL_SRWLOCK; +typedef struct _RTL_SRWLOCK { PVOID Ptr; } RTL_SRWLOCK, *PRTL_SRWLOCK; // Taken from WinBase.h typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; #endif } - -static PSRWLOCK GetLock(lldb::rwlock_t lock) -{ - return static_cast<PSRWLOCK>(lock); +static PSRWLOCK GetLock(lldb::rwlock_t lock) { + return static_cast<PSRWLOCK>(lock); } -static bool ReadLock(lldb::rwlock_t rwlock) -{ - ::AcquireSRWLockShared(GetLock(rwlock)); - return true; +static bool ReadLock(lldb::rwlock_t rwlock) { + ::AcquireSRWLockShared(GetLock(rwlock)); + return true; } -static bool ReadUnlock(lldb::rwlock_t rwlock) -{ - ::ReleaseSRWLockShared(GetLock(rwlock)); - return true; +static bool ReadUnlock(lldb::rwlock_t rwlock) { + ::ReleaseSRWLockShared(GetLock(rwlock)); + return true; } -static bool WriteLock(lldb::rwlock_t rwlock) -{ - ::AcquireSRWLockExclusive(GetLock(rwlock)); - return true; +static bool WriteLock(lldb::rwlock_t rwlock) { + ::AcquireSRWLockExclusive(GetLock(rwlock)); + return true; } -static bool WriteTryLock(lldb::rwlock_t rwlock) -{ - return !!::TryAcquireSRWLockExclusive(GetLock(rwlock)); +static bool WriteTryLock(lldb::rwlock_t rwlock) { + return !!::TryAcquireSRWLockExclusive(GetLock(rwlock)); } -static bool WriteUnlock(lldb::rwlock_t rwlock) -{ - ::ReleaseSRWLockExclusive(GetLock(rwlock)); - return true; +static bool WriteUnlock(lldb::rwlock_t rwlock) { + ::ReleaseSRWLockExclusive(GetLock(rwlock)); + return true; } using namespace lldb_private; -ProcessRunLock::ProcessRunLock() - : m_running(false) -{ - m_rwlock = new SRWLOCK; - InitializeSRWLock(GetLock(m_rwlock)); +ProcessRunLock::ProcessRunLock() : m_running(false) { + m_rwlock = new SRWLOCK; + InitializeSRWLock(GetLock(m_rwlock)); } -ProcessRunLock::~ProcessRunLock() -{ - delete m_rwlock; -} +ProcessRunLock::~ProcessRunLock() { delete m_rwlock; } -bool ProcessRunLock::ReadTryLock() -{ - ::ReadLock(m_rwlock); - if (m_running == false) - return true; - ::ReadUnlock(m_rwlock); - return false; +bool ProcessRunLock::ReadTryLock() { + ::ReadLock(m_rwlock); + if (m_running == false) + return true; + ::ReadUnlock(m_rwlock); + return false; } -bool ProcessRunLock::ReadUnlock() -{ - return ::ReadUnlock(m_rwlock); +bool ProcessRunLock::ReadUnlock() { return ::ReadUnlock(m_rwlock); } + +bool ProcessRunLock::SetRunning() { + WriteLock(m_rwlock); + m_running = true; + WriteUnlock(m_rwlock); + return true; } -bool ProcessRunLock::SetRunning () -{ - WriteLock(m_rwlock); +bool ProcessRunLock::TrySetRunning() { + if (WriteTryLock(m_rwlock)) { + bool was_running = m_running; m_running = true; WriteUnlock(m_rwlock); - return true; -} - -bool ProcessRunLock::TrySetRunning () -{ - if (WriteTryLock(m_rwlock)) - { - bool was_running = m_running; - m_running = true; - WriteUnlock(m_rwlock); - return !was_running; - } - return false; + return !was_running; + } + return false; } -bool ProcessRunLock::SetStopped () -{ - WriteLock(m_rwlock); - m_running = false; - WriteUnlock(m_rwlock); - return true; +bool ProcessRunLock::SetStopped() { + WriteLock(m_rwlock); + m_running = false; + WriteUnlock(m_rwlock); + return true; } diff --git a/lldb/source/Host/windows/ThisThread.cpp b/lldb/source/Host/windows/ThisThread.cpp index bcd5b8d..8db12f0 100644 --- a/lldb/source/Host/windows/ThisThread.cpp +++ b/lldb/source/Host/windows/ThisThread.cpp @@ -9,8 +9,8 @@ #include "lldb/Core/Error.h" -#include "lldb/Host/windows/windows.h" #include "lldb/Host/ThisThread.h" +#include "lldb/Host/windows/windows.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -20,47 +20,44 @@ using namespace lldb_private; #if defined(_MSC_VER) && !defined(__clang__) -namespace -{ +namespace { static const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push, 8) -struct THREADNAME_INFO -{ - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to thread name - DWORD dwThreadId; // Thread ID (-1 == current thread) - DWORD dwFlags; // Reserved. Do not use. +struct THREADNAME_INFO { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to thread name + DWORD dwThreadId; // Thread ID (-1 == current thread) + DWORD dwFlags; // Reserved. Do not use. }; #pragma pack(pop) } #endif -void -ThisThread::SetName(llvm::StringRef name) -{ -// Other compilers don't yet support SEH, so we can only set the thread if compiling with MSVC. +void ThisThread::SetName(llvm::StringRef name) { +// Other compilers don't yet support SEH, so we can only set the thread if +// compiling with MSVC. // TODO(zturner): Once clang-cl supports SEH, relax this conditional. #if defined(_MSC_VER) && !defined(__clang__) - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name.data(); - info.dwThreadId = ::GetCurrentThreadId(); - info.dwFlags = 0; - - __try { - ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); - } - __except(EXCEPTION_EXECUTE_HANDLER) {} + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name.data(); + info.dwThreadId = ::GetCurrentThreadId(); + info.dwFlags = 0; + + __try { + ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } #endif } -void -ThisThread::GetName(llvm::SmallVectorImpl<char> &name) -{ - // Getting the thread name is not supported on Windows. - // TODO(zturner): In SetName(), make a TLS entry that contains the thread's name, and in this function - // try to extract that TLS entry. - name.clear(); +void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) { + // Getting the thread name is not supported on Windows. + // TODO(zturner): In SetName(), make a TLS entry that contains the thread's + // name, and in this function + // try to extract that TLS entry. + name.clear(); } diff --git a/lldb/source/Host/windows/Windows.cpp b/lldb/source/Host/windows/Windows.cpp index a1ee5d6..8347b82 100644 --- a/lldb/source/Host/windows/Windows.cpp +++ b/lldb/source/Host/windows/Windows.cpp @@ -9,276 +9,253 @@ // This file provides Windows support functions -#include "lldb/Host/windows/windows.h" #include "lldb/Host/PosixApi.h" +#include "lldb/Host/windows/windows.h" #include "llvm/Support/ConvertUTF.h" #include <assert.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> -#include <io.h> #include <cerrno> #include <ctype.h> +#include <io.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> -// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors -extern "C" -{ - char *_getcwd(char *buffer, int maxlen); - int _chdir(const char *path); +// These prototypes are defined in <direct.h>, but it also defines chdir() and +// getcwd(), giving multiply defined errors +extern "C" { +char *_getcwd(char *buffer, int maxlen); +int _chdir(const char *path); } -namespace -{ -bool -utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) -{ - const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8); - size_t sourceLen = strlen(utf8) + 1 /* convert null too */; - UTF16 *target = reinterpret_cast<UTF16 *>(buf); - ConversionFlags flags = strictConversion; - return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK; +namespace { +bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) { + const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8); + size_t sourceLen = strlen(utf8) + 1 /* convert null too */; + UTF16 *target = reinterpret_cast<UTF16 *>(buf); + ConversionFlags flags = strictConversion; + return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, + target + bufSize, flags) == conversionOK; } -bool -wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) -{ - const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide); - size_t sourceLen = wcslen(wide) + 1 /* convert null too */; - UTF8 *target = reinterpret_cast<UTF8 *>(buf); - ConversionFlags flags = strictConversion; - return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK; +bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) { + const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide); + size_t sourceLen = wcslen(wide) + 1 /* convert null too */; + UTF8 *target = reinterpret_cast<UTF8 *>(buf); + ConversionFlags flags = strictConversion; + return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, + target + bufSize, flags) == conversionOK; } } -int vasprintf(char **ret, const char *fmt, va_list ap) -{ - char *buf; - int len; - size_t buflen; - va_list ap2; +int vasprintf(char **ret, const char *fmt, va_list ap) { + char *buf; + int len; + size_t buflen; + va_list ap2; #if defined(_MSC_VER) || defined(__MINGW64) - ap2 = ap; - len = _vscprintf(fmt, ap2); + ap2 = ap; + len = _vscprintf(fmt, ap2); #else - va_copy(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); + va_copy(ap2, ap); + len = vsnprintf(NULL, 0, fmt, ap2); #endif - if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; + if (len >= 0 && + (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; } -char* strcasestr(const char *s, const char* find) -{ - char c, sc; - size_t len; - - if ((c = *find++) != 0) { - c = tolower((unsigned char) c); - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return 0; - } while ((char) tolower((unsigned char) sc) != c); - } while (strncasecmp(s, find, len) != 0); - s--; - } - return ((char *) s); +char *strcasestr(const char *s, const char *find) { + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return 0; + } while ((char)tolower((unsigned char)sc) != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); } -char* realpath(const char * name, char * resolved) -{ - char *retname = NULL; - - /* SUSv3 says we must set `errno = EINVAL', and return NULL, - * if `name' is passed as a NULL pointer. - */ - if (name == NULL) - { - errno = EINVAL; - return NULL; - } +char *realpath(const char *name, char *resolved) { + char *retname = NULL; - /* Otherwise, `name' must refer to a readable filesystem object, - * if we are going to resolve its absolute path name. - */ - wchar_t wideNameBuffer[PATH_MAX]; - wchar_t *wideName = wideNameBuffer; - if (!utf8ToWide(name, wideName, PATH_MAX)) - { - errno = EINVAL; - return NULL; - } + /* SUSv3 says we must set `errno = EINVAL', and return NULL, + * if `name' is passed as a NULL pointer. + */ + if (name == NULL) { + errno = EINVAL; + return NULL; + } + + /* Otherwise, `name' must refer to a readable filesystem object, + * if we are going to resolve its absolute path name. + */ + wchar_t wideNameBuffer[PATH_MAX]; + wchar_t *wideName = wideNameBuffer; + if (!utf8ToWide(name, wideName, PATH_MAX)) { + errno = EINVAL; + return NULL; + } - if (_waccess(wideName, 4) != 0) - return NULL; + if (_waccess(wideName, 4) != 0) + return NULL; - /* If `name' didn't point to an existing entity, - * then we don't get to here; we simply fall past this block, - * returning NULL, with `errno' appropriately set by `access'. + /* If `name' didn't point to an existing entity, + * then we don't get to here; we simply fall past this block, + * returning NULL, with `errno' appropriately set by `access'. + * + * When we _do_ get to here, then we can use `_fullpath' to + * resolve the full path for `name' into `resolved', but first, + * check that we have a suitable buffer, in which to return it. + */ + + if ((retname = resolved) == NULL) { + /* Caller didn't give us a buffer, so we'll exercise the + * option granted by SUSv3, and allocate one. * - * When we _do_ get to here, then we can use `_fullpath' to - * resolve the full path for `name' into `resolved', but first, - * check that we have a suitable buffer, in which to return it. + * `_fullpath' would do this for us, but it uses `malloc', and + * Microsoft's implementation doesn't set `errno' on failure. + * If we don't do this explicitly ourselves, then we will not + * know if `_fullpath' fails on `malloc' failure, or for some + * other reason, and we want to set `errno = ENOMEM' for the + * `malloc' failure case. */ - if ((retname = resolved) == NULL) - { - /* Caller didn't give us a buffer, so we'll exercise the - * option granted by SUSv3, and allocate one. - * - * `_fullpath' would do this for us, but it uses `malloc', and - * Microsoft's implementation doesn't set `errno' on failure. - * If we don't do this explicitly ourselves, then we will not - * know if `_fullpath' fails on `malloc' failure, or for some - * other reason, and we want to set `errno = ENOMEM' for the - * `malloc' failure case. - */ - - retname = (char *)malloc(PATH_MAX); - if (retname == NULL) - { - errno = ENOMEM; - return NULL; - } + retname = (char *)malloc(PATH_MAX); + if (retname == NULL) { + errno = ENOMEM; + return NULL; } + } - /* Otherwise, when we do have a valid buffer, - * `_fullpath' should only fail if the path name is too long. - */ + /* Otherwise, when we do have a valid buffer, + * `_fullpath' should only fail if the path name is too long. + */ - wchar_t wideFullPathBuffer[PATH_MAX]; - wchar_t *wideFullPath; - if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL) - { - errno = ENAMETOOLONG; - return NULL; - } + wchar_t wideFullPathBuffer[PATH_MAX]; + wchar_t *wideFullPath; + if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == + NULL) { + errno = ENAMETOOLONG; + return NULL; + } - // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS - // FIXME: Check for failure - size_t initialLength = wcslen(wideFullPath); - GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX); - GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1); + // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS + // FIXME: Check for failure + size_t initialLength = wcslen(wideFullPath); + GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX); + GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1); - // Convert back to UTF-8 - if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) - { - errno = EINVAL; - return NULL; - } + // Convert back to UTF-8 + if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) { + errno = EINVAL; + return NULL; + } - // Force drive to be upper case - if (retname[1] == ':') - retname[0] = toupper(retname[0]); + // Force drive to be upper case + if (retname[1] == ':') + retname[0] = toupper(retname[0]); - return retname; + return retname; } #ifdef _MSC_VER -char* basename(char *path) -{ - char* l1 = strrchr(path, '\\'); - char* l2 = strrchr(path, '/'); - if (l2 > l1) l1 = l2; - if (!l1) return path; // no base name - return &l1[1]; +char *basename(char *path) { + char *l1 = strrchr(path, '\\'); + char *l2 = strrchr(path, '/'); + if (l2 > l1) + l1 = l2; + if (!l1) + return path; // no base name + return &l1[1]; } // use _getcwd() instead of GetCurrentDirectory() because it updates errno -char* getcwd(char* path, int max) -{ - assert(path == NULL || max <= PATH_MAX); - wchar_t wpath[PATH_MAX]; - if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) - { - // Caller is allowed to pass in NULL for `path`. - // In that case, we're supposed to allocate a - // buffer on the caller's behalf. - if (path == NULL) - { - max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1; - path = (char *)malloc(max); - if (path == NULL) - { - errno = ENOMEM; - return NULL; - } - } - if (wideToUtf8(wresult, path, max)) - return path; +char *getcwd(char *path, int max) { + assert(path == NULL || max <= PATH_MAX); + wchar_t wpath[PATH_MAX]; + if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) { + // Caller is allowed to pass in NULL for `path`. + // In that case, we're supposed to allocate a + // buffer on the caller's behalf. + if (path == NULL) { + max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1; + path = (char *)malloc(max); + if (path == NULL) { + errno = ENOMEM; + return NULL; + } } - return NULL; + if (wideToUtf8(wresult, path, max)) + return path; + } + return NULL; } // use _chdir() instead of SetCurrentDirectory() because it updates errno -int chdir(const char* path) -{ - return _chdir(path); -} - -char *dirname(char *path) -{ - char* l1 = strrchr(path, '\\'); - char* l2 = strrchr(path, '/'); - if (l2 > l1) l1 = l2; - if (!l1) return NULL; // no dir name - *l1 = 0; - return path; +int chdir(const char *path) { return _chdir(path); } + +char *dirname(char *path) { + char *l1 = strrchr(path, '\\'); + char *l2 = strrchr(path, '/'); + if (l2 > l1) + l1 = l2; + if (!l1) + return NULL; // no dir name + *l1 = 0; + return path; } -int strcasecmp(const char* s1, const char* s2) -{ - return stricmp(s1, s2); -} +int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); } -int strncasecmp(const char* s1, const char* s2, size_t n) -{ - return strnicmp(s1, s2, n); +int strncasecmp(const char *s1, const char *s2, size_t n) { + return strnicmp(s1, s2, n); } -int usleep(uint32_t useconds) -{ - Sleep(useconds / 1000); - return 0; +int usleep(uint32_t useconds) { + Sleep(useconds / 1000); + return 0; } #if _MSC_VER < 1900 namespace lldb_private { -int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) -{ - int old_errno = errno; - int r = ::vsnprintf(buffer, count, format, argptr); - int new_errno = errno; - buffer[count-1] = '\0'; - if (r == -1 || r == count) - { - FILE *nul = fopen("nul", "w"); - int bytes_written = ::vfprintf(nul, format, argptr); - fclose(nul); - if (bytes_written < count) - errno = new_errno; - else - { - errno = old_errno; - r = bytes_written; - } +int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) { + int old_errno = errno; + int r = ::vsnprintf(buffer, count, format, argptr); + int new_errno = errno; + buffer[count - 1] = '\0'; + if (r == -1 || r == count) { + FILE *nul = fopen("nul", "w"); + int bytes_written = ::vfprintf(nul, format, argptr); + fclose(nul); + if (bytes_written < count) + errno = new_errno; + else { + errno = old_errno; + r = bytes_written; } - return r; + } + return r; } } // namespace lldb_private #endif |