//===-- MessageObjects.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_SERVER_TESTS_MESSAGEOBJECTS_H #define LLDB_SERVER_TESTS_MESSAGEOBJECTS_H #include "lldb/Host/Host.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/StructuredData.h" #include "lldb/lldb-types.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" #include <string> namespace llgs_tests { class ThreadInfo; typedef llvm::DenseMap<uint64_t, ThreadInfo> ThreadInfoMap; typedef llvm::DenseMap<unsigned int, lldb_private::RegisterValue> RegisterMap; template <typename T> struct Parser { using result_type = T; }; class ProcessInfo : public Parser<ProcessInfo> { public: static llvm::Expected<ProcessInfo> create(llvm::StringRef response); lldb::pid_t GetPid() const; llvm::support::endianness GetEndian() const; private: ProcessInfo() = default; lldb::pid_t m_pid; lldb::pid_t m_parent_pid; uint32_t m_real_uid; uint32_t m_real_gid; uint32_t m_effective_uid; uint32_t m_effective_gid; std::string m_triple; llvm::SmallString<16> m_ostype; llvm::support::endianness m_endian; unsigned int m_ptrsize; }; class ThreadInfo { public: ThreadInfo() = default; ThreadInfo(llvm::StringRef name, llvm::StringRef reason, RegisterMap registers, unsigned int signal); const lldb_private::RegisterValue *ReadRegister(unsigned int Id) const; private: std::string m_name; std::string m_reason; RegisterMap m_registers; }; class JThreadsInfo : public Parser<JThreadsInfo> { public: static llvm::Expected<JThreadsInfo> create(llvm::StringRef Response, llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos); const ThreadInfoMap &GetThreadInfos() const; private: static llvm::Expected<RegisterMap> parseRegisters(const lldb_private::StructuredData::Dictionary &Dict, llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos); JThreadsInfo() = default; ThreadInfoMap m_thread_infos; }; struct RegisterInfoParser : public Parser<lldb_private::RegisterInfo> { static llvm::Expected<lldb_private::RegisterInfo> create(llvm::StringRef Response); }; llvm::Expected<lldb_private::RegisterValue> parseRegisterValue(const lldb_private::RegisterInfo &Info, llvm::StringRef HexValue, llvm::support::endianness Endian, bool ZeroPad = false); class StopReply : public Parser<std::unique_ptr<StopReply>> { public: StopReply() = default; virtual ~StopReply() = default; static llvm::Expected<std::unique_ptr<StopReply>> create(llvm::StringRef Response, llvm::support::endianness Endian, llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos); // for llvm::cast<> virtual lldb_private::WaitStatus getKind() const = 0; StopReply(const StopReply &) = delete; void operator=(const StopReply &) = delete; }; class StopReplyStop : public StopReply { public: StopReplyStop(uint8_t Signal, lldb::tid_t ThreadId, llvm::StringRef Name, RegisterMap ThreadPcs, RegisterMap Registers, llvm::StringRef Reason) : Signal(Signal), ThreadId(ThreadId), Name(Name), ThreadPcs(std::move(ThreadPcs)), Registers(std::move(Registers)), Reason(Reason) {} static llvm::Expected<std::unique_ptr<StopReplyStop>> create(llvm::StringRef Response, llvm::support::endianness Endian, llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos); const RegisterMap &getThreadPcs() const { return ThreadPcs; } lldb::tid_t getThreadId() const { return ThreadId; } // for llvm::cast<> lldb_private::WaitStatus getKind() const override { return lldb_private::WaitStatus{lldb_private::WaitStatus::Stop, Signal}; } static bool classof(const StopReply *R) { return R->getKind().type == lldb_private::WaitStatus::Stop; } private: static llvm::Expected<RegisterMap> parseRegisters( const llvm::StringMap<llvm::SmallVector<llvm::StringRef, 2>> &Elements, llvm::support::endianness Endian, llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos); uint8_t Signal; lldb::tid_t ThreadId; std::string Name; RegisterMap ThreadPcs; RegisterMap Registers; std::string Reason; }; class StopReplyExit : public StopReply { public: explicit StopReplyExit(uint8_t Status) : Status(Status) {} static llvm::Expected<std::unique_ptr<StopReplyExit>> create(llvm::StringRef response); // for llvm::cast<> lldb_private::WaitStatus getKind() const override { return lldb_private::WaitStatus{lldb_private::WaitStatus::Exit, Status}; } static bool classof(const StopReply *R) { return R->getKind().type == lldb_private::WaitStatus::Exit; } private: uint8_t Status; }; // Common functions for parsing packet data. llvm::Expected<llvm::StringMap<llvm::StringRef>> SplitUniquePairList(llvm::StringRef caller, llvm::StringRef s); llvm::StringMap<llvm::SmallVector<llvm::StringRef, 2>> SplitPairList(llvm::StringRef s); template <typename... Args> llvm::Error make_parsing_error(llvm::StringRef format, Args &&... args) { std::string error = "Unable to parse " + llvm::formatv(format.data(), std::forward<Args>(args)...).str(); return llvm::make_error<llvm::StringError>(error, llvm::inconvertibleErrorCode()); } } // namespace llgs_tests namespace lldb_private { std::ostream &operator<<(std::ostream &OS, const RegisterValue &RegVal); } #endif // LLDB_SERVER_TESTS_MESSAGEOBJECTS_H