diff options
Diffstat (limited to 'source/Utility')
-rw-r--r-- | source/Utility/ArchSpec.cpp | 44 | ||||
-rw-r--r-- | source/Utility/Args.cpp | 57 | ||||
-rw-r--r-- | source/Utility/Broadcaster.cpp | 11 | ||||
-rw-r--r-- | source/Utility/CompletionRequest.cpp | 57 | ||||
-rw-r--r-- | source/Utility/ConstString.cpp | 17 | ||||
-rw-r--r-- | source/Utility/DataExtractor.cpp | 37 | ||||
-rw-r--r-- | source/Utility/FileCollector.cpp | 182 | ||||
-rw-r--r-- | source/Utility/FileSpec.cpp | 8 | ||||
-rw-r--r-- | source/Utility/GDBRemote.cpp | 105 | ||||
-rw-r--r-- | source/Utility/JSON.cpp | 550 | ||||
-rw-r--r-- | source/Utility/Listener.cpp | 69 | ||||
-rw-r--r-- | source/Utility/Log.cpp | 39 | ||||
-rw-r--r-- | source/Utility/Logging.cpp | 10 | ||||
-rw-r--r-- | source/Utility/ProcessInfo.cpp | 95 | ||||
-rw-r--r-- | source/Utility/RegularExpression.cpp | 168 | ||||
-rw-r--r-- | source/Utility/Reproducer.cpp | 85 | ||||
-rw-r--r-- | source/Utility/Scalar.cpp | 45 | ||||
-rw-r--r-- | source/Utility/SelectHelper.cpp | 4 | ||||
-rw-r--r-- | source/Utility/StreamGDBRemote.cpp | 45 | ||||
-rw-r--r-- | source/Utility/StringExtractor.cpp | 28 | ||||
-rw-r--r-- | source/Utility/StringLexer.cpp | 2 | ||||
-rw-r--r-- | source/Utility/StringList.cpp | 36 | ||||
-rw-r--r-- | source/Utility/StructuredData.cpp | 244 |
23 files changed, 537 insertions, 1401 deletions
diff --git a/source/Utility/ArchSpec.cpp b/source/Utility/ArchSpec.cpp index 81b87fff88d4b..40cc4a092b0d8 100644 --- a/source/Utility/ArchSpec.cpp +++ b/source/Utility/ArchSpec.cpp @@ -101,6 +101,8 @@ static const CoreDefinition g_core_definitions[] = { ArchSpec::eCore_arm_arm64, "arm64"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_armv8, "armv8"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::aarch64_32, + ArchSpec::eCore_arm_arm64_32, "arm64_32"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64, "aarch64"}, @@ -214,6 +216,7 @@ static const CoreDefinition g_core_definitions[] = { ArchSpec::eCore_uknownMach32, "unknown-mach-32"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::UnknownArch, ArchSpec::eCore_uknownMach64, "unknown-mach-64"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arc, ArchSpec::eCore_arc, "arc"} }; // Ensure that we have an entry in the g_core_definitions for each core. If you @@ -243,19 +246,9 @@ void ArchSpec::ListSupportedArchNames(StringList &list) { list.AppendString(g_core_definitions[i].name); } -size_t ArchSpec::AutoComplete(CompletionRequest &request) { - if (!request.GetCursorArgumentPrefix().empty()) { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { - if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, - request.GetCursorArgumentPrefix())) - request.AddCompletion(g_core_definitions[i].name); - } - } else { - StringList matches; - ListSupportedArchNames(matches); - request.AddCompletions(matches); - } - return request.GetNumberOfMatches(); +void ArchSpec::AutoComplete(CompletionRequest &request) { + for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) + request.TryCompleteCurrentArg(g_core_definitions[i].name); } #define CPU_ANY (UINT32_MAX) @@ -306,6 +299,10 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = { SUBTYPE_MASK}, {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 13, UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 0, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 1, + UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, CPU_ANY, UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_thumb, llvm::MachO::CPU_TYPE_ARM, 0, UINT32_MAX, @@ -446,6 +443,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r6el {ArchSpec::eCore_hexagon_generic, llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // HEXAGON + {ArchSpec::eCore_arc, llvm::ELF::EM_ARC_COMPACT2, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARC }; static const ArchDefinition g_elf_arch_def = { @@ -469,7 +468,9 @@ static const ArchDefinitionEntry g_coff_arch_entries[] = { {ArchSpec::eCore_thumb, llvm::COFF::IMAGE_FILE_MACHINE_THUMB, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARMv7 {ArchSpec::eCore_x86_64_x86_64, llvm::COFF::IMAGE_FILE_MACHINE_AMD64, - LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} // AMD64 + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // AMD64 + {ArchSpec::eCore_arm_arm64, llvm::COFF::IMAGE_FILE_MACHINE_ARM64, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} // ARM64 }; static const ArchDefinition g_coff_arch_def = { @@ -760,6 +761,7 @@ bool ArchSpec::CharIsSignedByDefault() const { return true; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: case llvm::Triple::arm: case llvm::Triple::armeb: @@ -946,8 +948,10 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, } } else { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Unable to find a core definition for cpu 0x%" PRIx32 " sub %" PRId32, cpu, sub); + LLDB_LOGF(log, + "Unable to find a core definition for cpu 0x%" PRIx32 + " sub %" PRId32, + cpu, sub); } } CoreUpdated(update_triple); @@ -1245,6 +1249,14 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, } break; + case ArchSpec::eCore_arm_arm64_32: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + try_inverse = false; + } + break; + case ArchSpec::eCore_mips32: if (!enforce_exact_match) { if (core2 >= ArchSpec::kCore_mips32_first && diff --git a/source/Utility/Args.cpp b/source/Utility/Args.cpp index 77b0d43254a16..9fcc833ce432b 100644 --- a/source/Utility/Args.cpp +++ b/source/Utility/Args.cpp @@ -163,7 +163,6 @@ Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) { ::memcpy(data(), str.data() ? str.data() : "", size); ptr[size] = 0; - ref = llvm::StringRef(c_str(), size); } // Args constructor @@ -172,8 +171,8 @@ Args::Args(llvm::StringRef command) { SetCommandString(command); } Args::Args(const Args &rhs) { *this = rhs; } Args::Args(const StringList &list) : Args() { - for (size_t i = 0; i < list.GetSize(); ++i) - AppendArgument(list[i]); + for (const std::string &arg : list) + AppendArgument(arg); } Args &Args::operator=(const Args &rhs) { @@ -182,7 +181,7 @@ Args &Args::operator=(const Args &rhs) { m_argv.clear(); m_entries.clear(); for (auto &entry : rhs.m_entries) { - m_entries.emplace_back(entry.ref, entry.quote); + m_entries.emplace_back(entry.ref(), entry.quote); m_argv.push_back(m_entries.back().data()); } m_argv.push_back(nullptr); @@ -199,7 +198,7 @@ void Args::Dump(Stream &s, const char *label_name) const { int i = 0; for (auto &entry : m_entries) { s.Indent(); - s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref); + s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref()); } s.Format("{0}[{1}]=NULL\n", label_name, i); s.EOL(); @@ -211,7 +210,7 @@ bool Args::GetCommandString(std::string &command) const { for (size_t i = 0; i < m_entries.size(); ++i) { if (i > 0) command += ' '; - command += m_entries[i].ref; + command += m_entries[i].ref(); } return !m_entries.empty(); @@ -226,10 +225,10 @@ bool Args::GetQuotedCommandString(std::string &command) const { if (m_entries[i].quote) { command += m_entries[i].quote; - command += m_entries[i].ref; + command += m_entries[i].ref(); command += m_entries[i].quote; } else { - command += m_entries[i].ref; + command += m_entries[i].ref(); } } @@ -260,12 +259,6 @@ const char *Args::GetArgumentAtIndex(size_t idx) const { return nullptr; } -char Args::GetArgumentQuoteCharAtIndex(size_t idx) const { - if (idx < m_entries.size()) - return m_entries[idx].quote; - return '\0'; -} - char **Args::GetArgumentVector() { assert(!m_argv.empty()); // TODO: functions like execve and posix_spawnp exhibit undefined behavior @@ -299,7 +292,7 @@ void Args::AppendArguments(const Args &rhs) { assert(m_argv.back() == nullptr); m_argv.pop_back(); for (auto &entry : rhs.m_entries) { - m_entries.emplace_back(entry.ref, entry.quote); + m_entries.emplace_back(entry.ref(), entry.quote); m_argv.push_back(m_entries.back().data()); } m_argv.push_back(nullptr); @@ -342,15 +335,8 @@ void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str, if (idx >= m_entries.size()) return; - if (arg_str.size() > m_entries[idx].ref.size()) { - m_entries[idx] = ArgEntry(arg_str, quote_char); - m_argv[idx] = m_entries[idx].data(); - } else { - const char *src_data = arg_str.data() ? arg_str.data() : ""; - ::memcpy(m_entries[idx].data(), src_data, arg_str.size()); - m_entries[idx].ptr[arg_str.size()] = 0; - m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size()); - } + m_entries[idx] = ArgEntry(arg_str, quote_char); + m_argv[idx] = m_entries[idx].data(); } void Args::DeleteArgumentAtIndex(size_t idx) { @@ -388,29 +374,6 @@ void Args::Clear() { m_argv.push_back(nullptr); } -const char *Args::StripSpaces(std::string &s, bool leading, bool trailing, - bool return_null_if_empty) { - static const char *k_white_space = " \t\v"; - if (!s.empty()) { - if (leading) { - size_t pos = s.find_first_not_of(k_white_space); - if (pos == std::string::npos) - s.clear(); - else if (pos > 0) - s.erase(0, pos); - } - - if (trailing) { - size_t rpos = s.find_last_not_of(k_white_space); - if (rpos != std::string::npos && rpos + 1 < s.size()) - s.erase(rpos + 1); - } - } - if (return_null_if_empty && s.empty()) - return nullptr; - return s.c_str(); -} - const char *Args::GetShellSafeArgument(const FileSpec &shell, const char *unsafe_arg, std::string &safe_arg) { diff --git a/source/Utility/Broadcaster.cpp b/source/Utility/Broadcaster.cpp index 597888cfa0e2e..148fdf7ba5b1e 100644 --- a/source/Utility/Broadcaster.cpp +++ b/source/Utility/Broadcaster.cpp @@ -214,11 +214,12 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, if (Log *log = lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)) { StreamString event_description; event_sp->Dump(&event_description); - log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " - "unique =%i) hijack = %p", - static_cast<void *>(this), GetBroadcasterName(), - event_description.GetData(), unique, - static_cast<void *>(hijacking_listener_sp.get())); + LLDB_LOGF(log, + "%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " + "unique =%i) hijack = %p", + static_cast<void *>(this), GetBroadcasterName(), + event_description.GetData(), unique, + static_cast<void *>(hijacking_listener_sp.get())); } if (hijacking_listener_sp) { diff --git a/source/Utility/CompletionRequest.cpp b/source/Utility/CompletionRequest.cpp index c62ec4f56ffa9..3b5a4570e3242 100644 --- a/source/Utility/CompletionRequest.cpp +++ b/source/Utility/CompletionRequest.cpp @@ -13,46 +13,32 @@ using namespace lldb_private; CompletionRequest::CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, - int match_start_point, - int max_return_elements, CompletionResult &result) : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos), - m_match_start_point(match_start_point), - m_max_return_elements(max_return_elements), m_result(result) { + m_result(result) { + assert(raw_cursor_pos <= command_line.size() && "Out of bounds cursor?"); // We parse the argument up to the cursor, so the last argument in // parsed_line is the one containing the cursor, and the cursor is after the // last character. - m_parsed_line = Args(command_line); - m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos)); + llvm::StringRef partial_command(command_line.substr(0, raw_cursor_pos)); + m_parsed_line = Args(partial_command); - m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1; - - if (m_cursor_index == -1) + if (GetParsedLine().GetArgumentCount() == 0) { + m_cursor_index = 0; m_cursor_char_position = 0; - else + } else { + m_cursor_index = GetParsedLine().GetArgumentCount() - 1U; m_cursor_char_position = - strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index)); - - const char *cursor = command_line.data() + raw_cursor_pos; - if (raw_cursor_pos > 0 && cursor[-1] == ' ') { - // We are just after a space. If we are in an argument, then we will - // continue parsing, but if we are between arguments, then we have to - // complete whatever the next element would be. We can distinguish the two - // cases because if we are in an argument (e.g. because the space is - // protected by a quote) then the space will also be in the parsed - // argument... - - const char *current_elem = - m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index); - if (m_cursor_char_position == 0 || - current_elem[m_cursor_char_position - 1] != ' ') { - m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(), - '\0'); - m_cursor_index++; - m_cursor_char_position = 0; - } + strlen(GetParsedLine().GetArgumentAtIndex(m_cursor_index)); } + + // The cursor is after a space but the space is not part of the argument. + // Let's add an empty fake argument to the end to make sure the completion + // code. Note: The space could be part of the last argument when it's quoted. + if (partial_command.endswith(" ") && + !GetCursorArgumentPrefix().endswith(" ")) + AppendEmptyArgument(); } std::string CompletionResult::Completion::GetUniqueKey() const { @@ -66,13 +52,16 @@ std::string CompletionResult::Completion::GetUniqueKey() const { std::string result; result.append(std::to_string(m_completion.size())); result.append(m_completion); + result.append(std::to_string(static_cast<int>(m_mode))); + result.append(":"); result.append(m_descripton); return result; } void CompletionResult::AddResult(llvm::StringRef completion, - llvm::StringRef description) { - Completion r(completion, description); + llvm::StringRef description, + CompletionMode mode) { + Completion r(completion, description, mode); // Add the completion if we haven't seen the same value before. if (m_added_values.insert(r.GetUniqueKey()).second) @@ -82,11 +71,11 @@ void CompletionResult::AddResult(llvm::StringRef completion, void CompletionResult::GetMatches(StringList &matches) const { matches.Clear(); for (const Completion &completion : m_results) - matches.AppendString(completion.m_completion); + matches.AppendString(completion.GetCompletion()); } void CompletionResult::GetDescriptions(StringList &descriptions) const { descriptions.Clear(); for (const Completion &completion : m_results) - descriptions.AppendString(completion.m_descripton); + descriptions.AppendString(completion.GetDescription()); } diff --git a/source/Utility/ConstString.cpp b/source/Utility/ConstString.cpp index 46b7ab259383e..2516ecf6a9897 100644 --- a/source/Utility/ConstString.cpp +++ b/source/Utility/ConstString.cpp @@ -59,23 +59,6 @@ public: return nullptr; } - bool SetMangledCounterparts(const char *key_ccstr, const char *value_ccstr) { - if (key_ccstr != nullptr && value_ccstr != nullptr) { - { - const uint8_t h = hash(llvm::StringRef(key_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData(key_ccstr).setValue(value_ccstr); - } - { - const uint8_t h = hash(llvm::StringRef(value_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData(value_ccstr).setValue(key_ccstr); - } - return true; - } - return false; - } - const char *GetConstCString(const char *cstr) { if (cstr != nullptr) return GetConstCStringWithLength(cstr, strlen(cstr)); diff --git a/source/Utility/DataExtractor.cpp b/source/Utility/DataExtractor.cpp index 79a1f75d737c1..f642a8fc76392 100644 --- a/source/Utility/DataExtractor.cpp +++ b/source/Utility/DataExtractor.cpp @@ -816,26 +816,25 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len, // non-zero and there aren't enough available bytes, nullptr will be returned // and "offset_ptr" will not be updated. const char *DataExtractor::GetCStr(offset_t *offset_ptr) const { - const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1)); - if (cstr) { - const char *cstr_end = cstr; - const char *end = reinterpret_cast<const char *>(m_end); - while (cstr_end < end && *cstr_end) - ++cstr_end; - - // Now we are either at the end of the data or we point to the - // NULL C string terminator with cstr_end... - if (*cstr_end == '\0') { - // Advance the offset with one extra byte for the NULL terminator - *offset_ptr += (cstr_end - cstr + 1); - return cstr; - } + const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1)); + // Already at the end of the data. + if (!start) + return nullptr; - // We reached the end of the data without finding a NULL C string - // terminator. Fall through and return nullptr otherwise anyone that would - // have used the result as a C string can wander into unknown memory... - } - return nullptr; + const char *end = reinterpret_cast<const char *>(m_end); + + // Check all bytes for a null terminator that terminates a C string. + const char *terminator_or_end = std::find(start, end, '\0'); + + // We didn't find a null terminator, so return nullptr to indicate that there + // is no valid C string at that offset. + if (terminator_or_end == end) + return nullptr; + + // Update offset_ptr for the caller to point to the data behind the + // terminator (which is 1 byte long). + *offset_ptr += (terminator_or_end - start + 1UL); + return start; } // Extracts a NULL terminated C string from the fixed length field of length diff --git a/source/Utility/FileCollector.cpp b/source/Utility/FileCollector.cpp deleted file mode 100644 index ed93591922056..0000000000000 --- a/source/Utility/FileCollector.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//===-- FileCollector.cpp ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/FileCollector.h" - -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Process.h" - -using namespace lldb_private; -using namespace llvm; - -static bool IsCaseSensitivePath(StringRef path) { - SmallString<256> tmp_dest = path, upper_dest, real_dest; - - // Remove component traversals, links, etc. - if (!sys::fs::real_path(path, tmp_dest)) - return true; // Current default value in vfs.yaml - path = tmp_dest; - - // Change path to all upper case and ask for its real path, if the latter - // exists and is equal to path, it's not case sensitive. Default to case - // sensitive in the absence of real_path, since this is the YAMLVFSWriter - // default. - upper_dest = path.upper(); - if (sys::fs::real_path(upper_dest, real_dest) && path.equals(real_dest)) - return false; - return true; -} - -FileCollector::FileCollector(const FileSpec &root, const FileSpec &overlay_root) - : m_root(root), m_overlay_root(overlay_root) { - sys::fs::create_directories(m_root.GetPath(), true); -} - -bool FileCollector::GetRealPath(StringRef src_path, - SmallVectorImpl<char> &result) { - SmallString<256> real_path; - StringRef FileName = sys::path::filename(src_path); - std::string directory = sys::path::parent_path(src_path).str(); - auto dir_with_symlink = m_symlink_map.find(directory); - - // Use real_path to fix any symbolic link component present in a path. - // Computing the real path is expensive, cache the search through the - // parent path directory. - if (dir_with_symlink == m_symlink_map.end()) { - auto ec = sys::fs::real_path(directory, real_path); - if (ec) - return false; - m_symlink_map[directory] = real_path.str(); - } else { - real_path = dir_with_symlink->second; - } - - sys::path::append(real_path, FileName); - result.swap(real_path); - return true; -} - -void FileCollector::AddFile(const Twine &file) { - std::lock_guard<std::mutex> lock(m_mutex); - std::string file_str = file.str(); - if (MarkAsSeen(file_str)) - AddFileImpl(file_str); -} - -void FileCollector::AddFileImpl(StringRef src_path) { - std::string root = m_root.GetPath(); - - // We need an absolute src path to append to the root. - SmallString<256> absolute_src = src_path; - sys::fs::make_absolute(absolute_src); - - // Canonicalize src to a native path to avoid mixed separator styles. - sys::path::native(absolute_src); - - // Remove redundant leading "./" pieces and consecutive separators. - absolute_src = sys::path::remove_leading_dotslash(absolute_src); - - // Canonicalize the source path by removing "..", "." components. - SmallString<256> virtual_path = absolute_src; - sys::path::remove_dots(virtual_path, /*remove_dot_dot=*/true); - - // If a ".." component is present after a symlink component, remove_dots may - // lead to the wrong real destination path. Let the source be canonicalized - // like that but make sure we always use the real path for the destination. - SmallString<256> copy_from; - if (!GetRealPath(absolute_src, copy_from)) - copy_from = virtual_path; - - SmallString<256> dst_path = StringRef(root); - sys::path::append(dst_path, sys::path::relative_path(copy_from)); - - // Always map a canonical src path to its real path into the YAML, by doing - // this we map different virtual src paths to the same entry in the VFS - // overlay, which is a way to emulate symlink inside the VFS; this is also - // needed for correctness, not doing that can lead to module redefinition - // errors. - AddFileToMapping(virtual_path, dst_path); -} - -/// Set the access and modification time for the given file from the given -/// status object. -static std::error_code -CopyAccessAndModificationTime(StringRef filename, - const sys::fs::file_status &stat) { - int fd; - - if (auto ec = - sys::fs::openFileForWrite(filename, fd, sys::fs::CD_OpenExisting)) - return ec; - - if (auto ec = sys::fs::setLastAccessAndModificationTime( - fd, stat.getLastAccessedTime(), stat.getLastModificationTime())) - return ec; - - if (auto ec = sys::Process::SafelyCloseFileDescriptor(fd)) - return ec; - - return {}; -} - -std::error_code FileCollector::CopyFiles(bool stop_on_error) { - for (auto &entry : m_vfs_writer.getMappings()) { - // Create directory tree. - if (std::error_code ec = - sys::fs::create_directories(sys::path::parent_path(entry.RPath), - /*IgnoreExisting=*/true)) { - if (stop_on_error) - return ec; - } - - // Copy file over. - if (std::error_code ec = sys::fs::copy_file(entry.VPath, entry.RPath)) { - if (stop_on_error) - return ec; - } - - // Copy over permissions. - if (auto perms = sys::fs::getPermissions(entry.VPath)) { - if (std::error_code ec = sys::fs::setPermissions(entry.RPath, *perms)) { - if (stop_on_error) - return ec; - } - } - - // Copy over modification time. - sys::fs::file_status stat; - if (std::error_code ec = sys::fs::status(entry.VPath, stat)) { - if (stop_on_error) - return ec; - continue; - } - CopyAccessAndModificationTime(entry.RPath, stat); - } - return {}; -} - -std::error_code FileCollector::WriteMapping(const FileSpec &mapping_file) { - std::lock_guard<std::mutex> lock(m_mutex); - - std::string root = m_overlay_root.GetPath(); - - m_vfs_writer.setOverlayDir(root); - m_vfs_writer.setCaseSensitivity(IsCaseSensitivePath(root)); - m_vfs_writer.setUseExternalNames(false); - - std::error_code ec; - raw_fd_ostream os(mapping_file.GetPath(), ec, sys::fs::F_Text); - if (ec) - return ec; - - m_vfs_writer.write(os); - - return {}; -} diff --git a/source/Utility/FileSpec.cpp b/source/Utility/FileSpec.cpp index 35d22404b9480..f22ab4d84e40a 100644 --- a/source/Utility/FileSpec.cpp +++ b/source/Utility/FileSpec.cpp @@ -72,8 +72,8 @@ FileSpec::FileSpec(llvm::StringRef path, Style style) : m_style(style) { SetFile(path, style); } -FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &Triple) - : FileSpec{path, Triple.isOSWindows() ? Style::windows : Style::posix} {} +FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &triple) + : FileSpec{path, triple.isOSWindows() ? Style::windows : Style::posix} {} // Copy constructor FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() { @@ -228,8 +228,8 @@ void FileSpec::SetFile(llvm::StringRef pathname, Style style) { m_directory.SetString(directory); } -void FileSpec::SetFile(llvm::StringRef path, const llvm::Triple &Triple) { - return SetFile(path, Triple.isOSWindows() ? Style::windows : Style::posix); +void FileSpec::SetFile(llvm::StringRef path, const llvm::Triple &triple) { + return SetFile(path, triple.isOSWindows() ? Style::windows : Style::posix); } // Convert to pointer operator. This allows code to check any FileSpec objects diff --git a/source/Utility/GDBRemote.cpp b/source/Utility/GDBRemote.cpp new file mode 100644 index 0000000000000..85c4bc69a8d10 --- /dev/null +++ b/source/Utility/GDBRemote.cpp @@ -0,0 +1,105 @@ +//===-- GDBRemote.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/GDBRemote.h" + +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/Stream.h" + +#include <stdio.h> + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +StreamGDBRemote::StreamGDBRemote() : StreamString() {} + +StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, + ByteOrder byte_order) + : StreamString(flags, addr_size, byte_order) {} + +StreamGDBRemote::~StreamGDBRemote() {} + +int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) { + int bytes_written = 0; + const uint8_t *src = static_cast<const uint8_t *>(s); + bool binary_is_set = m_flags.Test(eBinary); + m_flags.Clear(eBinary); + while (src_len) { + uint8_t byte = *src; + src++; + src_len--; + if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) { + bytes_written += PutChar(0x7d); + byte ^= 0x20; + } + bytes_written += PutChar(byte); + }; + if (binary_is_set) + m_flags.Set(eBinary); + return bytes_written; +} + +void GDBRemotePacket::Serialize(raw_ostream &strm) const { + yaml::Output yout(strm); + yout << const_cast<GDBRemotePacket &>(*this); + strm.flush(); +} + +llvm::StringRef GDBRemotePacket::GetTypeStr() const { + switch (type) { + case GDBRemotePacket::ePacketTypeSend: + return "send"; + case GDBRemotePacket::ePacketTypeRecv: + return "read"; + case GDBRemotePacket::ePacketTypeInvalid: + return "invalid"; + } + llvm_unreachable("All enum cases should be handled"); +} + +void GDBRemotePacket::Dump(Stream &strm) const { + strm.Printf("tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", tid, + bytes_transmitted, GetTypeStr().data(), packet.data.c_str()); +} + +void yaml::ScalarEnumerationTraits<GDBRemotePacket::Type>::enumeration( + IO &io, GDBRemotePacket::Type &value) { + io.enumCase(value, "Invalid", GDBRemotePacket::ePacketTypeInvalid); + io.enumCase(value, "Send", GDBRemotePacket::ePacketTypeSend); + io.enumCase(value, "Recv", GDBRemotePacket::ePacketTypeRecv); +} + +void yaml::ScalarTraits<GDBRemotePacket::BinaryData>::output( + const GDBRemotePacket::BinaryData &Val, void *, raw_ostream &Out) { + Out << toHex(Val.data); +} + +StringRef yaml::ScalarTraits<GDBRemotePacket::BinaryData>::input( + StringRef Scalar, void *, GDBRemotePacket::BinaryData &Val) { + Val.data = fromHex(Scalar); + return {}; +} + +void yaml::MappingTraits<GDBRemotePacket>::mapping(IO &io, + GDBRemotePacket &Packet) { + io.mapRequired("packet", Packet.packet); + io.mapRequired("type", Packet.type); + io.mapRequired("bytes", Packet.bytes_transmitted); + io.mapRequired("index", Packet.packet_idx); + io.mapRequired("tid", Packet.tid); +} + +StringRef +yaml::MappingTraits<GDBRemotePacket>::validate(IO &io, + GDBRemotePacket &Packet) { + if (Packet.bytes_transmitted != Packet.packet.data.size()) + return "BinaryData size doesn't match bytes transmitted"; + + return {}; +} diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp deleted file mode 100644 index 2c3f6229eda11..0000000000000 --- a/source/Utility/JSON.cpp +++ /dev/null @@ -1,550 +0,0 @@ -//===--------------------- JSON.cpp -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/JSON.h" - -#include "lldb/Utility/Stream.h" -#include "lldb/Utility/StreamString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ErrorHandling.h" - -#include <inttypes.h> -#include <limits.h> -#include <stddef.h> -#include <utility> - -using namespace lldb_private; - -std::string JSONString::json_string_quote_metachars(const std::string &s) { - if (s.find_first_of("\\\n\"") == std::string::npos) - return s; - - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); - for (size_t i = 0; i < s_size; i++) { - unsigned char ch = *(s_chars + i); - if (ch == '"' || ch == '\\' || ch == '\n') { - output.push_back('\\'); - if (ch == '\n') ch = 'n'; - } - output.push_back(ch); - } - return output; -} - -JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} - -JSONString::JSONString(const char *s) - : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {} - -JSONString::JSONString(const std::string &s) - : JSONValue(JSONValue::Kind::String), m_data(s) {} - -void JSONString::Write(Stream &s) { - s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str()); -} - -uint64_t JSONNumber::GetAsUnsigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return m_data.m_unsigned; - case DataType::Signed: - return static_cast<uint64_t>(m_data.m_signed); - case DataType::Double: - return static_cast<uint64_t>(m_data.m_double); - } - llvm_unreachable("Unhandled data type"); -} - -int64_t JSONNumber::GetAsSigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return static_cast<int64_t>(m_data.m_unsigned); - case DataType::Signed: - return m_data.m_signed; - case DataType::Double: - return static_cast<int64_t>(m_data.m_double); - } - llvm_unreachable("Unhandled data type"); -} - -double JSONNumber::GetAsDouble() const { - switch (m_data_type) { - case DataType::Unsigned: - return static_cast<double>(m_data.m_unsigned); - case DataType::Signed: - return static_cast<double>(m_data.m_signed); - case DataType::Double: - return m_data.m_double; - } - llvm_unreachable("Unhandled data type"); -} - -void JSONNumber::Write(Stream &s) { - switch (m_data_type) { - case DataType::Unsigned: - s.Printf("%" PRIu64, m_data.m_unsigned); - break; - case DataType::Signed: - s.Printf("%" PRId64, m_data.m_signed); - break; - case DataType::Double: - s.Printf("%g", m_data.m_double); - break; - } -} - -JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} - -void JSONTrue::Write(Stream &s) { s.Printf("true"); } - -JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} - -void JSONFalse::Write(Stream &s) { s.Printf("false"); } - -JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} - -void JSONNull::Write(Stream &s) { s.Printf("null"); } - -JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} - -void JSONObject::Write(Stream &s) { - bool first = true; - s.PutChar('{'); - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s.PutChar(','); - JSONString key(iter->first); - JSONValue::SP value(iter->second); - key.Write(s); - s.PutChar(':'); - value->Write(s); - } - s.PutChar('}'); -} - -bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) { - if (key.empty() || nullptr == value.get()) - return false; - m_elements[key] = value; - return true; -} - -JSONValue::SP JSONObject::GetObject(const std::string &key) { - auto iter = m_elements.find(key), end = m_elements.end(); - if (iter == end) - return JSONValue::SP(); - return iter->second; -} - -JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {} - -void JSONArray::Write(Stream &s) { - bool first = true; - s.PutChar('['); - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s.PutChar(','); - (*iter)->Write(s); - } - s.PutChar(']'); -} - -bool JSONArray::SetObject(Index i, JSONValue::SP value) { - if (value.get() == nullptr) - return false; - if (i < m_elements.size()) { - m_elements[i] = value; - return true; - } - if (i == m_elements.size()) { - m_elements.push_back(value); - return true; - } - return false; -} - -bool JSONArray::AppendObject(JSONValue::SP value) { - if (value.get() == nullptr) - return false; - m_elements.push_back(value); - return true; -} - -JSONValue::SP JSONArray::GetObject(Index i) { - if (i < m_elements.size()) - return m_elements[i]; - return JSONValue::SP(); -} - -JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); } - -JSONParser::JSONParser(llvm::StringRef data) : StringExtractor(data) {} - -JSONParser::Token JSONParser::GetToken(std::string &value) { - StreamString error; - - value.clear(); - SkipSpaces(); - const uint64_t start_index = m_index; - const char ch = GetChar(); - switch (ch) { - case '{': - return Token::ObjectStart; - case '}': - return Token::ObjectEnd; - case '[': - return Token::ArrayStart; - case ']': - return Token::ArrayEnd; - case ',': - return Token::Comma; - case ':': - return Token::Colon; - case '\0': - return Token::EndOfFile; - case 't': - if (GetChar() == 'r') - if (GetChar() == 'u') - if (GetChar() == 'e') - return Token::True; - break; - - case 'f': - if (GetChar() == 'a') - if (GetChar() == 'l') - if (GetChar() == 's') - if (GetChar() == 'e') - return Token::False; - break; - - case 'n': - if (GetChar() == 'u') - if (GetChar() == 'l') - if (GetChar() == 'l') - return Token::Null; - break; - - case '"': { - while (true) { - bool was_escaped = false; - int escaped_ch = GetEscapedChar(was_escaped); - if (escaped_ch == -1) { - error.Printf( - "error: an error occurred getting a character from offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - - } else { - const bool is_end_quote = escaped_ch == '"'; - const bool is_null = escaped_ch == 0; - if (was_escaped || (!is_end_quote && !is_null)) { - if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) { - value.append(1, static_cast<char>(escaped_ch)); - } else { - error.Printf("error: wide character support is needed for unicode " - "character 0x%4.4x at offset %" PRIu64, - escaped_ch, start_index); - value = std::move(error.GetString()); - return Token::Status; - } - } else if (is_end_quote) { - return Token::String; - } else if (is_null) { - value = "error: missing end quote for string"; - return Token::Status; - } - } - } - } break; - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - bool done = false; - bool got_decimal_point = false; - uint64_t exp_index = 0; - bool got_int_digits = (ch >= '0') && (ch <= '9'); - bool got_frac_digits = false; - bool got_exp_digits = false; - while (!done) { - const char next_ch = PeekChar(); - switch (next_ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (exp_index != 0) { - got_exp_digits = true; - } else if (got_decimal_point) { - got_frac_digits = true; - } else { - got_int_digits = true; - } - ++m_index; // Skip this character - break; - - case '.': - if (got_decimal_point) { - error.Printf("error: extra decimal point found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } else { - got_decimal_point = true; - ++m_index; // Skip this character - } - break; - - case 'e': - case 'E': - if (exp_index != 0) { - error.Printf( - "error: extra exponent character found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } else { - exp_index = m_index; - ++m_index; // Skip this character - } - break; - - case '+': - case '-': - // The '+' and '-' can only come after an exponent character... - if (exp_index == m_index - 1) { - ++m_index; // Skip the exponent sign character - } else { - error.Printf("error: unexpected %c character at offset %" PRIu64, - next_ch, start_index); - value = std::move(error.GetString()); - return Token::Status; - } - break; - - default: - done = true; - break; - } - } - - if (m_index > start_index) { - value = m_packet.substr(start_index, m_index - start_index); - if (got_decimal_point) { - if (exp_index != 0) { - // We have an exponent, make sure we got exponent digits - if (got_exp_digits) { - return Token::Float; - } else { - error.Printf("error: got exponent character but no exponent digits " - "at offset in float value \"%s\"", - value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } else { - // No exponent, but we need at least one decimal after the decimal - // point - if (got_frac_digits) { - return Token::Float; - } else { - error.Printf("error: no digits after decimal point \"%s\"", - value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } - } else { - // No decimal point - if (got_int_digits) { - // We need at least some integer digits to make an integer - return Token::Integer; - } else { - error.Printf("error: no digits negate sign \"%s\"", value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } - } else { - error.Printf("error: invalid number found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } - } break; - default: - break; - } - error.Printf("error: failed to parse token at offset %" PRIu64 - " (around character '%c')", - start_index, ch); - value = std::move(error.GetString()); - return Token::Status; -} - -int JSONParser::GetEscapedChar(bool &was_escaped) { - was_escaped = false; - const char ch = GetChar(); - if (ch == '\\') { - was_escaped = true; - const char ch2 = GetChar(); - switch (ch2) { - case '"': - case '\\': - case '/': - default: - break; - - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'u': { - const int hi_byte = DecodeHexU8(); - const int lo_byte = DecodeHexU8(); - if (hi_byte >= 0 && lo_byte >= 0) - return hi_byte << 8 | lo_byte; - return -1; - } break; - } - return ch2; - } - return ch; -} - -JSONValue::SP JSONParser::ParseJSONObject() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - std::unique_ptr<JSONObject> dict_up(new JSONObject()); - - std::string value; - std::string key; - while (true) { - JSONParser::Token token = GetToken(value); - - if (token == JSONParser::Token::String) { - key.swap(value); - token = GetToken(value); - if (token == JSONParser::Token::Colon) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - dict_up->SetObject(key, value_sp); - else - break; - } - } else if (token == JSONParser::Token::ObjectEnd) { - return JSONValue::SP(dict_up.release()); - } else if (token == JSONParser::Token::Comma) { - continue; - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONArray() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - std::unique_ptr<JSONArray> array_up(new JSONArray()); - - std::string value; - std::string key; - while (true) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - array_up->AppendObject(value_sp); - else - break; - - JSONParser::Token token = GetToken(value); - if (token == JSONParser::Token::Comma) { - continue; - } else if (token == JSONParser::Token::ArrayEnd) { - return JSONValue::SP(array_up.release()); - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONValue() { - std::string value; - const JSONParser::Token token = GetToken(value); - switch (token) { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(); - - case JSONParser::Token::Integer: { - if (value.front() == '-') { - int64_t sval = 0; - if (!llvm::StringRef(value).getAsInteger(0, sval)) - return JSONValue::SP(new JSONNumber(sval)); - } else { - uint64_t uval = 0; - if (!llvm::StringRef(value).getAsInteger(0, uval)) - return JSONValue::SP(new JSONNumber(uval)); - } - } break; - - case JSONParser::Token::Float: { - double D; - if (!llvm::StringRef(value).getAsDouble(D)) - return JSONValue::SP(new JSONNumber(D)); - } break; - - case JSONParser::Token::String: - return JSONValue::SP(new JSONString(value)); - - case JSONParser::Token::True: - return JSONValue::SP(new JSONTrue()); - - case JSONParser::Token::False: - return JSONValue::SP(new JSONFalse()); - - case JSONParser::Token::Null: - return JSONValue::SP(new JSONNull()); - - default: - break; - } - return JSONValue::SP(); -} diff --git a/source/Utility/Listener.cpp b/source/Utility/Listener.cpp index 50c56406c2ca5..c2e537ba7dee0 100644 --- a/source/Utility/Listener.cpp +++ b/source/Utility/Listener.cpp @@ -42,8 +42,8 @@ Listener::Listener(const char *name) m_events_mutex() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log != nullptr) - log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this), - m_name.c_str()); + LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this), + m_name.c_str()); } Listener::~Listener() { @@ -51,9 +51,8 @@ Listener::~Listener() { Clear(); - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), - __FUNCTION__, m_name.c_str()); + LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } void Listener::Clear() { @@ -78,9 +77,8 @@ void Listener::Clear() { manager_sp->RemoveListener(this); } - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), - __FUNCTION__, m_name.c_str()); + LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, @@ -101,10 +99,11 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", - static_cast<void *>(this), static_cast<void *>(broadcaster), - event_mask, acquired_mask, m_name.c_str()); + LLDB_LOGF(log, + "%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, acquired_mask, m_name.c_str()); return acquired_mask; } @@ -132,12 +131,13 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) { void **pointer = reinterpret_cast<void **>(&callback); - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x, callback = %p, user_data = %p) " - "acquired_mask = 0x%8.8x for %s", - static_cast<void *>(this), static_cast<void *>(broadcaster), - event_mask, *pointer, static_cast<void *>(callback_user_data), - acquired_mask, m_name.c_str()); + LLDB_LOGF(log, + "%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x, callback = %p, user_data = %p) " + "acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, *pointer, static_cast<void *>(callback_user_data), + acquired_mask, m_name.c_str()); } return acquired_mask; @@ -202,9 +202,9 @@ void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { void Listener::AddEvent(EventSP &event_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) - log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", - static_cast<void *>(this), m_name.c_str(), - static_cast<void *>(event_sp.get())); + LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})", + static_cast<void *>(this), m_name.c_str(), + static_cast<void *>(event_sp.get())); std::lock_guard<std::mutex> guard(m_events_mutex); m_events.push_back(event_sp); @@ -290,14 +290,15 @@ bool Listener::FindNextEventInternal( event_sp = *pos; if (log != nullptr) - log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " - "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " - "remove=%i) event %p", - static_cast<void *>(this), GetName(), - static_cast<void *>(broadcaster), - static_cast<const void *>(broadcaster_names), - num_broadcaster_names, event_type_mask, remove, - static_cast<void *>(event_sp.get())); + LLDB_LOGF(log, + "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " + "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " + "remove=%i) event %p", + static_cast<void *>(this), GetName(), + static_cast<void *>(broadcaster), + static_cast<const void *>(broadcaster_names), + num_broadcaster_names, event_type_mask, remove, + static_cast<void *>(event_sp.get())); if (remove) { m_events.erase(pos); @@ -366,15 +367,13 @@ bool Listener::GetEventInternal( if (result == std::cv_status::timeout) { log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() timed out for %s", - static_cast<void *>(this), m_name.c_str()); + LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s", + static_cast<void *>(this), m_name.c_str()); return false; } else if (result != std::cv_status::no_timeout) { log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() unknown error for %s", - static_cast<void *>(this), m_name.c_str()); + LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s", + static_cast<void *>(this), m_name.c_str()); return false; } } diff --git a/source/Utility/Log.cpp b/source/Utility/Log.cpp index 217b0d2ba97b1..ab5e630114a6b 100644 --- a/source/Utility/Log.cpp +++ b/source/Utility/Log.cpp @@ -9,7 +9,6 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/VASPrintf.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator.h" @@ -38,13 +37,22 @@ using namespace lldb_private; llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map; -void Log::ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry) { - stream << llvm::formatv("Logging categories for '{0}':\n", entry.first()); - stream << " all - all available logging categories\n"; - stream << " default - default set of logging categories\n"; +void Log::ForEachCategory( + const Log::ChannelMap::value_type &entry, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) { + lambda("all", "all available logging categories"); + lambda("default", "default set of logging categories"); for (const auto &category : entry.second.m_channel.categories) - stream << llvm::formatv(" {0} - {1}\n", category.name, - category.description); + lambda(category.name, category.description); +} + +void Log::ListCategories(llvm::raw_ostream &stream, + const ChannelMap::value_type &entry) { + stream << llvm::formatv("Logging categories for '{0}':\n", entry.first()); + ForEachCategory(entry, + [&stream](llvm::StringRef name, llvm::StringRef description) { + stream << llvm::formatv(" {0} - {1}\n", name, description); + }); } uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, @@ -237,6 +245,23 @@ void Log::DisableAllLogChannels() { entry.second.Disable(UINT32_MAX); } +void Log::ForEachChannelCategory( + llvm::StringRef channel, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) { + auto ch = g_channel_map->find(channel); + if (ch == g_channel_map->end()) + return; + + ForEachCategory(*ch, lambda); +} + +std::vector<llvm::StringRef> Log::ListChannels() { + std::vector<llvm::StringRef> result; + for (const auto &channel : *g_channel_map) + result.push_back(channel.first()); + return result; +} + void Log::ListAllLogChannels(llvm::raw_ostream &stream) { if (g_channel_map->empty()) { stream << "No logging channels are currently registered.\n"; diff --git a/source/Utility/Logging.cpp b/source/Utility/Logging.cpp index c0856e5d9267d..22f38192fa5d1 100644 --- a/source/Utility/Logging.cpp +++ b/source/Utility/Logging.cpp @@ -62,13 +62,3 @@ Log *lldb_private::GetLogIfAllCategoriesSet(uint32_t mask) { Log *lldb_private::GetLogIfAnyCategoriesSet(uint32_t mask) { return g_log_channel.GetLogIfAny(mask); } - - -void lldb_private::LogIfAnyCategoriesSet(uint32_t mask, const char *format, ...) { - if (Log *log = GetLogIfAnyCategoriesSet(mask)) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } -} diff --git a/source/Utility/ProcessInfo.cpp b/source/Utility/ProcessInfo.cpp index b67ae87790006..5743d223be4fa 100644 --- a/source/Utility/ProcessInfo.cpp +++ b/source/Utility/ProcessInfo.cpp @@ -42,8 +42,8 @@ const char *ProcessInfo::GetName() const { return m_executable.GetFilename().GetCString(); } -size_t ProcessInfo::GetNameLength() const { - return m_executable.GetFilename().GetLength(); +llvm::StringRef ProcessInfo::GetNameAsStringRef() const { + return m_executable.GetFilename().GetStringRef(); } void ProcessInfo::Dump(Stream &s, Platform *platform) const { @@ -169,13 +169,15 @@ void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args, if (verbose) { s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE " - " %s\n", + " %s\n", label); - s.PutCString("====== ====== ========== ========== ========== ========== " - "======================== ============================\n"); + s.PutCString( + "====== ====== ========== ========== ========== ========== " + "============================== ============================\n"); } else { - s.Printf("PID PARENT USER TRIPLE %s\n", label); - s.PutCString("====== ====== ========== ======================== " + s.Printf("PID PARENT USER TRIPLE %s\n", + label); + s.PutCString("====== ====== ========== ============================== " "============================\n"); } } @@ -189,34 +191,47 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, if (m_arch.IsValid()) m_arch.DumpTriple(arch_strm); - auto print = [&](UserIDResolver::id_t id, - llvm::Optional<llvm::StringRef> (UserIDResolver::*get)( + auto print = [&](bool (ProcessInstanceInfo::*isValid)() const, + uint32_t (ProcessInstanceInfo::*getID)() const, + llvm::Optional<llvm::StringRef> (UserIDResolver::*getName)( UserIDResolver::id_t id)) { - if (auto name = (resolver.*get)(id)) - s.Format("{0,-10} ", *name); + const char *format = "{0,-10} "; + if (!(this->*isValid)()) { + s.Format(format, ""); + return; + } + uint32_t id = (this->*getID)(); + if (auto name = (resolver.*getName)(id)) + s.Format(format, *name); else - s.Format("{0,-10} ", id); + s.Format(format, id); }; if (verbose) { - print(m_uid, &UserIDResolver::GetUserName); - print(m_gid, &UserIDResolver::GetGroupName); - print(m_euid, &UserIDResolver::GetUserName); - print(m_egid, &UserIDResolver::GetGroupName); - - s.Printf("%-24s ", arch_strm.GetData()); + print(&ProcessInstanceInfo::UserIDIsValid, + &ProcessInstanceInfo::GetUserID, &UserIDResolver::GetUserName); + print(&ProcessInstanceInfo::GroupIDIsValid, + &ProcessInstanceInfo::GetGroupID, &UserIDResolver::GetGroupName); + print(&ProcessInstanceInfo::EffectiveUserIDIsValid, + &ProcessInstanceInfo::GetEffectiveUserID, + &UserIDResolver::GetUserName); + print(&ProcessInstanceInfo::EffectiveGroupIDIsValid, + &ProcessInstanceInfo::GetEffectiveGroupID, + &UserIDResolver::GetGroupName); + + s.Printf("%-30s ", arch_strm.GetData()); } else { - print(m_euid, &UserIDResolver::GetUserName); - s.Printf(" %-24s ", arch_strm.GetData()); + print(&ProcessInstanceInfo::EffectiveUserIDIsValid, + &ProcessInstanceInfo::GetEffectiveUserID, + &UserIDResolver::GetUserName); + s.Printf("%-30s ", arch_strm.GetData()); } if (verbose || show_args) { + s.PutCString(m_arg0); const uint32_t argc = m_arguments.GetArgumentCount(); - if (argc > 0) { - for (uint32_t i = 0; i < argc; i++) { - if (i > 0) - s.PutChar(' '); - s.PutCString(m_arguments.GetArgumentAtIndex(i)); - } + for (uint32_t i = 0; i < argc; i++) { + s.PutChar(' '); + s.PutCString(m_arguments.GetArgumentAtIndex(i)); } } else { s.PutCString(GetName()); @@ -226,8 +241,14 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, } } +bool ProcessInstanceInfoMatch::ArchitectureMatches( + const ArchSpec &arch_spec) const { + return !m_match_info.GetArchitecture().IsValid() || + m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec); +} + bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { - if (m_name_match_type == NameMatch::Ignore || process_name == nullptr) + if (m_name_match_type == NameMatch::Ignore) return true; const char *match_name = m_match_info.GetName(); if (!match_name) @@ -236,11 +257,8 @@ bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { return lldb_private::NameMatches(process_name, m_name_match_type, match_name); } -bool ProcessInstanceInfoMatch::Matches( +bool ProcessInstanceInfoMatch::ProcessIDsMatch( const ProcessInstanceInfo &proc_info) const { - if (!NameMatches(proc_info.GetName())) - return false; - if (m_match_info.ProcessIDIsValid() && m_match_info.GetProcessID() != proc_info.GetProcessID()) return false; @@ -248,7 +266,11 @@ bool ProcessInstanceInfoMatch::Matches( if (m_match_info.ParentProcessIDIsValid() && m_match_info.GetParentProcessID() != proc_info.GetParentProcessID()) return false; + return true; +} +bool ProcessInstanceInfoMatch::UserIDsMatch( + const ProcessInstanceInfo &proc_info) const { if (m_match_info.UserIDIsValid() && m_match_info.GetUserID() != proc_info.GetUserID()) return false; @@ -264,13 +286,14 @@ bool ProcessInstanceInfoMatch::Matches( if (m_match_info.EffectiveGroupIDIsValid() && m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID()) return false; - - if (m_match_info.GetArchitecture().IsValid() && - !m_match_info.GetArchitecture().IsCompatibleMatch( - proc_info.GetArchitecture())) - return false; return true; } +bool ProcessInstanceInfoMatch::Matches( + const ProcessInstanceInfo &proc_info) const { + return ArchitectureMatches(proc_info.GetArchitecture()) && + ProcessIDsMatch(proc_info) && UserIDsMatch(proc_info) && + NameMatches(proc_info.GetName()); +} bool ProcessInstanceInfoMatch::MatchAllProcesses() const { if (m_name_match_type != NameMatch::Ignore) diff --git a/source/Utility/RegularExpression.cpp b/source/Utility/RegularExpression.cpp index 0192e8b8a01a0..fd9d963f7294c 100644 --- a/source/Utility/RegularExpression.cpp +++ b/source/Utility/RegularExpression.cpp @@ -8,168 +8,34 @@ #include "lldb/Utility/RegularExpression.h" -#include "llvm/ADT/StringRef.h" - #include <string> -// Enable enhanced mode if it is available. This allows for things like \d for -// digit, \s for space, and many more, but it isn't available everywhere. -#if defined(REG_ENHANCED) -#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED) -#else -#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) -#endif - using namespace lldb_private; -RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() { - memset(&m_preg, 0, sizeof(m_preg)); -} - -// Constructor that compiles "re" using "flags" and stores the resulting -// compiled regular expression into this object. RegularExpression::RegularExpression(llvm::StringRef str) - : RegularExpression() { - Compile(str); -} + : m_regex_text(str), + // m_regex does not reference str anymore after it is constructed. + m_regex(llvm::Regex(str)) {} RegularExpression::RegularExpression(const RegularExpression &rhs) - : RegularExpression() { - Compile(rhs.GetText()); -} - -const RegularExpression &RegularExpression:: -operator=(const RegularExpression &rhs) { - if (&rhs != this) - Compile(rhs.GetText()); - return *this; -} - -// Destructor -// -// Any previously compiled regular expression contained in this object will be -// freed. -RegularExpression::~RegularExpression() { Free(); } - -// Compile a regular expression using the supplied regular expression text and -// flags. The compiled regular expression lives in this object so that it can -// be readily used for regular expression matches. Execute() can be called -// after the regular expression is compiled. Any previously compiled regular -// expression contained in this object will be freed. -// -// RETURNS -// True if the regular expression compiles successfully, false -// otherwise. -bool RegularExpression::Compile(llvm::StringRef str) { - Free(); - - // regcomp() on darwin does not recognize "" as a valid regular expression, - // so we substitute it with an equivalent non-empty one. - m_re = str.empty() ? "()" : str; - m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS); - return m_comp_err == 0; -} + : RegularExpression(rhs.GetText()) {} -// Execute a regular expression match using the compiled regular expression -// that is already in this object against the match string "s". If any parens -// are used for regular expression matches "match_count" should indicate the -// number of regmatch_t values that are present in "match_ptr". The regular -// expression will be executed using the "execute_flags". -bool RegularExpression::Execute(llvm::StringRef str, Match *match) const { - int err = 1; - if (m_comp_err == 0) { - // Argument to regexec must be null-terminated. - std::string reg_str = str; - if (match) { - err = ::regexec(&m_preg, reg_str.c_str(), match->GetSize(), - match->GetData(), 0); - } else { - err = ::regexec(&m_preg, reg_str.c_str(), 0, nullptr, 0); - } - } - - if (err != 0) { - // The regular expression didn't compile, so clear the matches - if (match) - match->Clear(); +bool RegularExpression::Execute( + llvm::StringRef str, + llvm::SmallVectorImpl<llvm::StringRef> *matches) const { + if (!IsValid()) return false; - } - return true; -} - -bool RegularExpression::Match::GetMatchAtIndex(llvm::StringRef s, uint32_t idx, - std::string &match_str) const { - llvm::StringRef match_str_ref; - if (GetMatchAtIndex(s, idx, match_str_ref)) { - match_str = match_str_ref.str(); - return true; - } - return false; + return m_regex.match(str, matches); } -bool RegularExpression::Match::GetMatchAtIndex( - llvm::StringRef s, uint32_t idx, llvm::StringRef &match_str) const { - if (idx < m_matches.size()) { - if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1) - return false; - - if (m_matches[idx].rm_eo == m_matches[idx].rm_so) { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) { - match_str = s.substr(m_matches[idx].rm_so, - m_matches[idx].rm_eo - m_matches[idx].rm_so); - return true; - } - } - return false; -} - -bool RegularExpression::Match::GetMatchSpanningIndices( - llvm::StringRef s, uint32_t idx1, uint32_t idx2, - llvm::StringRef &match_str) const { - if (idx1 < m_matches.size() && idx2 < m_matches.size()) { - if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) { - match_str = s.substr(m_matches[idx1].rm_so, - m_matches[idx2].rm_eo - m_matches[idx1].rm_so); - return true; - } - } - return false; -} +bool RegularExpression::IsValid() const { return m_regex.isValid(); } -// Returns true if the regular expression compiled and is ready for execution. -bool RegularExpression::IsValid() const { return m_comp_err == 0; } - -// Returns the text that was used to compile the current regular expression. -llvm::StringRef RegularExpression::GetText() const { return m_re; } - -// Free any contained compiled regular expressions. -void RegularExpression::Free() { - if (m_comp_err == 0) { - m_re.clear(); - regfree(&m_preg); - // Set a compile error since we no longer have a valid regex - m_comp_err = 1; - } -} - -size_t RegularExpression::GetErrorAsCString(char *err_str, - size_t err_str_max_len) const { - if (m_comp_err == 0) { - if (err_str && err_str_max_len) - *err_str = '\0'; - return 0; - } - - return ::regerror(m_comp_err, &m_preg, err_str, err_str_max_len); -} +llvm::StringRef RegularExpression::GetText() const { return m_regex_text; } -bool RegularExpression::operator<(const RegularExpression &rhs) const { - return (m_re < rhs.m_re); +llvm::Error RegularExpression::GetError() const { + std::string error; + if (!m_regex.isValid(error)) + return llvm::make_error<llvm::StringError>(llvm::inconvertibleErrorCode(), + error); + return llvm::Error::success(); } diff --git a/source/Utility/Reproducer.cpp b/source/Utility/Reproducer.cpp index 479ed311d1ded..4777d7576a321 100644 --- a/source/Utility/Reproducer.cpp +++ b/source/Utility/Reproducer.cpp @@ -136,7 +136,17 @@ FileSpec Reproducer::GetReproducerPath() const { return {}; } -Generator::Generator(const FileSpec &root) : m_root(root), m_done(false) {} +static FileSpec MakeAbsolute(FileSpec file_spec) { + SmallString<128> path; + file_spec.GetPath(path, false); + llvm::sys::fs::make_absolute(path); + return FileSpec(path, file_spec.GetPathStyle()); +} + +Generator::Generator(FileSpec root) + : m_root(MakeAbsolute(std::move(root))), m_done(false) { + GetOrCreate<repro::WorkingDirectoryProvider>(); +} Generator::~Generator() {} @@ -175,8 +185,8 @@ void Generator::AddProvidersToIndex() { index.AppendPathComponent("index.yaml"); std::error_code EC; - auto strm = llvm::make_unique<raw_fd_ostream>(index.GetPath(), EC, - sys::fs::OpenFlags::F_None); + auto strm = std::make_unique<raw_fd_ostream>(index.GetPath(), EC, + sys::fs::OpenFlags::OF_None); yaml::Output yout(*strm); std::vector<std::string> files; @@ -188,7 +198,8 @@ void Generator::AddProvidersToIndex() { yout << files; } -Loader::Loader(const FileSpec &root) : m_root(root), m_loaded(false) {} +Loader::Loader(FileSpec root) + : m_root(MakeAbsolute(std::move(root))), m_loaded(false) {} llvm::Error Loader::LoadIndex() { if (m_loaded) @@ -223,7 +234,7 @@ bool Loader::HasFile(StringRef file) { llvm::Expected<std::unique_ptr<DataRecorder>> DataRecorder::Create(const FileSpec &filename) { std::error_code ec; - auto recorder = llvm::make_unique<DataRecorder>(std::move(filename), ec); + auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec); if (ec) return llvm::errorCodeToError(ec); return std::move(recorder); @@ -254,7 +265,7 @@ void CommandProvider::Keep() { FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text); + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); if (ec) return; yaml::Output yout(os); @@ -266,20 +277,78 @@ void CommandProvider::Discard() { m_data_recorders.clear(); } void VersionProvider::Keep() { FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text); + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); if (ec) return; os << m_version << "\n"; } +void WorkingDirectoryProvider::Keep() { + FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + os << m_cwd << "\n"; +} + +llvm::raw_ostream *ProcessGDBRemoteProvider::GetHistoryStream() { + FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); + + std::error_code EC; + m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, + sys::fs::OpenFlags::OF_Text); + return m_stream_up.get(); +} + +std::unique_ptr<CommandLoader> CommandLoader::Create(Loader *loader) { + if (!loader) + return {}; + + FileSpec file = loader->GetFile<repro::CommandProvider::Info>(); + if (!file) + return {}; + + auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); + if (auto err = error_or_file.getError()) + return {}; + + std::vector<std::string> files; + llvm::yaml::Input yin((*error_or_file)->getBuffer()); + yin >> files; + + if (auto err = yin.error()) + return {}; + + for (auto &file : files) { + FileSpec absolute_path = + loader->GetRoot().CopyByAppendingPathComponent(file); + file = absolute_path.GetPath(); + } + + return std::make_unique<CommandLoader>(std::move(files)); +} + +llvm::Optional<std::string> CommandLoader::GetNextFile() { + if (m_index >= m_files.size()) + return {}; + return m_files[m_index++]; +} + void ProviderBase::anchor() {} -char ProviderBase::ID = 0; char CommandProvider::ID = 0; char FileProvider::ID = 0; +char ProcessGDBRemoteProvider::ID = 0; +char ProviderBase::ID = 0; char VersionProvider::ID = 0; +char WorkingDirectoryProvider::ID = 0; const char *CommandProvider::Info::file = "command-interpreter.yaml"; const char *CommandProvider::Info::name = "command-interpreter"; const char *FileProvider::Info::file = "files.yaml"; const char *FileProvider::Info::name = "files"; +const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml"; +const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote"; const char *VersionProvider::Info::file = "version.txt"; const char *VersionProvider::Info::name = "version"; +const char *WorkingDirectoryProvider::Info::file = "cwd.txt"; +const char *WorkingDirectoryProvider::Info::name = "cwd"; diff --git a/source/Utility/Scalar.cpp b/source/Utility/Scalar.cpp index 23d50b9eaba50..e9aec17b6650d 100644 --- a/source/Utility/Scalar.cpp +++ b/source/Utility/Scalar.cpp @@ -416,6 +416,51 @@ Scalar &Scalar::operator=(llvm::APInt rhs) { Scalar::~Scalar() = default; +Scalar::Type Scalar::GetBestTypeForBitSize(size_t bit_size, bool sign) { + // Scalar types are always host types, hence the sizeof(). + if (sign) { + if (bit_size <= sizeof(int)*8) return Scalar::e_sint; + if (bit_size <= sizeof(long)*8) return Scalar::e_slong; + if (bit_size <= sizeof(long long)*8) return Scalar::e_slonglong; + if (bit_size <= 128) return Scalar::e_sint128; + if (bit_size <= 256) return Scalar::e_sint256; + if (bit_size <= 512) return Scalar::e_sint512; + } else { + if (bit_size <= sizeof(unsigned int)*8) return Scalar::e_uint; + if (bit_size <= sizeof(unsigned long)*8) return Scalar::e_ulong; + if (bit_size <= sizeof(unsigned long long)*8) return Scalar::e_ulonglong; + if (bit_size <= 128) return Scalar::e_uint128; + if (bit_size <= 256) return Scalar::e_uint256; + if (bit_size <= 512) return Scalar::e_uint512; + } + return Scalar::e_void; +} + +void Scalar::TruncOrExtendTo(Scalar::Type type, uint16_t bits) { + switch (type) { + case e_sint: + case e_slong: + case e_slonglong: + case e_sint128: + case e_sint256: + case e_sint512: + m_integer = m_integer.sextOrTrunc(bits); + break; + case e_uint: + case e_ulong: + case e_ulonglong: + case e_uint128: + case e_uint256: + case e_uint512: + m_integer = m_integer.zextOrTrunc(bits); + break; + default: + llvm_unreachable("Promoting a Scalar to a specific number of bits is only " + "supported for integer types."); + } + m_type = type; +} + bool Scalar::Promote(Scalar::Type type) { bool success = false; switch (m_type) { diff --git a/source/Utility/SelectHelper.cpp b/source/Utility/SelectHelper.cpp index ff21d99e400ab..9f5ca586e1ef9 100644 --- a/source/Utility/SelectHelper.cpp +++ b/source/Utility/SelectHelper.cpp @@ -92,7 +92,7 @@ static void updateMaxFd(llvm::Optional<lldb::socket_t> &vold, lldb_private::Status SelectHelper::Select() { lldb_private::Status error; -#ifdef _MSC_VER +#ifdef _WIN32 // On windows FD_SETSIZE limits the number of file descriptors, not their // numeric value. lldbassert(m_fd_map.size() <= FD_SETSIZE); @@ -107,7 +107,7 @@ lldb_private::Status SelectHelper::Select() { for (auto &pair : m_fd_map) { pair.second.PrepareForSelect(); const lldb::socket_t fd = pair.first; -#if !defined(__APPLE__) && !defined(_MSC_VER) +#if !defined(__APPLE__) && !defined(_WIN32) lldbassert(fd < static_cast<int>(FD_SETSIZE)); if (fd >= static_cast<int>(FD_SETSIZE)) { error.SetErrorStringWithFormat("%i is too large for select()", fd); diff --git a/source/Utility/StreamGDBRemote.cpp b/source/Utility/StreamGDBRemote.cpp deleted file mode 100644 index c710bbe3eecb3..0000000000000 --- a/source/Utility/StreamGDBRemote.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===-- StreamGDBRemote.cpp -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/StreamGDBRemote.h" - -#include "lldb/Utility/Flags.h" -#include "lldb/Utility/Stream.h" - -#include <stdio.h> - -using namespace lldb; -using namespace lldb_private; - -StreamGDBRemote::StreamGDBRemote() : StreamString() {} - -StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, - ByteOrder byte_order) - : StreamString(flags, addr_size, byte_order) {} - -StreamGDBRemote::~StreamGDBRemote() {} - -int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) { - int bytes_written = 0; - const uint8_t *src = static_cast<const uint8_t *>(s); - bool binary_is_set = m_flags.Test(eBinary); - m_flags.Clear(eBinary); - while (src_len) { - uint8_t byte = *src; - src++; - src_len--; - if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) { - bytes_written += PutChar(0x7d); - byte ^= 0x20; - } - bytes_written += PutChar(byte); - }; - if (binary_is_set) - m_flags.Set(eBinary); - return bytes_written; -} diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp index 502f468da3ccc..87fe4f13e450c 100644 --- a/source/Utility/StringExtractor.cpp +++ b/source/Utility/StringExtractor.cpp @@ -296,34 +296,6 @@ size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { return bytes_extracted; } -// Consume ASCII hex nibble character pairs until we have decoded byte_size -// bytes of data. - -uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, - bool little_endian, - uint64_t fail_value) { - if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { - uint64_t result = 0; - uint32_t i; - if (little_endian) { - // Little Endian - uint32_t shift_amount; - for (i = 0, shift_amount = 0; i < byte_size && IsGood(); - ++i, shift_amount += 8) { - result |= (static_cast<uint64_t>(GetHexU8()) << shift_amount); - } - } else { - // Big Endian - for (i = 0; i < byte_size && IsGood(); ++i) { - result <<= 8; - result |= GetHexU8(); - } - } - } - m_index = UINT64_MAX; - return fail_value; -} - size_t StringExtractor::GetHexByteString(std::string &str) { str.clear(); str.reserve(GetBytesLeft() / 2); diff --git a/source/Utility/StringLexer.cpp b/source/Utility/StringLexer.cpp index 958a9580db7ac..c357cb0fb5530 100644 --- a/source/Utility/StringLexer.cpp +++ b/source/Utility/StringLexer.cpp @@ -11,7 +11,7 @@ #include <algorithm> #include <assert.h> -using namespace lldb_utility; +using namespace lldb_private; StringLexer::StringLexer(std::string s) : m_data(s), m_position(0) {} diff --git a/source/Utility/StringList.cpp b/source/Utility/StringList.cpp index fb0d9be8797d4..5e06b6b69fc09 100644 --- a/source/Utility/StringList.cpp +++ b/source/Utility/StringList.cpp @@ -61,10 +61,8 @@ void StringList::AppendList(const char **strv, int strc) { } void StringList::AppendList(StringList strings) { - size_t len = strings.GetSize(); - - for (size_t i = 0; i < len; ++i) - m_strings.push_back(strings.GetStringAtIndex(i)); + m_strings.reserve(m_strings.size() + strings.GetSize()); + m_strings.insert(m_strings.end(), strings.begin(), strings.end()); } size_t StringList::GetSize() const { return m_strings.size(); } @@ -100,10 +98,9 @@ void StringList::Join(const char *separator, Stream &strm) { void StringList::Clear() { m_strings.clear(); } -void StringList::LongestCommonPrefix(std::string &common_prefix) { - common_prefix.clear(); +std::string StringList::LongestCommonPrefix() { if (m_strings.empty()) - return; + return {}; auto args = llvm::makeArrayRef(m_strings); llvm::StringRef prefix = args.front(); @@ -115,7 +112,7 @@ void StringList::LongestCommonPrefix(std::string &common_prefix) { } prefix = prefix.take_front(count); } - common_prefix = prefix; + return prefix.str(); } void StringList::InsertStringAtIndex(size_t idx, const char *str) { @@ -226,29 +223,6 @@ StringList &StringList::operator=(const std::vector<std::string> &rhs) { return *this; } -size_t StringList::AutoComplete(llvm::StringRef s, StringList &matches, - size_t &exact_idx) const { - matches.Clear(); - exact_idx = SIZE_MAX; - if (s.empty()) { - // No string, so it matches everything - matches = *this; - return matches.GetSize(); - } - - const size_t s_len = s.size(); - const size_t num_strings = m_strings.size(); - - for (size_t i = 0; i < num_strings; ++i) { - if (m_strings[i].find(s) == 0) { - if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len) - exact_idx = matches.GetSize(); - matches.AppendString(m_strings[i]); - } - } - return matches.GetSize(); -} - void StringList::LogDump(Log *log, const char *name) { if (!log) return; diff --git a/source/Utility/StructuredData.cpp b/source/Utility/StructuredData.cpp index 0e203f9739d16..783a080821744 100644 --- a/source/Utility/StructuredData.cpp +++ b/source/Utility/StructuredData.cpp @@ -9,9 +9,7 @@ #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/Status.h" -#include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -21,11 +19,20 @@ #include <limits> using namespace lldb_private; +using namespace llvm; -// Functions that use a JSONParser to parse JSON into StructuredData -static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser); +static StructuredData::ObjectSP ParseJSONValue(json::Value &value); +static StructuredData::ObjectSP ParseJSONObject(json::Object *object); +static StructuredData::ObjectSP ParseJSONArray(json::Array *array); + +StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { + llvm::Expected<json::Value> value = json::parse(json_text); + if (!value) { + llvm::consumeError(value.takeError()); + return nullptr; + } + return ParseJSONValue(*value); +} StructuredData::ObjectSP StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { @@ -38,112 +45,53 @@ StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { buffer_or_error.getError().message()); return return_sp; } - - JSONParser json_parser(buffer_or_error.get()->getBuffer()); - return_sp = ParseJSONValue(json_parser); - return return_sp; + return ParseJSON(buffer_or_error.get()->getBuffer().str()); } -static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - auto dict_up = llvm::make_unique<StructuredData::Dictionary>(); +static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { + if (json::Object *O = value.getAsObject()) + return ParseJSONObject(O); - std::string value; - std::string key; - while (true) { - JSONParser::Token token = json_parser.GetToken(value); + if (json::Array *A = value.getAsArray()) + return ParseJSONArray(A); - if (token == JSONParser::Token::String) { - key.swap(value); - token = json_parser.GetToken(value); - if (token == JSONParser::Token::Colon) { - StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); - if (value_sp) - dict_up->AddItem(key, value_sp); - else - break; - } - } else if (token == JSONParser::Token::ObjectEnd) { - return StructuredData::ObjectSP(dict_up.release()); - } else if (token == JSONParser::Token::Comma) { - continue; - } else { - break; - } - } - return StructuredData::ObjectSP(); -} + std::string s; + if (json::fromJSON(value, s)) + return std::make_shared<StructuredData::String>(s); -static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - auto array_up = llvm::make_unique<StructuredData::Array>(); + bool b; + if (json::fromJSON(value, b)) + return std::make_shared<StructuredData::Boolean>(b); - std::string value; - std::string key; - while (true) { - StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); - if (value_sp) - array_up->AddItem(value_sp); - else - break; + int64_t i; + if (json::fromJSON(value, i)) + return std::make_shared<StructuredData::Integer>(i); + + double d; + if (json::fromJSON(value, d)) + return std::make_shared<StructuredData::Float>(d); - JSONParser::Token token = json_parser.GetToken(value); - if (token == JSONParser::Token::Comma) { - continue; - } else if (token == JSONParser::Token::ArrayEnd) { - return StructuredData::ObjectSP(array_up.release()); - } else { - break; - } - } return StructuredData::ObjectSP(); } -static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) { - std::string value; - const JSONParser::Token token = json_parser.GetToken(value); - switch (token) { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(json_parser); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(json_parser); - - case JSONParser::Token::Integer: { - uint64_t uval; - if (llvm::to_integer(value, uval, 0)) - return std::make_shared<StructuredData::Integer>(uval); - } break; - - case JSONParser::Token::Float: { - double val; - if (llvm::to_float(value, val)) - return std::make_shared<StructuredData::Float>(val); - } break; - - case JSONParser::Token::String: - return std::make_shared<StructuredData::String>(value); - - case JSONParser::Token::True: - case JSONParser::Token::False: - return std::make_shared<StructuredData::Boolean>(token == - JSONParser::Token::True); - - case JSONParser::Token::Null: - return std::make_shared<StructuredData::Null>(); - - default: - break; +static StructuredData::ObjectSP ParseJSONObject(json::Object *object) { + auto dict_up = std::make_unique<StructuredData::Dictionary>(); + for (auto &KV : *object) { + StringRef key = KV.first; + json::Value value = KV.second; + if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) + dict_up->AddItem(key, value_sp); } - return StructuredData::ObjectSP(); + return dict_up; } -StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { - JSONParser json_parser(json_text); - StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser); - return object_sp; +static StructuredData::ObjectSP ParseJSONArray(json::Array *array) { + auto array_up = std::make_unique<StructuredData::Array>(); + for (json::Value &value : *array) { + if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) + array_up->AddItem(value_sp); + } + return array_up; } StructuredData::ObjectSP @@ -181,98 +129,48 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { } void StructuredData::Object::DumpToStdout(bool pretty_print) const { - StreamString stream; - Dump(stream, pretty_print); - llvm::outs() << stream.GetString(); + json::OStream stream(llvm::outs(), pretty_print ? 2 : 0); + Serialize(stream); } -void StructuredData::Array::Dump(Stream &s, bool pretty_print) const { - bool first = true; - s << "["; - if (pretty_print) { - s << "\n"; - s.IndentMore(); - } +void StructuredData::Array::Serialize(json::OStream &s) const { + s.arrayBegin(); for (const auto &item_sp : m_items) { - if (first) { - first = false; - } else { - s << ","; - if (pretty_print) - s << "\n"; - } - - if (pretty_print) - s.Indent(); - item_sp->Dump(s, pretty_print); - } - if (pretty_print) { - s.IndentLess(); - s.EOL(); - s.Indent(); + item_sp->Serialize(s); } - s << "]"; + s.arrayEnd(); } -void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const { - s.Printf("%" PRIu64, m_value); +void StructuredData::Integer::Serialize(json::OStream &s) const { + s.value(static_cast<int64_t>(m_value)); } -void StructuredData::Float::Dump(Stream &s, bool pretty_print) const { - s.Printf("%lg", m_value); +void StructuredData::Float::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const { - if (m_value) - s.PutCString("true"); - else - s.PutCString("false"); +void StructuredData::Boolean::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::String::Dump(Stream &s, bool pretty_print) const { - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize; ++i) { - char ch = m_value[i]; - if (ch == '"' || ch == '\\') - quoted.push_back('\\'); - quoted.push_back(ch); - } - s.Printf("\"%s\"", quoted.c_str()); +void StructuredData::String::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const { - bool first = true; - s << "{"; - if (pretty_print) { - s << "\n"; - s.IndentMore(); - } +void StructuredData::Dictionary::Serialize(json::OStream &s) const { + s.objectBegin(); for (const auto &pair : m_dict) { - if (first) - first = false; - else { - s << ","; - if (pretty_print) - s << "\n"; - } - if (pretty_print) - s.Indent(); - s << "\"" << pair.first.AsCString() << "\" : "; - pair.second->Dump(s, pretty_print); - } - if (pretty_print) { - s.IndentLess(); - s.EOL(); - s.Indent(); + s.attributeBegin(pair.first.AsCString()); + pair.second->Serialize(s); + s.attributeEnd(); } - s << "}"; + s.objectEnd(); } -void StructuredData::Null::Dump(Stream &s, bool pretty_print) const { - s << "null"; +void StructuredData::Null::Serialize(json::OStream &s) const { + s.value(nullptr); } -void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const { - s << "0x" << m_object; +void StructuredData::Generic::Serialize(json::OStream &s) const { + s.value(llvm::formatv("{0:X}", m_object)); } |