diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Host/common')
16 files changed, 1248 insertions, 523 deletions
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp index ed67d0c2c2b3..4640154c6cb1 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp @@ -203,7 +203,7 @@ namespace lldb_private { snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str()); } - m_path = std::move (FileSpec (history_path, true).GetPath()); + m_path = FileSpec (history_path, true).GetPath(); } if (m_path.empty()) return NULL; @@ -863,34 +863,50 @@ Editline::NextLineCommand (int ch) unsigned char Editline::FixIndentationCommand (int ch) { - if (!m_fix_indentation_callback) + if (!m_fix_indentation_callback) return CC_NORM; - - // Insert the character by hand prior to correction + + // Insert the character typed before proceeding EditLineCharType inserted[] = { (EditLineCharType)ch, 0 }; el_winsertstr (m_editline, inserted); - SaveEditedLine(); - StringList lines = GetInputAsStringList (m_current_line_index + 1); - - // Determine the cursor position 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); - - // Adjust the input buffer to correct indentation + + // 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) { - info->cursor = info->buffer; - el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str()); + currentLine = currentLine.insert (0, indent_correction, ' '); } - else if (indent_correction < 0) + else { - info->cursor = info->buffer - indent_correction; - el_wdeletestr (m_editline, -indent_correction); + currentLine = currentLine.erase (0, -indent_correction); } - info->cursor = info->buffer + cursor_position + indent_correction; - return CC_REFRESH; +#if LLDB_EDITLINE_USE_WCHAR + m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine); +#else + 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; } unsigned char diff --git a/contrib/llvm/tools/lldb/source/Host/common/File.cpp b/contrib/llvm/tools/lldb/source/Host/common/File.cpp index a3420bff65f5..71a6149cd614 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/File.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/File.cpp @@ -22,6 +22,8 @@ #include <sys/ioctl.h> #endif +#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() + #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -143,7 +145,13 @@ File::GetDescriptor() const // Don't open the file descriptor if we don't need to, just get it from the // stream if we have one. if (StreamIsValid()) - return fileno (m_stream); + { +#if defined(LLVM_ON_WIN32) + return _fileno(m_stream); +#else + return fileno(m_stream); +#endif + } // Invalid descriptor and invalid stream, return invalid descriptor. return kInvalidDescriptor; @@ -1045,7 +1053,11 @@ File::CalculateInteractiveAndTerminal () 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 @@ -1068,3 +1080,11 @@ File::GetIsRealTerminal () return m_is_real_terminal == eLazyBoolYes; } +bool +File::GetIsTerminalWithColors () +{ + if (m_supports_colors == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_supports_colors == eLazyBoolYes; +} + diff --git a/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp b/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp index ceb094b9ede7..8885a791d88c 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp @@ -107,7 +107,7 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl<char> &path) return; llvm::StringRef path_str(path.data(), path.size()); - size_t slash_pos = path_str.find_first_of("/", 1); + 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 @@ -789,6 +789,28 @@ FileSpec::GetFileType () const return eFileTypeInvalid; } +bool +FileSpec::IsSymbolicLink () const +{ + char resolved_path[PATH_MAX]; + if (!GetPath (resolved_path, sizeof (resolved_path))) + return false; + +#ifdef _WIN32 + auto attrs = ::GetFileAttributes (resolved_path); + if (attrs == INVALID_FILE_ATTRIBUTES) + return false; + + return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); +#else + struct stat file_stats; + if (::lstat (resolved_path, &file_stats) != 0) + return false; + + return (file_stats.st_mode & S_IFMT) == S_IFLNK; +#endif +} + uint32_t FileSpec::GetPermissions () const { @@ -1409,7 +1431,7 @@ FileSpec::AppendPathComponent(const char *new_path) return; } StreamString stream; - if (m_filename.IsEmpty()) + if (m_filename.IsEmpty() || (m_filename.GetLength() == 1 && m_filename.GetCString()[0] == '.')) stream.Printf("%s/%s", m_directory.GetCString(), new_path); else if (m_directory.IsEmpty()) stream.Printf("%s/%s", m_filename.GetCString(), new_path); diff --git a/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp b/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp new file mode 100644 index 000000000000..7689f36c8154 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp @@ -0,0 +1,473 @@ +#include "lldb/Host/common/GetOptInc.h" + +#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || defined(REPLACE_GETOPT_LONG_ONLY) + +// getopt.cpp +#include <errno.h> +#include <stdlib.h> +#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 */ +#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 */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#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 gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static const char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +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; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +static void pass() {} +#define warnx(a, ...) pass(); + +/* +* Exchange the block from nonopt_start to nonopt_end with the block +* 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; + } + } +} + +/* +* parse_long_options -- +* 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++; + } + 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) { + /* + * 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); + 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; +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 we have "-" do nothing, if "--" we are done. + */ + 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 (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(recargchar, optchar); + optopt = optchar; + return (BADARG); + } + else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +/* +* getopt -- +* Parse argc/argv argument vector. +* +* [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)); +} +#endif + +/* +* getopt_long -- +* 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)); +} +#endif + +/* +* getopt_long_only -- +* 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) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE | FLAG_LONGONLY)); +} +#endif + +#endif diff --git a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp index 94c78a015651..e89f4def478c 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp @@ -143,7 +143,11 @@ private: #endif // __linux__ #ifdef __linux__ +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) +static __thread volatile sig_atomic_t g_usr1_called; +#else static thread_local volatile sig_atomic_t g_usr1_called; +#endif static void SigUsr1Handler (int) @@ -816,8 +820,8 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau #endif const char *tmp_argv[2]; - char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector(); - char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector(); + 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 @@ -825,7 +829,7 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau // variables don't make it into the child process if "argv == NULL"!!! tmp_argv[0] = exe_path; tmp_argv[1] = NULL; - argv = (char * const*)tmp_argv; + argv = const_cast<char * const*>(tmp_argv); } #if !defined (__APPLE__) diff --git a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp index e969e33190eb..0f4324f83dd6 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <thread> @@ -102,7 +103,7 @@ HostInfoBase::GetVendorString() { static std::once_flag g_once_flag; std::call_once(g_once_flag, []() { - g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str()); + g_fields->m_vendor_string = HostInfo::GetArchitecture().GetTriple().getVendorName().str(); }); return g_fields->m_vendor_string; } @@ -306,7 +307,10 @@ HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) 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(); @@ -341,19 +345,9 @@ HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { - file_spec.Clear(); - - const char *tmpdir_cstr = getenv("TMPDIR"); - if (tmpdir_cstr == nullptr) - { - tmpdir_cstr = getenv("TMP"); - if (tmpdir_cstr == nullptr) - tmpdir_cstr = getenv("TEMP"); - } - if (!tmpdir_cstr) - return false; - - file_spec = FileSpec(tmpdir_cstr, false); + 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; } diff --git a/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp b/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp index c26467fa0d79..98f5321ad67f 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp @@ -27,7 +27,7 @@ #endif // Enable extra mutex error checking -#ifdef LLDB_CONFIGURATION_DEBUG +#if 0 // LLDB_CONFIGURATION_DEBUG #define ENABLE_MUTEX_ERROR_CHECKING 1 #include <inttypes.h> #endif diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp index 818d69bdabdc..7d2f4012bf85 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp @@ -436,12 +436,6 @@ NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */) // Default implementation does nothing. } -void -NativeProcessProtocol::Terminate () -{ - // Default implementation does nothing. -} - #ifndef __linux__ // 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. @@ -449,6 +443,7 @@ NativeProcessProtocol::Terminate () Error NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp) { llvm_unreachable("Platform has no NativeProcessProtocol support"); @@ -457,6 +452,7 @@ NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, Error NativeProcessProtocol::Attach (lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp) { llvm_unreachable("Platform has no NativeProcessProtocol support"); diff --git a/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp b/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp index a91e764bfe3b..a9784592a738 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp @@ -16,8 +16,10 @@ using namespace lldb_private; void -OptionParser::Prepare() +OptionParser::Prepare(Mutex::Locker &locker) { + static Mutex g_mutex(Mutex::eMutexTypeNormal); + locker.Lock(g_mutex); #ifdef __GLIBC__ optind = 0; #else diff --git a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp index f7e93c634a12..91a5e37424e6 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp @@ -12,21 +12,16 @@ #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Host/Config.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" - -#ifdef __ANDROID_NDK__ -#include <linux/tcp.h> -#include <bits/error_constants.h> -#include <asm-generic/errno-base.h> -#include <errno.h> -#include <arpa/inet.h> -#endif +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/common/UDPSocket.h" #ifndef LLDB_DISABLE_POSIX +#include "lldb/Host/posix/DomainSocket.h" + #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> @@ -35,6 +30,23 @@ #include <sys/un.h> #endif +#ifdef __linux__ +#include "lldb/Host/linux/AbstractSocket.h" +#endif + +#ifdef __ANDROID_NDK__ +#include <linux/tcp.h> +#include <bits/error_constants.h> +#include <asm-generic/errno-base.h> +#include <errno.h> +#include <arpa/inet.h> +#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) +#include <unistd.h> +#include <sys/syscall.h> +#include <fcntl.h> +#endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC +#endif // __ANDROID_NDK__ + using namespace lldb; using namespace lldb_private; @@ -48,48 +60,8 @@ typedef void * get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = -1; #endif // #if defined(_WIN32) -#ifdef __ANDROID__ -// Android does not have SUN_LEN -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) -#endif -#endif // #ifdef __ANDROID__ - namespace { -NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit) -{ - auto socketType = type; -#ifdef SOCK_CLOEXEC - if (!child_processes_inherit) { - socketType |= SOCK_CLOEXEC; - } -#endif - return ::socket (domain, socketType, protocol); -} - -NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit) -{ -#ifdef SOCK_CLOEXEC - int flags = 0; - if (!child_processes_inherit) { - flags |= SOCK_CLOEXEC; - } - return ::accept4 (sockfd, addr, addrlen, flags); -#else - return ::accept (sockfd, addr, addrlen); -#endif -} - -void SetLastError(Error &error) -{ -#if defined(_WIN32) - error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); -#else - error.SetErrorToErrno(); -#endif -} - bool IsInterrupted() { #if defined(_WIN32) @@ -114,128 +86,84 @@ Socket::~Socket() Close(); } -Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) +std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error) { - // Store the result in a unique_ptr in case we error out, the memory will get correctly freed. - std::unique_ptr<Socket> final_socket; - NativeSocket sock = kInvalidSocketValue; - Error error; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); - if (log) - log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data()); - - 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; - - // Create the socket - sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit); - if (sock == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to - // be the owner. - final_socket.reset(new Socket(sock, ProtocolTcp, true)); - - // Enable local address reuse - final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); + error.Clear(); - if (inet_pton_result <= 0) + std::unique_ptr<Socket> socket_up; + switch (protocol) { - 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 (AF_INET, 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; - } + 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)); +#else + error.SetErrorString("Unix domain sockets are not supported on this platform."); +#endif + break; + case ProtocolUnixAbstract: +#ifdef __linux__ + socket_up.reset(new AbstractSocket(child_processes_inherit, error)); +#else + error.SetErrorString("Abstract domain sockets are not supported on this platform."); +#endif + break; } - if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa))) - { - SetLastError (error); - return error; - } + if (error.Fail()) + socket_up.reset(); - // Keep our TCP packets coming without any delays. - final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = final_socket.release(); - return error; + return socket_up; } -Error Socket::TcpListen( - llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket, - Predicate<uint16_t>* predicate, - int backlog) +Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { - std::unique_ptr<Socket> listen_socket; - NativeSocket listen_sock = kInvalidSocketValue; - Error error; + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - const int protocol = IPPROTO_TCP; - listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit); - if (listen_sock == kInvalidSocketValue) - { - SetLastError (error); + Error error; + std::unique_ptr<Socket> connect_socket(Create(ProtocolTcp, child_processes_inherit, error)); + if (error.Fail()) return error; - } - listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true)); + error = connect_socket->Connect(host_and_port); + if (error.Success()) + socket = connect_socket.release(); - // enable local address reuse - listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); + 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::TcpListen (%s)", host_and_port.data()); + 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; - SocketAddress anyaddr; - if (anyaddr.SetToAnyAddress (family, port)) - { - int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength()); - if (err == -1) - { - SetLastError (error); - return error; - } - - err = ::listen (listen_sock, backlog); - if (err == -1) - { - SetLastError (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 @@ -250,287 +178,77 @@ Error Socket::TcpListen( // another thread in an efficient manor. if (predicate) predicate->SetValue (port, eBroadcastAlways); - socket = listen_socket.release(); } return error; } -Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::string host_str; - std::string port_str; - int32_t port; - if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error)) - return error; - - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - 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<Socket> 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; -#endif - socklen_t accept_addr_len = sizeof accept_addr; - - int sock = Accept (this->GetNativeSocket(), - (struct sockaddr *)&accept_addr, - &accept_addr_len, - child_processes_inherit); - - if (sock == kInvalidSocketValue) - { - SetLastError (error); - break; - } - - bool is_same_addr = true; -#if !(defined(__linux__) || (defined(_WIN32))) - 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; - // Since both sockets have the same descriptor, arbitrarily choose the send - // socket to be the owner. - accepted_socket.reset(new Socket(sock, ProtocolTcp, 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->SetOption (IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = accepted_socket.release(); - return error; - -} - Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) { - std::unique_ptr<Socket> final_send_socket; - std::unique_ptr<Socket> final_recv_socket; - NativeSocket final_send_fd = kInvalidSocketValue; - NativeSocket final_recv_fd = kInvalidSocketValue; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data()); + 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); +} + +Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ 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)) + std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); + if (error.Fail()) 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_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit); - if (final_recv_fd == kInvalidSocketValue) - { - // Socket creation failed... - SetLastError (error); - } - else - { - final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true)); - - // Socket was created, now lets bind to the requested port - SocketAddress addr; - addr.SetToAnyAddress (AF_INET, 0); + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); - if (::bind (final_recv_fd, addr, addr.GetLength()) == -1) - { - // Bind failed... - SetLastError (error); - } - } + return error; +} - assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); +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; - // 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 = NULL; - - ::memset (&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - 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 != NULL; - service_info_ptr = service_info_ptr->ai_next) - { - final_send_fd = ::CreateSocket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, - child_processes_inherit); - - if (final_send_fd != kInvalidSocketValue) - { - final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true)); - final_send_socket->m_udp_send_sockaddr = service_info_ptr; - break; - } - else - continue; - } - - :: freeaddrinfo (service_info_list); - - if (final_send_fd == kInvalidSocketValue) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - send_socket = final_send_socket.release(); - recv_socket = final_recv_socket.release(); - error.Clear(); + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } -Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - std::unique_ptr<Socket> final_socket; - - // Open the socket that was passed in as an option - struct sockaddr_un saddr_un; - int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (fd == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - final_socket.reset(new Socket(fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - - if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) - { - SetLastError (error); + std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixAbstract, child_processes_inherit, error)); + if (error.Fail()) return error; - } - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - struct sockaddr_un saddr_un; - std::unique_ptr<Socket> listen_socket; - std::unique_ptr<Socket> final_socket; - NativeSocket listen_fd = kInvalidSocketValue; - NativeSocket socket_fd = kInvalidSocketValue; - - listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (listen_fd == kInvalidSocketValue) - { - SetLastError (error); + std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixAbstract,child_processes_inherit, error)); + if (error.Fail()) return error; - } - - listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - FileSystem::Unlink(FileSpec{name, true}); - bool success = false; - if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) - { - if (::listen (listen_fd, 5) == 0) - { - socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit); - if (socket_fd > 0) - { - final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true)); - success = true; - } - } - } - - if (!success) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - // We are done with the listen port - listen_socket.reset(); - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } @@ -605,7 +323,7 @@ Error Socket::Read (void *buf, size_t &num_bytes) else num_bytes = bytes_received; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION)); + 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)", @@ -626,17 +344,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) int bytes_sent = 0; do { - if (m_protocol == ProtocolUdp) - { - bytes_sent = ::sendto (m_socket, - static_cast<const char*>(buf), - num_bytes, - 0, - m_udp_send_sockaddr, - m_udp_send_sockaddr.GetLength()); - } - else - bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); + bytes_sent = Send(buf, num_bytes); } while (bytes_sent < 0 && IsInterrupted ()); if (bytes_sent < 0) @@ -647,7 +355,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) else num_bytes = bytes_sent; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); + 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)", @@ -698,70 +406,84 @@ 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); + 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)); + return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) +size_t Socket::Send(const void *buf, const size_t num_bytes) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; + return ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); } -// Return the port number that is being used by the socket. -uint16_t Socket::GetLocalPortNumber() const +void Socket::SetLastError(Error &error) { - return GetLocalPortNumber (m_socket); +#if defined(_WIN32) + error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); +#else + error.SetErrorToErrno(); +#endif } -std::string Socket::GetLocalIPAddress () const +NativeSocket +Socket::CreateSocket(const int domain, + const int type, + const int protocol, + bool child_processes_inherit, + Error& error) { - // 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 ""; -} + error.Clear(); + auto socketType = type; +#ifdef SOCK_CLOEXEC + if (!child_processes_inherit) + socketType |= SOCK_CLOEXEC; +#endif + auto sock = ::socket (domain, socketType, protocol); + if (sock == kInvalidSocketValue) + SetLastError(error); -uint16_t Socket::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; + return sock; } -std::string Socket::GetRemoteIPAddress () const +NativeSocket +Socket::AcceptSocket(NativeSocket sockfd, + struct sockaddr *addr, + socklen_t *addrlen, + bool child_processes_inherit, + Error& error) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) + 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) { - 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 (); + 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; } - return ""; +#if defined(__NetBSD__) + NativeSocket fd = ::paccept (sockfd, addr, addrlen, nullptr, flags); +#else + NativeSocket fd = ::accept4 (sockfd, addr, addrlen, flags); +#endif +#else + NativeSocket fd = ::accept (sockfd, addr, addrlen); +#endif + if (fd == kInvalidSocketValue) + SetLastError(error); + return fd; } - - diff --git a/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp b/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp index 3ab6cfeec4a0..c8b1687c378e 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp @@ -304,8 +304,10 @@ SocketAddress::getaddrinfo (const char *host, *this = service_info_list; result = IsValid (); } - - :: freeaddrinfo (service_info_list); + + if (service_info_list) + ::freeaddrinfo(service_info_list); + return result; } diff --git a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp index 2b63f46c02e6..60e1dc6bf995 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StreamString.h" @@ -37,8 +38,7 @@ int LocateMacOSXFilesUsingDebugSymbols ( const ModuleSpec &module_spec, - FileSpec *out_exec_fspec, // If non-NULL, try and find the executable - FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file + ModuleSpec &return_module_spec ); #else @@ -47,8 +47,7 @@ int LocateMacOSXFilesUsingDebugSymbols ( const ModuleSpec &module_spec, - FileSpec *out_exec_fspec, // If non-NULL, try and find the executable - FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file + ModuleSpec &return_module_spec ) { // Cannot find MacOSX files using debug symbols on non MacOSX. return 0; @@ -79,6 +78,7 @@ FileAtPathContainsArchAndUUID (const FileSpec &file_fspec, const ArchSpec *arch, 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) { @@ -88,6 +88,17 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym // 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); @@ -99,6 +110,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym 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 @@ -118,6 +133,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym 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 @@ -154,22 +173,28 @@ LocateExecutableSymbolFileDsym (const ModuleSpec &module_spec) "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>", arch ? arch->GetArchitectureName() : "<NULL>", - (void*)uuid); + (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, NULL, &symbol_fspec); + LocateMacOSXFilesUsingDebugSymbols (module_spec, dsym_module_spec); } - return symbol_fspec; + else + { + dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; + } + return dsym_module_spec.GetSymbolFileSpec(); } -FileSpec +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(); @@ -177,28 +202,31 @@ Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>", arch ? arch->GetArchitectureName() : "<NULL>", - (void*)uuid); + (const void*)uuid); - FileSpec objfile_fspec; 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)) { - objfile_fspec = exec_fspec; + result.GetFileSpec() = exec_fspec; } else { - LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL); + LocateMacOSXFilesUsingDebugSymbols (module_spec, result); } - return objfile_fspec; + return result; } FileSpec Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) { - const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString(); + 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()); @@ -210,8 +238,10 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) // 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)); +#endif // LLVM_ON_WIN32 std::string uuid_str; const UUID &module_uuid = module_spec.GetUUID(); @@ -224,10 +254,6 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) uuid_str = uuid_str + ".debug"; } - // Get directory of our module. Needed to check debug files like this: - // /usr/lib/debug/usr/lib/library.so.debug - std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString(); - size_t num_directories = debug_file_search_paths.GetSize(); for (size_t idx = 0; idx < num_directories; ++idx) { @@ -242,7 +268,11 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) files.push_back (dirname + "/" + symbol_filename); files.push_back (dirname + "/.debug/" + symbol_filename); files.push_back (dirname + "/.build-id/" + uuid_str); - files.push_back (dirname + module_directory + "/" + symbol_filename); + + // 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) diff --git a/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp new file mode 100644 index 000000000000..b23055ee7d87 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp @@ -0,0 +1,288 @@ +//===-- TcpSocket.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/TCPSocket.h" + +#include "lldb/Core/Log.h" +#include "lldb/Host/Config.h" + +#ifndef LLDB_DISABLE_POSIX +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <sys/socket.h> +#endif + +using namespace lldb; +using namespace lldb_private; + +namespace { + +const int kDomain = AF_INET; +const int kType = SOCK_STREAM; + +} + +TCPSocket::TCPSocket(NativeSocket socket, bool 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) +{ +} + + +// 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; +} + +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; +} + +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; + + // Enable local address reuse + SetOptionReuseAddress(); + + 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; + } + } + + 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; + + // enable local address reuse + SetOptionReuseAddress(); + + 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; + + 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); + + 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); + + if (err == -1) + SetLastError (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; + } + } + + 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; +#endif + socklen_t accept_addr_len = sizeof accept_addr; + + int sock = AcceptSocket (GetNativeSocket(), + (struct sockaddr *)&accept_addr, + &accept_addr_len, + child_processes_inherit, + error); + + if (error.Fail()) + break; + + bool is_same_addr = true; +#if !(defined(__linux__) || (defined(_WIN32))) + 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 (!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::SetOptionReuseAddress() +{ + return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); +} diff --git a/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp b/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp index 289ec780e9fb..763701441c1a 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp @@ -37,7 +37,7 @@ ThisThread::SetName(llvm::StringRef name, int 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.find_last_of("."); + std::string::size_type last_dot = truncated_name.rfind('.'); if (last_dot != std::string::npos) begin = last_dot + 1; diff --git a/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp new file mode 100644 index 000000000000..8297232ae723 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp @@ -0,0 +1,158 @@ +//===-- UdpSocket.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/UDPSocket.h" + +#include "lldb/Core/Log.h" +#include "lldb/Host/Config.h" + +#ifndef LLDB_DISABLE_POSIX +#include <arpa/inet.h> +#include <sys/socket.h> +#endif + +#include <memory> + +using namespace lldb; +using namespace lldb_private; + +namespace { + +const int kDomain = AF_INET; +const int kType = SOCK_DGRAM; + +const Error kNotSupported("Not supported"); + +} + +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)) +{ +} + +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 kNotSupported; +} + +Error +UDPSocket::Listen(llvm::StringRef name, int backlog) +{ + return kNotSupported; +} + +Error +UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + return kNotSupported; +} + +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); + } + } + + 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; + } + + 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/contrib/llvm/tools/lldb/source/Host/common/XML.cpp b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp index 14e786ab8b16..dc9cb0bc5a33 100644 --- a/contrib/llvm/tools/lldb/source/Host/common/XML.cpp +++ b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp @@ -329,7 +329,7 @@ XMLNode::ForEachSiblingElementWithName (const char *name, NodeCallback const &ca else { if (node->name) - continue; // nullptr name specified and this elemnt has a name, ignore this one + continue; // nullptr name specified and this element has a name, ignore this one } if (callback(XMLNode(node)) == false) @@ -592,7 +592,7 @@ ApplePropertyList::ExtractStringFromValueNode (const XMLNode &node, std::string if (element_name == "true" || element_name == "false") { // The text value _is_ the element name itself... - value = std::move(element_name.str()); + value = element_name.str(); return true; } else if (element_name == "dict" || element_name == "array") @@ -689,5 +689,3 @@ ApplePropertyList::GetStructuredData() #endif return root_sp; } - - |