diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
commit | ead246455adf1a215ec2715dad6533073a6beb4e (patch) | |
tree | f3f97a47d77053bf96fe74cdbd6fae74380e8a92 /include/lldb/Utility | |
parent | fdb00c4408990a0a63ef7f496d809ce59f263bc5 (diff) | |
download | src-ead246455adf1a215ec2715dad6533073a6beb4e.tar.gz src-ead246455adf1a215ec2715dad6533073a6beb4e.zip |
Vendor import of stripped lldb trunk r375505, the last commit before thevendor/lldb/lldb-trunk-r375505vendor/lldb
upstream Subversion repository was made read-only, and the LLVM project
migrated to GitHub:
https://llvm.org/svn/llvm-project/lldb/trunk@375505
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=353952
svn path=/vendor/lldb/lldb-r375505/; revision=353953; tag=vendor/lldb/lldb-trunk-r375505
Diffstat (limited to 'include/lldb/Utility')
31 files changed, 598 insertions, 900 deletions
diff --git a/include/lldb/Utility/AnsiTerminal.h b/include/lldb/Utility/AnsiTerminal.h index 1473c60eeaf2..21375e3821ca 100644 --- a/include/lldb/Utility/AnsiTerminal.h +++ b/include/lldb/Utility/AnsiTerminal.h @@ -55,7 +55,7 @@ #include <string> -namespace lldb_utility { +namespace lldb_private { namespace ansi { @@ -137,4 +137,4 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, return fmt; } } -} +} // namespace lldb_private diff --git a/include/lldb/Utility/ArchSpec.h b/include/lldb/Utility/ArchSpec.h index 7a32556310c4..3bfc988abf0b 100644 --- a/include/lldb/Utility/ArchSpec.h +++ b/include/lldb/Utility/ArchSpec.h @@ -122,6 +122,7 @@ public: eCore_thumbv7em, eCore_arm_arm64, eCore_arm_armv8, + eCore_arm_arm64_32, eCore_arm_aarch64, eCore_mips32, @@ -183,6 +184,8 @@ public: eCore_uknownMach32, eCore_uknownMach64, + eCore_arc, // little endian ARC + kNumCores, kCore_invalid, @@ -268,7 +271,7 @@ public: static bool ContainsOnlyArch(const llvm::Triple &normalized_triple); static void ListSupportedArchNames(StringList &list); - static size_t AutoComplete(CompletionRequest &request); + static void AutoComplete(CompletionRequest &request); /// Returns a static string representing the current architecture. /// diff --git a/include/lldb/Utility/Args.h b/include/lldb/Utility/Args.h index 6f258498d5ba..7987787e7af5 100644 --- a/include/lldb/Utility/Args.h +++ b/include/lldb/Utility/Args.h @@ -35,6 +35,7 @@ public: private: friend class Args; std::unique_ptr<char[]> ptr; + char quote; char *data() { return ptr.get(); } @@ -42,12 +43,12 @@ public: ArgEntry() = default; ArgEntry(llvm::StringRef str, char quote); - llvm::StringRef ref; - char quote; + llvm::StringRef ref() const { return c_str(); } const char *c_str() const { return ptr.get(); } /// Returns true if this argument was quoted in any way. bool IsQuoted() const { return quote != '\0'; } + char GetQuoteChar() const { return quote; } }; /// Construct with an option command string. @@ -121,7 +122,6 @@ public: const char *GetArgumentAtIndex(size_t idx) const; llvm::ArrayRef<ArgEntry> entries() const { return m_entries; } - char GetArgumentQuoteCharAtIndex(size_t idx) const; using const_iterator = std::vector<ArgEntry>::const_iterator; @@ -168,8 +168,8 @@ public: /// Appends a new argument to the end of the list argument list. /// - /// \param[in] arg_cstr - /// The new argument as a NULL terminated C string. + /// \param[in] arg_str + /// The new argument. /// /// \param[in] quote_char /// If the argument was originally quoted, put in the quote char here. @@ -179,30 +179,27 @@ public: void AppendArguments(const char **argv); - /// Insert the argument value at index \a idx to \a arg_cstr. + /// Insert the argument value at index \a idx to \a arg_str. /// /// \param[in] idx /// The index of where to insert the argument. /// - /// \param[in] arg_cstr - /// The new argument as a NULL terminated C string. + /// \param[in] arg_str + /// The new argument. /// /// \param[in] quote_char /// If the argument was originally quoted, put in the quote char here. - /// - /// \return - /// The NULL terminated C string of the copy of \a arg_cstr. void InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str, char quote_char = '\0'); - /// Replaces the argument value at index \a idx to \a arg_cstr if \a idx is + /// Replaces the argument value at index \a idx to \a arg_str if \a idx is /// a valid argument index. /// /// \param[in] idx /// The index of the argument that will have its value replaced. /// - /// \param[in] arg_cstr - /// The new argument as a NULL terminated C string. + /// \param[in] arg_str + /// The new argument. /// /// \param[in] quote_char /// If the argument was originally quoted, put in the quote char here. @@ -238,12 +235,12 @@ public: /// \see Args::GetArgumentAtIndex (size_t) const void Shift(); - /// Inserts a class owned copy of \a arg_cstr at the beginning of the + /// Inserts a class owned copy of \a arg_str at the beginning of the /// argument vector. /// - /// A copy \a arg_cstr will be made. + /// A copy \a arg_str will be made. /// - /// \param[in] arg_cstr + /// \param[in] arg_str /// The argument to push on the front of the argument stack. /// /// \param[in] quote_char @@ -255,10 +252,6 @@ public: // For re-setting or blanking out the list of arguments. void Clear(); - static const char *StripSpaces(std::string &s, bool leading = true, - bool trailing = true, - bool return_null_if_empty = true); - static bool UInt64ValueIsValidForByteSize(uint64_t uval64, size_t total_byte_size) { if (total_byte_size > 8) diff --git a/include/lldb/Utility/CleanUp.h b/include/lldb/Utility/CleanUp.h deleted file mode 100644 index 6cd5f332ef95..000000000000 --- a/include/lldb/Utility/CleanUp.h +++ /dev/null @@ -1,42 +0,0 @@ -//===-- CleanUp.h -----------------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_CleanUp_h_ -#define liblldb_CleanUp_h_ - -#include "lldb/lldb-public.h" -#include <functional> - -namespace lldb_private { - -/// Run a cleanup function on scope exit unless it's explicitly disabled. -class CleanUp { - std::function<void()> Clean; - -public: - /// Register a cleanup function which applies \p Func to a list of arguments. - /// Use caution with arguments which are references: they will be copied. - template <typename F, typename... Args> - CleanUp(F &&Func, Args &&... args) - : Clean(std::bind(std::forward<F>(Func), std::forward<Args>(args)...)) {} - - ~CleanUp() { - if (Clean) - Clean(); - } - - /// Disable the cleanup. - void disable() { Clean = nullptr; } - - // Prevent cleanups from being run more than once. - DISALLOW_COPY_AND_ASSIGN(CleanUp); -}; - -} // namespace lldb_private - -#endif // #ifndef liblldb_CleanUp_h_ diff --git a/include/lldb/Utility/CompletionRequest.h b/include/lldb/Utility/CompletionRequest.h index f5ccb01ca16f..570f626ac54e 100644 --- a/include/lldb/Utility/CompletionRequest.h +++ b/include/lldb/Utility/CompletionRequest.h @@ -16,25 +16,53 @@ #include "llvm/ADT/StringSet.h" namespace lldb_private { +enum class CompletionMode { + // The current token has been completed. + Normal, + // The current token has been partially completed. This means that we found + // a completion, but that the completed token is still incomplete. Examples + // for this are file paths, where we want to complete "/bi" to "/bin/", but + // the file path token is still incomplete after the completion. Clients + // should not indicate to the user that this is a full completion (e.g. by + // not inserting the usual trailing space after a successful completion). + Partial, + // The full line has been rewritten by the completion. + RewriteLine, +}; + class CompletionResult { +public: /// A single completion and all associated data. - struct Completion { - Completion(llvm::StringRef completion, llvm::StringRef description) - : m_completion(completion.str()), m_descripton(description.str()) {} + class Completion { std::string m_completion; std::string m_descripton; + CompletionMode m_mode; + + public: + Completion(llvm::StringRef completion, llvm::StringRef description, + CompletionMode mode) + : m_completion(completion.str()), m_descripton(description.str()), + m_mode(mode) {} + const std::string &GetCompletion() const { return m_completion; } + const std::string &GetDescription() const { return m_descripton; } + CompletionMode GetMode() const { return m_mode; } /// Generates a string that uniquely identifies this completion result. std::string GetUniqueKey() const; }; + +private: std::vector<Completion> m_results; /// List of added completions so far. Used to filter out duplicates. llvm::StringSet<> m_added_values; public: - void AddResult(llvm::StringRef completion, llvm::StringRef description); + void AddResult(llvm::StringRef completion, llvm::StringRef description, + CompletionMode mode); + + llvm::ArrayRef<Completion> GetResults() const { return m_results; } /// Adds all collected completion matches to the given list. /// The list will be cleared before the results are added. The number of @@ -68,18 +96,10 @@ public: /// the cursor is at the start of the line. The completion starts from /// this cursor position. /// - /// \param [in] match_start_point - /// \param [in] max_return_elements - /// If there is a match that is expensive to compute, these are here to - /// allow you to compute the completions in batches. Start the - /// completion from match_start_point, and return match_return_elements - /// elements. - /// /// \param [out] result /// The CompletionResult that will be filled with the results after this /// request has been handled. CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, - int match_start_point, int max_return_elements, CompletionResult &result); llvm::StringRef GetRawLine() const { return m_command; } @@ -90,21 +110,25 @@ public: Args &GetParsedLine() { return m_parsed_line; } - const Args &GetPartialParsedLine() const { return m_partial_parsed_line; } - - void SetCursorIndex(int i) { m_cursor_index = i; } - int GetCursorIndex() const { return m_cursor_index; } - - void SetCursorCharPosition(int pos) { m_cursor_char_position = pos; } - int GetCursorCharPosition() const { return m_cursor_char_position; } - - int GetMatchStartPoint() const { return m_match_start_point; } + const Args::ArgEntry &GetParsedArg() { + return GetParsedLine()[GetCursorIndex()]; + } - int GetMaxReturnElements() const { return m_max_return_elements; } + /// Drops the first argument from the argument list. + void ShiftArguments() { + m_cursor_index--; + m_parsed_line.Shift(); + } - bool GetWordComplete() { return m_word_complete; } + /// Adds an empty argument at the end of the argument list and moves + /// the cursor to this new argument. + void AppendEmptyArgument() { + m_parsed_line.AppendArgument(llvm::StringRef()); + m_cursor_index++; + m_cursor_char_position = 0; + } - void SetWordComplete(bool v) { m_word_complete = v; } + size_t GetCursorIndex() const { return m_cursor_index; } /// Adds a possible completion string. If the completion was already /// suggested before, it will not be added to the list of results. A copy of @@ -112,11 +136,31 @@ public: /// afterwards. /// /// \param match The suggested completion. - /// \param match An optional description of the completion string. The + /// \param completion An optional description of the completion string. The /// description will be displayed to the user alongside the completion. + /// \param mode The CompletionMode for this completion. void AddCompletion(llvm::StringRef completion, - llvm::StringRef description = "") { - m_result.AddResult(completion, description); + llvm::StringRef description = "", + CompletionMode mode = CompletionMode::Normal) { + m_result.AddResult(completion, description, mode); + } + + /// Adds a possible completion string if the completion would complete the + /// current argument. + /// + /// \param match The suggested completion. + /// \param description An optional description of the completion string. The + /// description will be displayed to the user alongside the completion. + template <CompletionMode M = CompletionMode::Normal> + void TryCompleteCurrentArg(llvm::StringRef completion, + llvm::StringRef description = "") { + // Trying to rewrite the whole line while checking for the current + // argument never makes sense. Completion modes are always hardcoded, so + // this can be a static_assert. + static_assert(M != CompletionMode::RewriteLine, + "Shouldn't rewrite line with this function"); + if (completion.startswith(GetCursorArgumentPrefix())) + AddCompletion(completion, description, M); } /// Adds multiple possible completion strings. @@ -125,8 +169,8 @@ public: /// /// \see AddCompletion void AddCompletions(const StringList &completions) { - for (std::size_t i = 0; i < completions.GetSize(); ++i) - AddCompletion(completions.GetStringAtIndex(i)); + for (const std::string &completion : completions) + AddCompletion(completion); } /// Adds multiple possible completion strings alongside their descriptions. @@ -145,16 +189,8 @@ public: descriptions.GetStringAtIndex(i)); } - std::size_t GetNumberOfMatches() const { - return m_result.GetNumberOfResults(); - } - - llvm::StringRef GetCursorArgument() const { - return GetParsedLine().GetArgumentAtIndex(GetCursorIndex()); - } - llvm::StringRef GetCursorArgumentPrefix() const { - return GetCursorArgument().substr(0, GetCursorCharPosition()); + return GetParsedLine().GetArgumentAtIndex(GetCursorIndex()); } private: @@ -164,22 +200,10 @@ private: unsigned m_raw_cursor_pos; /// The command line parsed as arguments. Args m_parsed_line; - /// The command line until the cursor position parsed as arguments. - Args m_partial_parsed_line; /// The index of the argument in which the completion cursor is. - int m_cursor_index; + size_t m_cursor_index; /// The cursor position in the argument indexed by m_cursor_index. - int m_cursor_char_position; - /// If there is a match that is expensive - /// to compute, these are here to allow you to compute the completions in - /// batches. Start the completion from \amatch_start_point, and return - /// \amatch_return_elements elements. - // FIXME: These two values are not implemented. - int m_match_start_point; - int m_max_return_elements; - /// \btrue if this is a complete option value (a space will be inserted - /// after the completion.) \bfalse otherwise. - bool m_word_complete = false; + size_t m_cursor_char_position; /// The result this request is supposed to fill out. /// We keep this object private to ensure that no backend can in any way diff --git a/include/lldb/Utility/ConstString.h b/include/lldb/Utility/ConstString.h index 8576c18ddcd8..9a9ee458239f 100644 --- a/include/lldb/Utility/ConstString.h +++ b/include/lldb/Utility/ConstString.h @@ -10,6 +10,7 @@ #define liblldb_ConstString_h_ #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/FormatVariadic.h" #include <stddef.h> @@ -204,9 +205,7 @@ public: /// \param[in] rhs /// Another string object to compare this object to. /// - /// \return - /// \li \b true if this object is not equal to \a rhs. - /// \li \b false if this object is equal to \a rhs. + /// \return \b true if this object is not equal to \a rhs, false otherwise. bool operator!=(const char *rhs) const { return !(*this == rhs); } bool operator<(ConstString rhs) const; @@ -218,8 +217,7 @@ public: /// /// If \a value_if_empty is nullptr, then nullptr will be returned. /// - /// \return - /// Returns \a value_if_empty if the string is empty, otherwise + /// \return Returns \a value_if_empty if the string is empty, otherwise /// the C string value contained in this object. const char *AsCString(const char *value_if_empty = nullptr) const { return (IsEmpty() ? value_if_empty : m_string); @@ -269,7 +267,7 @@ public: /// in a pointer comparison since all strings are in a uniqued in a global /// string pool. /// - /// \param[in] rhs + /// \param[in] lhs /// The Left Hand Side const ConstString object reference. /// /// \param[in] rhs @@ -279,9 +277,7 @@ public: /// Case sensitivity. If true, case sensitive equality /// will be tested, otherwise character case will be ignored /// - /// \return - /// \li \b true if this object is equal to \a rhs. - /// \li \b false if this object is not equal to \a rhs. + /// \return \b true if this object is equal to \a rhs, \b false otherwise. static bool Equals(ConstString lhs, ConstString rhs, const bool case_sensitive = true); @@ -305,10 +301,7 @@ public: /// Case sensitivity of compare. If true, case sensitive compare /// will be performed, otherwise character case will be ignored /// - /// \return - /// \li -1 if lhs < rhs - /// \li 0 if lhs == rhs - /// \li 1 if lhs > rhs + /// \return -1 if lhs < rhs, 0 if lhs == rhs, 1 if lhs > rhs static int Compare(ConstString lhs, ConstString rhs, const bool case_sensitive = true); @@ -445,6 +438,14 @@ public: static size_t StaticMemorySize(); protected: + template <typename T> friend struct ::llvm::DenseMapInfo; + /// Only used by DenseMapInfo. + static ConstString FromStringPoolPointer(const char *ptr) { + ConstString s; + s.m_string = ptr; + return s; + }; + // Member variables const char *m_string; }; @@ -459,6 +460,27 @@ template <> struct format_provider<lldb_private::ConstString> { static void format(const lldb_private::ConstString &CS, llvm::raw_ostream &OS, llvm::StringRef Options); }; + +/// DenseMapInfo implementation. +/// \{ +template <> struct DenseMapInfo<lldb_private::ConstString> { + static inline lldb_private::ConstString getEmptyKey() { + return lldb_private::ConstString::FromStringPoolPointer( + DenseMapInfo<const char *>::getEmptyKey()); + } + static inline lldb_private::ConstString getTombstoneKey() { + return lldb_private::ConstString::FromStringPoolPointer( + DenseMapInfo<const char *>::getTombstoneKey()); + } + static unsigned getHashValue(lldb_private::ConstString val) { + return DenseMapInfo<const char *>::getHashValue(val.m_string); + } + static bool isEqual(lldb_private::ConstString LHS, + lldb_private::ConstString RHS) { + return LHS == RHS; + } +}; +/// \} } #endif // liblldb_ConstString_h_ diff --git a/include/lldb/Utility/DataEncoder.h b/include/lldb/Utility/DataEncoder.h index 19b7cef9f0ca..7d44afd2ce69 100644 --- a/include/lldb/Utility/DataEncoder.h +++ b/include/lldb/Utility/DataEncoder.h @@ -204,12 +204,11 @@ public: /// m_addr_size member variable and should be set correctly prior to /// extracting any address values. /// - /// \param[in,out] offset_ptr - /// A pointer to an offset within the data that will be advanced - /// by the appropriate number of bytes if the value is extracted - /// correctly. If the offset is out of bounds or there are not - /// enough bytes to extract this value, the offset will be left - /// unmodified. + /// \param[in] offset + /// The offset where to encode the address. + /// + /// \param[in] addr + /// The address to encode. /// /// \return /// The next valid offset within data if the put operation @@ -220,19 +219,18 @@ public: /// /// Encodes a C string into the existing data including the terminating /// - /// \param[in,out] offset_ptr - /// A pointer to an offset within the data that will be advanced - /// by the appropriate number of bytes if the value is extracted - /// correctly. If the offset is out of bounds or there are not - /// enough bytes to extract this value, the offset will be left - /// unmodified. + /// \param[in] offset + /// The offset where to encode the string. + /// + /// \param[in] cstr + /// The string to encode. /// /// \return /// A pointer to the C string value in the data. If the offset /// pointed to by \a offset_ptr is out of bounds, or if the /// offset plus the length of the C string is out of bounds, /// NULL will be returned. - uint32_t PutCString(uint32_t offset_ptr, const char *cstr); + uint32_t PutCString(uint32_t offset, const char *cstr); lldb::DataBufferSP &GetSharedDataBuffer() { return m_data_sp; } diff --git a/include/lldb/Utility/DataExtractor.h b/include/lldb/Utility/DataExtractor.h index 74174b34ce99..333baf9fd349 100644 --- a/include/lldb/Utility/DataExtractor.h +++ b/include/lldb/Utility/DataExtractor.h @@ -14,6 +14,7 @@ #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/DataExtractor.h" #include <cassert> #include <stdint.h> @@ -167,9 +168,8 @@ public: /// the beginning of each line and can be offset by base address \a /// base_addr. \a num_per_line objects will be displayed on each line. /// - /// \param[in] s - /// The stream to dump the output to. If nullptr the output will - /// be dumped to Log(). + /// \param[in] log + /// The log to dump the output to. /// /// \param[in] offset /// The offset into the data at which to start dumping. @@ -362,30 +362,29 @@ public: /// when say copying a partial data value into a register. /// /// \param[in] src_offset - /// The offset into this data from which to start copying an - /// endian entity + /// The offset into this data from which to start copying an endian + /// entity /// /// \param[in] src_len - /// The length of the endian data to copy from this object - /// into the \a dst object + /// The length of the endian data to copy from this object into the \a + /// dst object /// /// \param[out] dst - /// The buffer where to place the endian data. The data might - /// need to be byte swapped (and appropriately padded with - /// zeroes if \a src_len != \a dst_len) if \a dst_byte_order - /// does not match the byte order in this object. + /// The buffer where to place the endian data. The data might need to be + /// byte swapped (and appropriately padded with zeroes if \a src_len != + /// \a dst_len) if \a dst_byte_order does not match the byte order in + /// this object. /// /// \param[in] dst_len - /// The length number of bytes that the endian value will - /// occupy is \a dst. + /// The length number of bytes that the endian value will occupy is \a + /// dst. /// - /// \param[in] byte_order - /// The byte order that the endian value should be in the \a dst - /// buffer. + /// \param[in] dst_byte_order + /// The byte order that the endian value should be in the \a dst buffer. /// /// \return - /// Returns the number of bytes that were copied, or zero if - /// anything goes wrong. + /// Returns the number of bytes that were copied, or zero if anything + /// goes wrong. lldb::offset_t CopyByteOrderedData(lldb::offset_t src_offset, lldb::offset_t src_len, void *dst, lldb::offset_t dst_len, @@ -520,7 +519,7 @@ public: /// enough bytes to extract this value, the offset will be left /// unmodified. /// - /// \param[in] byte_size + /// \param[in] size /// The size in byte of the integer to extract. /// /// \param[in] bitfield_bit_size @@ -558,7 +557,7 @@ public: /// enough bytes to extract this value, the offset will be left /// unmodified. /// - /// \param[in] byte_size + /// \param[in] size /// The size in bytes of the integer to extract. /// /// \param[in] bitfield_bit_size @@ -956,14 +955,14 @@ public: /// unmodified. /// /// \return - // The number of bytes consumed during the extraction. + /// The number of bytes consumed during the extraction. uint32_t Skip_LEB128(lldb::offset_t *offset_ptr) const; /// Test the validity of \a offset. /// /// \return - /// \b true if \a offset is a valid offset into the data in this - /// object, \b false otherwise. + /// true if \a offset is a valid offset into the data in this object, + /// false otherwise. bool ValidOffset(lldb::offset_t offset) const { return offset < GetByteSize(); } @@ -971,8 +970,8 @@ public: /// Test the availability of \a length bytes of data from \a offset. /// /// \return - /// \b true if \a offset is a valid offset and there are \a - /// length bytes available at that offset, \b false otherwise. + /// true if \a offset is a valid offset and there are \a + /// length bytes available at that offset, false otherwise. bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const { return length <= BytesLeft(offset); @@ -997,6 +996,11 @@ public: return {GetDataStart(), size_t(GetByteSize())}; } + llvm::DataExtractor GetAsLLVM() const { + return {GetData(), GetByteOrder() == lldb::eByteOrderLittle, + uint8_t(GetAddressByteSize())}; + } + protected: // Member variables const uint8_t *m_start; ///< A pointer to the first byte of data. diff --git a/include/lldb/Utility/FileCollector.h b/include/lldb/Utility/FileCollector.h deleted file mode 100644 index a89206747fe1..000000000000 --- a/include/lldb/Utility/FileCollector.h +++ /dev/null @@ -1,77 +0,0 @@ -//===-- FileCollector.h -----------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_UTILITY_FILE_COLLECTOR_H -#define LLDB_UTILITY_FILE_COLLECTOR_H - -#include "lldb/Utility/FileSpec.h" - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/VirtualFileSystem.h" - -#include <mutex> - -namespace lldb_private { - -/// Collects files into a directory and generates a mapping that can be used by -/// the VFS. -class FileCollector { -public: - FileCollector(const FileSpec &root, const FileSpec &overlay); - - void AddFile(const llvm::Twine &file); - void AddFile(const FileSpec &file) { return AddFile(file.GetPath()); } - - /// Write the yaml mapping (for the VFS) to the given file. - std::error_code WriteMapping(const FileSpec &mapping_file); - - /// Copy the files into the root directory. - /// - /// When stop_on_error is true (the default) we abort as soon as one file - /// cannot be copied. This is relatively common, for example when a file was - /// removed after it was added to the mapping. - std::error_code CopyFiles(bool stop_on_error = true); - -protected: - void AddFileImpl(llvm::StringRef src_path); - - bool MarkAsSeen(llvm::StringRef path) { return m_seen.insert(path).second; } - - bool GetRealPath(llvm::StringRef src_path, - llvm::SmallVectorImpl<char> &result); - - void AddFileToMapping(llvm::StringRef virtual_path, - llvm::StringRef real_path) { - m_vfs_writer.addFileMapping(virtual_path, real_path); - } - - /// Synchronizes adding files. - std::mutex m_mutex; - - /// The root directory where files are copied. - FileSpec m_root; - - /// The root directory where the VFS overlay lives. - FileSpec m_overlay_root; - - /// Tracks already seen files so they can be skipped. - llvm::StringSet<> m_seen; - - /// The yaml mapping writer. - llvm::vfs::YAMLVFSWriter m_vfs_writer; - - /// Caches real_path calls when resolving symlinks. - llvm::StringMap<std::string> m_symlink_map; -}; - -} // namespace lldb_private - -#endif // LLDB_UTILITY_FILE_COLLECTOR_H diff --git a/include/lldb/Utility/FileSpec.h b/include/lldb/Utility/FileSpec.h index f0bc5c89fec7..50ad1f1600d8 100644 --- a/include/lldb/Utility/FileSpec.h +++ b/include/lldb/Utility/FileSpec.h @@ -73,7 +73,7 @@ public: /// \see FileSpec::SetFile (const char *path) explicit FileSpec(llvm::StringRef path, Style style = Style::native); - explicit FileSpec(llvm::StringRef path, const llvm::Triple &Triple); + explicit FileSpec(llvm::StringRef path, const llvm::Triple &triple); /// Copy constructor /// @@ -200,10 +200,8 @@ public: /// only the filename will be compared, else a full comparison /// is done. /// - /// \return - /// \li -1 if \a lhs is less than \a rhs - /// \li 0 if \a lhs is equal to \a rhs - /// \li 1 if \a lhs is greater than \a rhs + /// \return -1 if \a lhs is less than \a rhs, 0 if \a lhs is equal to \a rhs, + /// 1 if \a lhs is greater than \a rhs static int Compare(const FileSpec &lhs, const FileSpec &rhs, bool full); static bool Equal(const FileSpec &a, const FileSpec &b, bool full); @@ -322,10 +320,6 @@ public: /// Extract the full path to the file. /// /// Extract the directory and path into an llvm::SmallVectorImpl<> - /// - /// \return - /// Returns a std::string with the directory and filename - /// concatenated. void GetPath(llvm::SmallVectorImpl<char> &path, bool denormalize = true) const; @@ -336,8 +330,7 @@ public: /// filename has no extension, ConstString(nullptr) is returned. The dot /// ('.') character is not returned as part of the extension /// - /// \return - /// Returns the extension of the file as a ConstString object. + /// \return Returns the extension of the file as a ConstString object. ConstString GetFileNameExtension() const; /// Return the filename without the extension part @@ -346,9 +339,7 @@ public: /// without the extension part (e.g. for a file named "foo.bar", "foo" is /// returned) /// - /// \return - /// Returns the filename without extension - /// as a ConstString object. + /// \return Returns the filename without extension as a ConstString object. ConstString GetFileNameStrippingExtension() const; /// Get the memory cost of this object. @@ -372,12 +363,22 @@ public: /// \param[in] path /// A full, partial, or relative path to a file. /// - /// \param[in] resolve_path - /// If \b true, then we will try to resolve links the path using - /// the static FileSpec::Resolve. + /// \param[in] style + /// The style for the given path. void SetFile(llvm::StringRef path, Style style); - void SetFile(llvm::StringRef path, const llvm::Triple &Triple); + /// Change the file specified with a new path. + /// + /// Update the contents of this object with a new path. The path will be + /// split up into a directory and filename and stored as uniqued string + /// values for quick comparison and efficient memory usage. + /// + /// \param[in] path + /// A full, partial, or relative path to a file. + /// + /// \param[in] triple + /// The triple which is used to set the Path style. + void SetFile(llvm::StringRef path, const llvm::Triple &triple); bool IsResolved() const { return m_is_resolved; } diff --git a/include/lldb/Utility/Flags.h b/include/lldb/Utility/Flags.h index 48b14e7d2a2c..aa869eca0c6e 100644 --- a/include/lldb/Utility/Flags.h +++ b/include/lldb/Utility/Flags.h @@ -121,32 +121,6 @@ public: /// \b true if \a bit is 0, \b false otherwise. bool IsClear(ValueType bit) const { return (m_flags & bit) == 0; } - /// Get the number of zero bits in \a m_flags. - /// - /// \return - /// The number of bits that are set to 0 in the current flags. - size_t ClearCount() const { - size_t count = 0; - for (ValueType shift = 0; shift < sizeof(ValueType) * 8; ++shift) { - if ((m_flags & (1u << shift)) == 0) - ++count; - } - return count; - } - - /// Get the number of one bits in \a m_flags. - /// - /// \return - /// The number of bits that are set to 1 in the current flags. - size_t SetCount() const { - size_t count = 0; - for (ValueType mask = m_flags; mask; mask >>= 1) { - if (mask & 1u) - ++count; - } - return count; - } - protected: ValueType m_flags; ///< The flags. }; diff --git a/include/lldb/Utility/GDBRemote.h b/include/lldb/Utility/GDBRemote.h new file mode 100644 index 000000000000..b4adeb368524 --- /dev/null +++ b/include/lldb/Utility/GDBRemote.h @@ -0,0 +1,117 @@ +//===-- GDBRemote.h ----------------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GDBRemote_h_ +#define liblldb_GDBRemote_h_ + +#include "lldb/Utility/StreamString.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-public.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" + +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <vector> + +namespace lldb_private { + +class StreamGDBRemote : public StreamString { +public: + StreamGDBRemote(); + + StreamGDBRemote(uint32_t flags, uint32_t addr_size, + lldb::ByteOrder byte_order); + + ~StreamGDBRemote() override; + + /// Output a block of data to the stream performing GDB-remote escaping. + /// + /// \param[in] s + /// A block of data. + /// + /// \param[in] src_len + /// The amount of data to write. + /// + /// \return + /// Number of bytes written. + // TODO: Convert this function to take ArrayRef<uint8_t> + int PutEscapedBytes(const void *s, size_t src_len); +}; + +/// GDB remote packet as used by the reproducer and the GDB remote +/// communication history. Packets can be serialized to file. +struct GDBRemotePacket { + + friend llvm::yaml::MappingTraits<GDBRemotePacket>; + + enum Type { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; + + GDBRemotePacket() + : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), packet_idx(0), + tid(LLDB_INVALID_THREAD_ID) {} + + void Clear() { + packet.data.clear(); + type = ePacketTypeInvalid; + bytes_transmitted = 0; + packet_idx = 0; + tid = LLDB_INVALID_THREAD_ID; + } + + struct BinaryData { + std::string data; + }; + + void Serialize(llvm::raw_ostream &strm) const; + void Dump(Stream &strm) const; + + BinaryData packet; + Type type; + uint32_t bytes_transmitted; + uint32_t packet_idx; + lldb::tid_t tid; + +private: + llvm::StringRef GetTypeStr() const; +}; + +} // namespace lldb_private + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::GDBRemotePacket) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector<lldb_private::GDBRemotePacket>) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits<lldb_private::GDBRemotePacket::Type> { + static void enumeration(IO &io, lldb_private::GDBRemotePacket::Type &value); +}; + +template <> struct ScalarTraits<lldb_private::GDBRemotePacket::BinaryData> { + static void output(const lldb_private::GDBRemotePacket::BinaryData &, void *, + raw_ostream &); + + static StringRef input(StringRef, void *, + lldb_private::GDBRemotePacket::BinaryData &); + + static QuotingType mustQuote(StringRef S) { return QuotingType::None; } +}; + +template <> struct MappingTraits<lldb_private::GDBRemotePacket> { + static void mapping(IO &io, lldb_private::GDBRemotePacket &Packet); + + static StringRef validate(IO &io, lldb_private::GDBRemotePacket &); +}; + +} // namespace yaml +} // namespace llvm + +#endif // liblldb_GDBRemote_h_ diff --git a/include/lldb/Utility/IOObject.h b/include/lldb/Utility/IOObject.h index 1640200a01d9..16ed580abf71 100644 --- a/include/lldb/Utility/IOObject.h +++ b/include/lldb/Utility/IOObject.h @@ -29,8 +29,7 @@ public: typedef int WaitableHandle; static const WaitableHandle kInvalidHandleValue; - IOObject(FDType type, bool should_close) - : m_fd_type(type), m_should_close_fd(should_close) {} + IOObject(FDType type) : m_fd_type(type) {} virtual ~IOObject(); virtual Status Read(void *buf, size_t &num_bytes) = 0; @@ -44,8 +43,6 @@ public: protected: FDType m_fd_type; - bool m_should_close_fd; // True if this class should close the file descriptor - // when it goes away. private: DISALLOW_COPY_AND_ASSIGN(IOObject); diff --git a/include/lldb/Utility/JSON.h b/include/lldb/Utility/JSON.h deleted file mode 100644 index 172f77afb01f..000000000000 --- a/include/lldb/Utility/JSON.h +++ /dev/null @@ -1,283 +0,0 @@ -//===---------------------JSON.h --------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef utility_JSON_h_ -#define utility_JSON_h_ - -#include "lldb/Utility/StringExtractor.h" - -#include <map> -#include <memory> -#include <string> -#include <type_traits> -#include <vector> - -#include <stdint.h> - -namespace lldb_private { -class Stream; - -class JSONValue { -public: - virtual void Write(Stream &s) = 0; - - typedef std::shared_ptr<JSONValue> SP; - - enum class Kind { String, Number, True, False, Null, Object, Array }; - - JSONValue(Kind k) : m_kind(k) {} - - Kind GetKind() const { return m_kind; } - - virtual ~JSONValue() = default; - -private: - const Kind m_kind; -}; - -class JSONString : public JSONValue { -public: - JSONString(); - JSONString(const char *s); - JSONString(const std::string &s); - - JSONString(const JSONString &s) = delete; - JSONString &operator=(const JSONString &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONString> SP; - - std::string GetData() { return m_data; } - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::String; - } - - ~JSONString() override = default; - -private: - static std::string json_string_quote_metachars(const std::string &); - - std::string m_data; -}; - -class JSONNumber : public JSONValue { -public: - typedef std::shared_ptr<JSONNumber> SP; - - // We cretae a constructor for all integer and floating point type with using - // templates and - // SFINAE to avoid having ambiguous overloads because of the implicit type - // promotion. If we - // would have constructors only with int64_t, uint64_t and double types then - // constructing a JSONNumber from an int32_t (or any other similar type) - // would fail to compile. - - template <typename T, typename std::enable_if< - std::is_integral<T>::value && - std::is_unsigned<T>::value>::type * = nullptr> - explicit JSONNumber(T u) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) { - m_data.m_unsigned = u; - } - - template <typename T, - typename std::enable_if<std::is_integral<T>::value && - std::is_signed<T>::value>::type * = nullptr> - explicit JSONNumber(T s) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) { - m_data.m_signed = s; - } - - template <typename T, typename std::enable_if< - std::is_floating_point<T>::value>::type * = nullptr> - explicit JSONNumber(T d) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) { - m_data.m_double = d; - } - - ~JSONNumber() override = default; - - JSONNumber(const JSONNumber &s) = delete; - JSONNumber &operator=(const JSONNumber &s) = delete; - - void Write(Stream &s) override; - - uint64_t GetAsUnsigned() const; - - int64_t GetAsSigned() const; - - double GetAsDouble() const; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Number; - } - -private: - enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type; - - union { - uint64_t m_unsigned; - int64_t m_signed; - double m_double; - } m_data; -}; - -class JSONTrue : public JSONValue { -public: - JSONTrue(); - - JSONTrue(const JSONTrue &s) = delete; - JSONTrue &operator=(const JSONTrue &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONTrue> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::True; - } - - ~JSONTrue() override = default; -}; - -class JSONFalse : public JSONValue { -public: - JSONFalse(); - - JSONFalse(const JSONFalse &s) = delete; - JSONFalse &operator=(const JSONFalse &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONFalse> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::False; - } - - ~JSONFalse() override = default; -}; - -class JSONNull : public JSONValue { -public: - JSONNull(); - - JSONNull(const JSONNull &s) = delete; - JSONNull &operator=(const JSONNull &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONNull> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Null; - } - - ~JSONNull() override = default; -}; - -class JSONObject : public JSONValue { -public: - JSONObject(); - - JSONObject(const JSONObject &s) = delete; - JSONObject &operator=(const JSONObject &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONObject> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Object; - } - - bool SetObject(const std::string &key, JSONValue::SP value); - - JSONValue::SP GetObject(const std::string &key); - - ~JSONObject() override = default; - -private: - typedef std::map<std::string, JSONValue::SP> Map; - typedef Map::iterator Iterator; - Map m_elements; -}; - -class JSONArray : public JSONValue { -public: - JSONArray(); - - JSONArray(const JSONArray &s) = delete; - JSONArray &operator=(const JSONArray &s) = delete; - - void Write(Stream &s) override; - - typedef std::shared_ptr<JSONArray> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Array; - } - -private: - typedef std::vector<JSONValue::SP> Vector; - typedef Vector::iterator Iterator; - typedef Vector::size_type Index; - typedef Vector::size_type Size; - -public: - bool SetObject(Index i, JSONValue::SP value); - - bool AppendObject(JSONValue::SP value); - - JSONValue::SP GetObject(Index i); - - Size GetNumElements(); - - ~JSONArray() override = default; - - Vector m_elements; -}; - -class JSONParser : public StringExtractor { -public: - enum Token { - Invalid, - Status, - ObjectStart, - ObjectEnd, - ArrayStart, - ArrayEnd, - Comma, - Colon, - String, - Integer, - Float, - True, - False, - Null, - EndOfFile - }; - - JSONParser(llvm::StringRef data); - - int GetEscapedChar(bool &was_escaped); - - Token GetToken(std::string &value); - - JSONValue::SP ParseJSONValue(); - -protected: - JSONValue::SP ParseJSONObject(); - - JSONValue::SP ParseJSONArray(); -}; -} // namespace lldb_private - -#endif // utility_JSON_h_ diff --git a/include/lldb/Utility/Log.h b/include/lldb/Utility/Log.h index 949de69c8e5a..09c0f6954478 100644 --- a/include/lldb/Utility/Log.h +++ b/include/lldb/Utility/Log.h @@ -14,6 +14,7 @@ #include "lldb/lldb-defines.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -112,6 +113,14 @@ public: static bool ListChannelCategories(llvm::StringRef channel, llvm::raw_ostream &stream); + /// Returns the list of log channels. + static std::vector<llvm::StringRef> ListChannels(); + /// Calls the given lambda for every category in the given channel. + /// If no channel with the given name exists, lambda is never called. + static void ForEachChannelCategory( + llvm::StringRef channel, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda); + static void DisableAllLogChannels(); static void ListAllLogChannels(llvm::raw_ostream &stream); @@ -142,14 +151,11 @@ public: std::forward<Args>(args)...)); } + /// Prefer using LLDB_LOGF whenever possible. void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); - void VAPrintf(const char *format, va_list args); - void Error(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void VAError(const char *format, va_list args); - void Verbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); void Warning(const char *fmt, ...) __attribute__((format(printf, 2, 3))); @@ -161,6 +167,9 @@ public: bool GetVerbose() const; private: + void VAPrintf(const char *format, va_list args); + void VAError(const char *format, va_list args); + Channel &m_channel; // The mutex makes sure enable/disable operations are thread-safe. The @@ -193,6 +202,10 @@ private: typedef llvm::StringMap<Log> ChannelMap; static llvm::ManagedStatic<ChannelMap> g_channel_map; + static void ForEachCategory( + const Log::ChannelMap::value_type &entry, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda); + static void ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry); static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, @@ -206,6 +219,26 @@ private: } // namespace lldb_private +/// The LLDB_LOG* macros defined below are the way to emit log messages. +/// +/// Note that the macros surround the arguments in a check for the log +/// being on, so you can freely call methods in arguments without affecting +/// the non-log execution flow. +/// +/// If you need to do more complex computations to prepare the log message +/// be sure to add your own if (log) check, since we don't want logging to +/// have any effect when not on. +/// +/// However, the LLDB_LOG macro uses the llvm::formatv system (see the +/// ProgrammersManual page in the llvm docs for more details). This allows +/// the use of "format_providers" to auto-format datatypes, and there are +/// already formatters for some of the llvm and lldb datatypes. +/// +/// So if you need to do non-trivial formatting of one of these types, be +/// sure to grep the lldb and llvm sources for "format_provider" to see if +/// there is already a formatter before doing in situ formatting, and if +/// possible add a provider if one does not already exist. + #define LLDB_LOG(log, ...) \ do { \ ::lldb_private::Log *log_private = (log); \ @@ -213,6 +246,13 @@ private: log_private->Format(__FILE__, __func__, __VA_ARGS__); \ } while (0) +#define LLDB_LOGF(log, ...) \ + do { \ + ::lldb_private::Log *log_private = (log); \ + if (log_private) \ + log_private->Printf(__VA_ARGS__); \ + } while (0) + #define LLDB_LOGV(log, ...) \ do { \ ::lldb_private::Log *log_private = (log); \ diff --git a/include/lldb/Utility/Logging.h b/include/lldb/Utility/Logging.h index 41086fedf8c2..1a8a1022c5c0 100644 --- a/include/lldb/Utility/Logging.h +++ b/include/lldb/Utility/Logging.h @@ -54,8 +54,6 @@ namespace lldb_private { class Log; -void LogIfAnyCategoriesSet(uint32_t mask, const char *format, ...); - Log *GetLogIfAllCategoriesSet(uint32_t mask); Log *GetLogIfAnyCategoriesSet(uint32_t mask); diff --git a/include/lldb/Utility/Predicate.h b/include/lldb/Utility/Predicate.h index f1539b576686..cbccc3e91a8b 100644 --- a/include/lldb/Utility/Predicate.h +++ b/include/lldb/Utility/Predicate.h @@ -117,8 +117,7 @@ public: /// How long to wait for the condition to hold. /// /// \return - /// \li m_value if Cond(m_value) is true. - /// \li None otherwise (timeout occurred). + /// m_value if Cond(m_value) is true, None otherwise (timeout occurred). template <typename C> llvm::Optional<T> WaitFor(C Cond, const Timeout<std::micro> &timeout) { std::unique_lock<std::mutex> lock(m_mutex); @@ -151,8 +150,8 @@ public: /// How long to wait for the condition to hold. /// /// \return - /// \li \b true if the \a m_value is equal to \a value - /// \li \b false otherwise (timeout occurred) + /// true if the \a m_value is equal to \a value, false otherwise (timeout + /// occurred). bool WaitForValueEqualTo(T value, const Timeout<std::micro> &timeout = llvm::None) { return WaitFor([&value](T current) { return value == current; }, timeout) != @@ -179,8 +178,7 @@ public: /// How long to wait for the condition to hold. /// /// \return - /// \li m_value if m_value != value - /// \li None otherwise (timeout occurred). + /// m_value if m_value != value, None otherwise (timeout occurred). llvm::Optional<T> WaitForValueNotEqualTo(T value, const Timeout<std::micro> &timeout = llvm::None) { diff --git a/include/lldb/Utility/ProcessInfo.h b/include/lldb/Utility/ProcessInfo.h index a25c06cabdf6..9188bf3b7090 100644 --- a/include/lldb/Utility/ProcessInfo.h +++ b/include/lldb/Utility/ProcessInfo.h @@ -38,7 +38,7 @@ public: const char *GetName() const; - size_t GetNameLength() const; + llvm::StringRef GetNameAsStringRef() const; FileSpec &GetExecutableFile() { return m_executable; } @@ -165,12 +165,8 @@ public: void Append(const ProcessInstanceInfo &info) { m_infos.push_back(info); } - const char *GetProcessNameAtIndex(size_t idx) { - return ((idx < m_infos.size()) ? m_infos[idx].GetName() : nullptr); - } - - size_t GetProcessNameLengthAtIndex(size_t idx) { - return ((idx < m_infos.size()) ? m_infos[idx].GetNameLength() : 0); + llvm::StringRef GetProcessNameAtIndex(size_t idx) { + return ((idx < m_infos.size()) ? m_infos[idx].GetNameAsStringRef() : ""); } lldb::pid_t GetProcessIDAtIndex(size_t idx) { @@ -227,8 +223,20 @@ public: m_name_match_type = name_match_type; } + /// Return true iff the architecture in this object matches arch_spec. + bool ArchitectureMatches(const ArchSpec &arch_spec) const; + + /// Return true iff the process name in this object matches process_name. bool NameMatches(const char *process_name) const; + /// Return true iff the process ID and parent process IDs in this object match + /// the ones in proc_info. + bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const; + + /// Return true iff the (both effective and real) user and group IDs in this + /// object match the ones in proc_info. + bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const; + bool Matches(const ProcessInstanceInfo &proc_info) const; bool MatchAllProcesses() const; diff --git a/include/lldb/Utility/RangeMap.h b/include/lldb/Utility/RangeMap.h index 36401f59d34f..709b5d2f66c7 100644 --- a/include/lldb/Utility/RangeMap.h +++ b/include/lldb/Utility/RangeMap.h @@ -724,12 +724,14 @@ public: #ifdef ASSERT_RANGEMAP_ARE_SORTED assert(IsSorted()); #endif - - if (!m_entries.empty()) { - for (const auto &entry : m_entries) { - if (entry.Contains(addr)) - indexes.push_back(entry.data); - } + // Search the entries until the first entry that has a larger base address + // than `addr`. As m_entries is sorted by their base address, all following + // entries can't contain `addr` as their base address is already larger. + for (const auto &entry : m_entries) { + if (entry.Contains(addr)) + indexes.push_back(entry.data); + else if (entry.GetRangeBase() > addr) + break; } return indexes.size(); } diff --git a/include/lldb/Utility/RegularExpression.h b/include/lldb/Utility/RegularExpression.h index 54f3dd89c7a2..6acc203d8e7c 100644 --- a/include/lldb/Utility/RegularExpression.h +++ b/include/lldb/Utility/RegularExpression.h @@ -9,189 +9,84 @@ #ifndef liblldb_RegularExpression_h_ #define liblldb_RegularExpression_h_ -#ifdef _WIN32 -#include "../lib/Support/regex_impl.h" - -typedef llvm_regmatch_t regmatch_t; -typedef llvm_regex_t regex_t; - -inline int regcomp(llvm_regex_t *a, const char *b, int c) { - return llvm_regcomp(a, b, c); -} - -inline size_t regerror(int a, const llvm_regex_t *b, char *c, size_t d) { - return llvm_regerror(a, b, c, d); -} - -inline int regexec(const llvm_regex_t *a, const char *b, size_t c, - llvm_regmatch_t d[], int e) { - return llvm_regexec(a, b, c, d, e); -} - -inline void regfree(llvm_regex_t *a) { llvm_regfree(a); } -#else -#ifdef __ANDROID__ -#include <regex> -#endif -#include <regex.h> -#endif - -#include <string> -#include <vector> - -#include <stddef.h> -#include <stdint.h> - -namespace llvm { -class StringRef; -} // namespace llvm +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Regex.h" namespace lldb_private { -/// \class RegularExpression RegularExpression.h -/// "lldb/Utility/RegularExpression.h" -/// A C++ wrapper class for regex. -/// -/// This regular expression class wraps the posix regex functions \c -/// regcomp(), \c regerror(), \c regexec(), and \c regfree() from the header -/// file in \c /usr/include/regex\.h. class RegularExpression { public: - class Match { - public: - Match(uint32_t max_matches) : m_matches() { - if (max_matches > 0) - m_matches.resize(max_matches + 1); - } - - void Clear() { - const size_t num_matches = m_matches.size(); - regmatch_t invalid_match = {-1, -1}; - for (size_t i = 0; i < num_matches; ++i) - m_matches[i] = invalid_match; - } - - size_t GetSize() const { return m_matches.size(); } - - regmatch_t *GetData() { - return (m_matches.empty() ? nullptr : m_matches.data()); - } - - bool GetMatchAtIndex(llvm::StringRef s, uint32_t idx, - std::string &match_str) const; - - bool GetMatchAtIndex(llvm::StringRef s, uint32_t idx, - llvm::StringRef &match_str) const; - - bool GetMatchSpanningIndices(llvm::StringRef s, uint32_t idx1, - uint32_t idx2, - llvm::StringRef &match_str) const; - - protected: - std::vector<regmatch_t> - m_matches; ///< Where parenthesized subexpressions results are stored - }; - - /// Default constructor. - /// /// The default constructor that initializes the object state such that it /// contains no compiled regular expression. - RegularExpression(); + RegularExpression() = default; - explicit RegularExpression(llvm::StringRef string); - - /// Destructor. - /// - /// Any previously compiled regular expression contained in this object will - /// be freed. - ~RegularExpression(); - - RegularExpression(const RegularExpression &rhs); - - const RegularExpression &operator=(const RegularExpression &rhs); - - /// Compile a regular expression. + /// Constructor for a regular expression. /// /// Compile a regular expression using the supplied regular expression text. /// 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. + /// after the regular expression is compiled. /// - /// \param[in] re - /// A NULL terminated C string that represents the regular - /// expression to compile. - /// - /// \return - /// \b true if the regular expression compiles successfully, - /// \b false otherwise. - bool Compile(llvm::StringRef string); - bool Compile(const char *) = delete; + /// \param[in] string + /// An llvm::StringRef that represents the regular expression to compile. + // String is not referenced anymore after the object is constructed. + explicit RegularExpression(llvm::StringRef string); + + ~RegularExpression() = default; + + RegularExpression(const RegularExpression &rhs); + RegularExpression(RegularExpression &&rhs) = default; + + RegularExpression &operator=(RegularExpression &&rhs) = default; + RegularExpression &operator=(const RegularExpression &rhs) = default; - /// Executes a regular expression. - /// /// Execute a regular expression match using the compiled regular expression - /// that is already in this object against the match string \a s. If any - /// parens are used for regular expression matches \a match_count should - /// indicate the number of regmatch_t values that are present in \a - /// match_ptr. + /// that is already in this object against the given \a string. If any parens + /// are used for regular expression matches. /// /// \param[in] string /// The string to match against the compile regular expression. /// - /// \param[in] match - /// A pointer to a RegularExpression::Match structure that was - /// properly initialized with the desired number of maximum - /// matches, or nullptr if no parenthesized matching is needed. + /// \param[out] matches + /// A pointer to a SmallVector to hold the matches. /// /// \return - /// \b true if \a string matches the compiled regular - /// expression, \b false otherwise. - bool Execute(llvm::StringRef string, Match *match = nullptr) const; - bool Execute(const char *, Match * = nullptr) = delete; - - size_t GetErrorAsCString(char *err_str, size_t err_str_max_len) const; - - /// Free the compiled regular expression. - /// - /// If this object contains a valid compiled regular expression, this - /// function will free any resources it was consuming. - void Free(); + /// true if \a string matches the compiled regular expression, false + /// otherwise incl. the case regular exression failed to compile. + bool Execute(llvm::StringRef string, + llvm::SmallVectorImpl<llvm::StringRef> *matches = nullptr) const; /// Access the regular expression text. /// - /// Returns the text that was used to compile the current regular - /// expression. - /// /// \return /// The NULL terminated C string that was used to compile the /// current regular expression llvm::StringRef GetText() const; - /// Test if valid. - /// /// Test if this object contains a valid regular expression. /// /// \return - /// \b true if the regular expression compiled and is ready - /// for execution, \b false otherwise. + /// true if the regular expression compiled and is ready for execution, + /// false otherwise. bool IsValid() const; - void Clear() { - Free(); - m_re.clear(); - m_comp_err = 1; - } - - int GetErrorCode() const { return m_comp_err; } + /// Return an error if the regular expression failed to compile. + /// + /// \return + /// A string error if the regular expression failed to compile, success + /// otherwise. + llvm::Error GetError() const; - bool operator<(const RegularExpression &rhs) const; + bool operator==(const RegularExpression &rhs) const { + return GetText() == rhs.GetText(); + } private: - // Member variables - std::string m_re; ///< A copy of the original regular expression text - int m_comp_err; ///< Status code for the regular expression compilation - regex_t m_preg; ///< The compiled regular expression + /// A copy of the original regular expression text. + std::string m_regex_text; + /// The compiled regular expression. + mutable llvm::Regex m_regex; }; } // namespace lldb_private diff --git a/include/lldb/Utility/Reproducer.h b/include/lldb/Utility/Reproducer.h index 670041d06bba..3db98a781d4c 100644 --- a/include/lldb/Utility/Reproducer.h +++ b/include/lldb/Utility/Reproducer.h @@ -9,11 +9,10 @@ #ifndef LLDB_UTILITY_REPRODUCER_H #define LLDB_UTILITY_REPRODUCER_H -#include "lldb/Utility/FileCollector.h" #include "lldb/Utility/FileSpec.h" - #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileCollector.h" #include "llvm/Support/YAMLTraits.h" #include <mutex> @@ -91,23 +90,26 @@ public: FileProvider(const FileSpec &directory) : Provider(directory), - m_collector(directory.CopyByAppendingPathComponent("root"), directory) { - } + m_collector(std::make_shared<llvm::FileCollector>( + directory.CopyByAppendingPathComponent("root").GetPath(), + directory.GetPath())) {} - FileCollector &GetFileCollector() { return m_collector; } + std::shared_ptr<llvm::FileCollector> GetFileCollector() { + return m_collector; + } void Keep() override { auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file); // Temporary files that are removed during execution can cause copy errors. - if (auto ec = m_collector.CopyFiles(/*stop_on_error=*/false)) + if (auto ec = m_collector->copyFiles(/*stop_on_error=*/false)) return; - m_collector.WriteMapping(mapping); + m_collector->writeMapping(mapping.GetPath()); } static char ID; private: - FileCollector m_collector; + std::shared_ptr<llvm::FileCollector> m_collector; }; /// Provider for the LLDB version number. @@ -130,11 +132,32 @@ public: static char ID; }; +/// Provider for the LLDB current working directroy. +/// +/// When the reproducer is kept, it writes lldb's current working directory to +/// a file named cwd.txt in the reproducer root. +class WorkingDirectoryProvider : public Provider<WorkingDirectoryProvider> { +public: + WorkingDirectoryProvider(const FileSpec &directory) : Provider(directory) { + llvm::SmallString<128> cwd; + if (std::error_code EC = llvm::sys::fs::current_path(cwd)) + return; + m_cwd = cwd.str(); + } + struct Info { + static const char *name; + static const char *file; + }; + void Keep() override; + std::string m_cwd; + static char ID; +}; + class DataRecorder { public: DataRecorder(const FileSpec &filename, std::error_code &ec) : m_filename(filename.GetFilename().GetStringRef()), - m_os(filename.GetPath(), ec, llvm::sys::fs::F_Text), m_record(true) {} + m_os(filename.GetPath(), ec, llvm::sys::fs::OF_Text), m_record(true) {} static llvm::Expected<std::unique_ptr<DataRecorder>> Create(const FileSpec &filename); @@ -181,12 +204,39 @@ private: std::vector<std::unique_ptr<DataRecorder>> m_data_recorders; }; +class ProcessGDBRemoteProvider + : public repro::Provider<ProcessGDBRemoteProvider> { +public: + struct Info { + static const char *name; + static const char *file; + }; + + ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) {} + + llvm::raw_ostream *GetHistoryStream(); + + void SetCallback(std::function<void()> callback) { + m_callback = std::move(callback); + } + + void Keep() override { m_callback(); } + void Discard() override { m_callback(); } + + static char ID; + +private: + std::function<void()> m_callback; + std::unique_ptr<llvm::raw_fd_ostream> m_stream_up; +}; + /// The generator is responsible for the logic needed to generate a /// reproducer. For doing so it relies on providers, who serialize data that /// is necessary for reproducing a failure. class Generator final { + public: - Generator(const FileSpec &root); + Generator(FileSpec root); ~Generator(); /// Method to indicate we want to keep the reproducer. If reproducer @@ -200,7 +250,7 @@ public: /// Create and register a new provider. template <typename T> T *Create() { - std::unique_ptr<ProviderBase> provider = llvm::make_unique<T>(m_root); + std::unique_ptr<ProviderBase> provider = std::make_unique<T>(m_root); return static_cast<T *>(Register(std::move(provider))); } @@ -243,7 +293,7 @@ private: class Loader final { public: - Loader(const FileSpec &root); + Loader(FileSpec root); template <typename T> FileSpec GetFile() { if (!HasFile(T::file)) @@ -252,6 +302,15 @@ public: return GetRoot().CopyByAppendingPathComponent(T::file); } + template <typename T> llvm::Expected<std::string> LoadBuffer() { + FileSpec file = GetFile<typename T::Info>(); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = + llvm::vfs::getRealFileSystem()->getBufferForFile(file.GetPath()); + if (!buffer) + return llvm::errorCodeToError(buffer.getError()); + return (*buffer)->getBuffer().str(); + } + llvm::Error LoadIndex(); const FileSpec &GetRoot() const { return m_root; } @@ -284,6 +343,9 @@ public: FileSpec GetReproducerPath() const; + bool IsCapturing() { return static_cast<bool>(m_generator); }; + bool IsReplaying() { return static_cast<bool>(m_loader); }; + protected: llvm::Error SetCapture(llvm::Optional<FileSpec> root); llvm::Error SetReplay(llvm::Optional<FileSpec> root); @@ -297,6 +359,19 @@ private: mutable std::mutex m_mutex; }; +/// Helper class for replaying commands through the reproducer. +class CommandLoader { +public: + CommandLoader(std::vector<std::string> files) : m_files(files) {} + + static std::unique_ptr<CommandLoader> Create(Loader *loader); + llvm::Optional<std::string> GetNextFile(); + +private: + std::vector<std::string> m_files; + unsigned m_index = 0; +}; + } // namespace repro } // namespace lldb_private diff --git a/include/lldb/Utility/ReproducerInstrumentation.h b/include/lldb/Utility/ReproducerInstrumentation.h index f90ce4bc767a..75d66045758f 100644 --- a/include/lldb/Utility/ReproducerInstrumentation.h +++ b/include/lldb/Utility/ReproducerInstrumentation.h @@ -40,7 +40,7 @@ inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { template <> inline void stringify_append<char>(llvm::raw_string_ostream &ss, const char *t) { - ss << t; + ss << '\"' << t << '\"'; } template <typename Head> @@ -105,8 +105,8 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { } #define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ + lldb_private::repro::Recorder sb_recorder( \ + LLVM_PRETTY_FUNCTION, stringify_args(*this, __VA_ARGS__)); \ if (lldb_private::repro::InstrumentationData data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ sb_recorder.Record( \ @@ -117,8 +117,8 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { } #define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ + lldb_private::repro::Recorder sb_recorder( \ + LLVM_PRETTY_FUNCTION, stringify_args(*this, __VA_ARGS__)); \ if (lldb_private::repro::InstrumentationData data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ sb_recorder.Record( \ @@ -129,7 +129,8 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { } #define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); \ + lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ + stringify_args(*this)); \ if (lldb_private::repro::InstrumentationData data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ @@ -139,7 +140,8 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { } #define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); \ + lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ + stringify_args(*this)); \ if (lldb_private::repro::InstrumentationData data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ sb_recorder.Record( \ @@ -175,6 +177,8 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { #define LLDB_RECORD_DUMMY(Result, Class, Method, Signature, ...) \ lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ stringify_args(__VA_ARGS__)); +#define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \ + lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); namespace lldb_private { namespace repro { @@ -234,9 +238,12 @@ struct ReferenceTag {}; struct ValueTag {}; struct FundamentalPointerTag {}; struct FundamentalReferenceTag {}; +struct NotImplementedTag {}; /// Return the deserialization tag for the given type T. -template <class T> struct serializer_tag { typedef ValueTag type; }; +template <class T> struct serializer_tag { + typedef typename std::conditional<std::is_trivially_copyable<T>::value, ValueTag, NotImplementedTag>::type type; +}; template <class T> struct serializer_tag<T *> { typedef typename std::conditional<std::is_fundamental<T>::value, @@ -300,6 +307,11 @@ public: } private: + template <typename T> T Read(NotImplementedTag) { + m_buffer = m_buffer.drop_front(sizeof(T)); + return T(); + } + template <typename T> T Read(ValueTag) { assert(HasData(sizeof(T))); T t; @@ -442,7 +454,7 @@ public: void Register(Signature *f, llvm::StringRef result = {}, llvm::StringRef scope = {}, llvm::StringRef name = {}, llvm::StringRef args = {}) { - DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(f), + DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(f), SignatureStr(result, scope, name, args)); } @@ -452,7 +464,7 @@ public: void Register(Signature *f, Signature *g, llvm::StringRef result = {}, llvm::StringRef scope = {}, llvm::StringRef name = {}, llvm::StringRef args = {}) { - DoRegister(uintptr_t(f), llvm::make_unique<DefaultReplayer<Signature>>(g), + DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(g), SignatureStr(result, scope, name, args)); } @@ -542,9 +554,7 @@ public: SerializeAll(tail...); } - void SerializeAll() { - m_stream.flush(); - } + void SerializeAll() { m_stream.flush(); } private: /// Serialize pointers. We need to differentiate between pointers to diff --git a/include/lldb/Utility/Scalar.h b/include/lldb/Utility/Scalar.h index 62ee9f666e89..72f153ff97cd 100644 --- a/include/lldb/Utility/Scalar.h +++ b/include/lldb/Utility/Scalar.h @@ -38,6 +38,7 @@ namespace lldb_private { // follows the ANSI C type promotion rules. class Scalar { public: + // FIXME: These are host types which seems to be an odd choice. enum Type { e_void = 0, e_sint, @@ -98,30 +99,14 @@ public: } Scalar(llvm::APInt v) : m_type(), m_float(static_cast<float>(0)) { m_integer = llvm::APInt(v); - switch (m_integer.getBitWidth()) { - case 8: - case 16: - case 32: - m_type = e_sint; - return; - case 64: - m_type = e_slonglong; - return; - case 128: - m_type = e_sint128; - return; - case 256: - m_type = e_sint256; - return; - case 512: - m_type = e_sint512; - return; - } - lldbassert(false && "unsupported bitwidth"); + m_type = GetBestTypeForBitSize(m_integer.getBitWidth(), true); } // Scalar(const RegisterValue& reg_value); virtual ~Scalar(); + /// Return the most efficient Scalar::Type for the requested bit size. + static Type GetBestTypeForBitSize(size_t bit_size, bool sign); + bool SignExtend(uint32_t bit_pos); bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset); @@ -154,6 +139,9 @@ public: return (m_type >= e_sint) && (m_type <= e_long_double); } + /// Convert integer to \p type, limited to \p bits size. + void TruncOrExtendTo(Scalar::Type type, uint16_t bits); + bool Promote(Scalar::Type type); bool MakeSigned(); diff --git a/include/lldb/Utility/Status.h b/include/lldb/Utility/Status.h index ae730b90dffe..e6a0a8e7fce1 100644 --- a/include/lldb/Utility/Status.h +++ b/include/lldb/Utility/Status.h @@ -47,8 +47,8 @@ public: /// into ValueType. typedef uint32_t ValueType; - /// Default constructor. - /// + Status(); + /// Initialize the error object with a generic success value. /// /// \param[in] err @@ -56,23 +56,14 @@ public: /// /// \param[in] type /// The type for \a err. - Status(); - explicit Status(ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric); - /* implicit */ Status(std::error_code EC); + Status(std::error_code EC); explicit Status(const char *format, ...) __attribute__((format(printf, 2, 3))); - /// Assignment operator. - /// - /// \param[in] err - /// An error code. - /// - /// \return - /// A const reference to this object. const Status &operator=(const Status &rhs); ~Status(); @@ -221,4 +212,11 @@ template <> struct format_provider<lldb_private::Status> { }; } +#define LLDB_ERRORF(status, fmt, ...) \ + do { \ + if (status) { \ + (status)->SetErrorStringWithFormat((fmt), __VA_ARGS__); \ + } \ + } while (0); + #endif // #ifndef LLDB_UTILITY_STATUS_H diff --git a/include/lldb/Utility/Stream.h b/include/lldb/Utility/Stream.h index b24d4e457177..414f92177303 100644 --- a/include/lldb/Utility/Stream.h +++ b/include/lldb/Utility/Stream.h @@ -35,11 +35,11 @@ public: /// Utility class for counting the bytes that were written to a stream in a /// certain time span. + /// /// \example /// ByteDelta delta(*this); /// WriteDataToStream("foo"); /// return *delta; - /// \endcode class ByteDelta { Stream *m_stream; /// Bytes we have written so far when ByteDelta was created. diff --git a/include/lldb/Utility/StreamGDBRemote.h b/include/lldb/Utility/StreamGDBRemote.h deleted file mode 100644 index dd0ea31126d9..000000000000 --- a/include/lldb/Utility/StreamGDBRemote.h +++ /dev/null @@ -1,45 +0,0 @@ -//===-- StreamGDBRemote.h ----------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_StreamGDBRemote_h_ -#define liblldb_StreamGDBRemote_h_ - -#include "lldb/Utility/StreamString.h" -#include "lldb/lldb-enumerations.h" - -#include <stddef.h> -#include <stdint.h> - -namespace lldb_private { - -class StreamGDBRemote : public StreamString { -public: - StreamGDBRemote(); - - StreamGDBRemote(uint32_t flags, uint32_t addr_size, - lldb::ByteOrder byte_order); - - ~StreamGDBRemote() override; - - /// Output a block of data to the stream performing GDB-remote escaping. - /// - /// \param[in] s - /// A block of data. - /// - /// \param[in] src_len - /// The amount of data to write. - /// - /// \return - /// Number of bytes written. - // TODO: Convert this function to take ArrayRef<uint8_t> - int PutEscapedBytes(const void *s, size_t src_len); -}; - -} // namespace lldb_private - -#endif // liblldb_StreamGDBRemote_h_ diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h index f20ec92199bb..293fef2fbe6b 100644 --- a/include/lldb/Utility/StringExtractor.h +++ b/include/lldb/Utility/StringExtractor.h @@ -45,9 +45,7 @@ public: void SkipSpaces(); - std::string &GetStringRef() { return m_packet; } - - const std::string &GetStringRef() const { return m_packet; } + llvm::StringRef GetStringRef() const { return m_packet; } bool Empty() { return m_packet.empty(); } @@ -91,9 +89,6 @@ public: size_t GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest); - uint64_t GetHexWithFixedSize(uint32_t byte_size, bool little_endian, - uint64_t fail_value); - size_t GetHexByteString(std::string &str); size_t GetHexByteStringFixedLength(std::string &str, uint32_t nibble_length); @@ -113,12 +108,14 @@ protected: m_index = UINT64_MAX; return false; } - // For StringExtractor only - std::string m_packet; // The string in which to extract data. - uint64_t m_index; // When extracting data from a packet, this index - // will march along as things get extracted. If set to - // UINT64_MAX the end of the packet data was reached - // when decoding information + + /// The string in which to extract data. + std::string m_packet; + + /// When extracting data from a packet, this index will march along as things + /// get extracted. If set to UINT64_MAX the end of the packet data was + /// reached when decoding information. + uint64_t m_index; }; #endif // utility_StringExtractor_h_ diff --git a/include/lldb/Utility/StringLexer.h b/include/lldb/Utility/StringLexer.h index d9806c1b37d7..533fd4fb896e 100644 --- a/include/lldb/Utility/StringLexer.h +++ b/include/lldb/Utility/StringLexer.h @@ -1,4 +1,4 @@ -//===--------------------- StringLexer.h ------------------------*- C++ -*-===// +//===-- StringLexer.h -------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -13,7 +13,7 @@ #include <string> #include <utility> -namespace lldb_utility { +namespace lldb_private { class StringLexer { public: diff --git a/include/lldb/Utility/StringList.h b/include/lldb/Utility/StringList.h index 68c1f87510f6..0b1d955678b3 100644 --- a/include/lldb/Utility/StringList.h +++ b/include/lldb/Utility/StringList.h @@ -23,6 +23,8 @@ class Stream; namespace lldb_private { class StringList { + typedef std::vector<std::string> collection; + public: StringList(); @@ -52,6 +54,14 @@ public: size_t GetMaxStringLength() const; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + iterator begin() { return m_strings.begin(); } + iterator end() { return m_strings.end(); } + const_iterator begin() const { return m_strings.begin(); } + const_iterator end() const { return m_strings.end(); } + std::string &operator[](size_t idx) { // No bounds checking, verify "idx" is good prior to calling this function return m_strings[idx]; @@ -69,7 +79,7 @@ public: void Clear(); - void LongestCommonPrefix(std::string &common_prefix); + std::string LongestCommonPrefix(); void InsertStringAtIndex(size_t idx, const std::string &str); @@ -97,14 +107,6 @@ public: // Copy assignment for a vector of strings StringList &operator=(const std::vector<std::string> &rhs); - // This string list contains a list of valid auto completion strings, and the - // "s" is passed in. "matches" is filled in with zero or more string values - // that start with "s", and the first string to exactly match one of the - // string values in this collection, will have "exact_matches_idx" filled in - // to match the index, or "exact_matches_idx" will have SIZE_MAX - size_t AutoComplete(llvm::StringRef s, StringList &matches, - size_t &exact_matches_idx) const; - // Dump the StringList to the given lldb_private::Log, `log`, one item per // line. If given, `name` will be used to identify the start and end of the // list in the output. @@ -125,7 +127,7 @@ public: } private: - std::vector<std::string> m_strings; + collection m_strings; }; } // namespace lldb_private diff --git a/include/lldb/Utility/StructuredData.h b/include/lldb/Utility/StructuredData.h index 75eb2f7b7291..01b14fc3d4d3 100644 --- a/include/lldb/Utility/StructuredData.h +++ b/include/lldb/Utility/StructuredData.h @@ -10,9 +10,11 @@ #define liblldb_StructuredData_h_ #include "llvm/ADT/StringRef.h" +#include "llvm/Support/JSON.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Stream.h" #include "lldb/lldb-enumerations.h" #include <cassert> @@ -28,7 +30,6 @@ namespace lldb_private { class Status; -class Stream; } namespace lldb_private { @@ -150,7 +151,12 @@ public: void DumpToStdout(bool pretty_print = true) const; - virtual void Dump(Stream &s, bool pretty_print = true) const = 0; + virtual void Serialize(llvm::json::OStream &s) const = 0; + + void Dump(lldb_private::Stream &s, bool pretty_print = true) const { + llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0); + Serialize(jso); + } private: lldb::StructuredDataType m_type; @@ -269,7 +275,7 @@ public: void AddItem(ObjectSP item) { m_items.push_back(item); } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: typedef std::vector<ObjectSP> collection; @@ -287,7 +293,7 @@ public: uint64_t GetValue() { return m_value; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: uint64_t m_value; @@ -304,7 +310,7 @@ public: double GetValue() { return m_value; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: double m_value; @@ -321,7 +327,7 @@ public: bool GetValue() { return m_value; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: bool m_value; @@ -337,7 +343,7 @@ public: llvm::StringRef GetValue() { return m_value; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: std::string m_value; @@ -506,7 +512,7 @@ public: AddItem(key, std::make_shared<Boolean>(value)); } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; protected: typedef std::map<ConstString, ObjectSP> collection; @@ -521,7 +527,7 @@ public: bool IsValid() const override { return false; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; }; class Generic : public Object { @@ -535,14 +541,13 @@ public: bool IsValid() const override { return m_object != nullptr; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; private: void *m_object; }; static ObjectSP ParseJSON(std::string json_text); - static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error); }; diff --git a/include/lldb/Utility/UUID.h b/include/lldb/Utility/UUID.h index dbeb9db611b2..0284357be44a 100644 --- a/include/lldb/Utility/UUID.h +++ b/include/lldb/Utility/UUID.h @@ -9,14 +9,11 @@ #ifndef LLDB_UTILITY_UUID_H #define LLDB_UTILITY_UUID_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include <stddef.h> #include <stdint.h> #include <string> -#include "llvm/ADT/ArrayRef.h" - -namespace llvm { - class StringRef; -} namespace lldb_private { @@ -67,10 +64,10 @@ public: std::string GetAsString(llvm::StringRef separator = "-") const; size_t SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes = 16); - - // Same as SetFromStringRef, but if the resultant UUID is all 0 bytes, set the + + // Same as SetFromStringRef, but if the resultant UUID is all 0 bytes, set the // UUID to invalid. - size_t SetFromOptionalStringRef(llvm::StringRef str, + size_t SetFromOptionalStringRef(llvm::StringRef str, uint32_t num_uuid_bytes = 16); // Decode as many UUID bytes (up to 16) as possible from the C string "cstr" @@ -79,14 +76,13 @@ public: /// Decode as many UUID bytes (up to 16) as possible from the C /// string \a cstr. /// - /// \param[in] cstr - /// A NULL terminate C string that points at a UUID string value - /// (no leading spaces). The string must contain only hex - /// characters and optionally can contain the '-' sepearators. + /// \param[in] str + /// An llvm::StringRef that points at a UUID string value (no leading + /// spaces). The string must contain only hex characters and optionally + /// can contain the '-' sepearators. /// /// \param[in] uuid_bytes - /// A buffer of bytes that will contain a full or patially - /// decoded UUID. + /// A buffer of bytes that will contain a full or partially decoded UUID. /// /// \return /// The original string, with all decoded bytes removed. |