10b57cec5SDimitry Andric //===-- NativeProcessProtocol.h ---------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_HOST_COMMON_NATIVEPROCESSPROTOCOL_H 105ffd83dbSDimitry Andric #define LLDB_HOST_COMMON_NATIVEPROCESSPROTOCOL_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "NativeBreakpointList.h" 130b57cec5SDimitry Andric #include "NativeThreadProtocol.h" 140b57cec5SDimitry Andric #include "NativeWatchpointList.h" 150b57cec5SDimitry Andric #include "lldb/Host/Host.h" 160b57cec5SDimitry Andric #include "lldb/Host/MainLoop.h" 170b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h" 1881ad6265SDimitry Andric #include "lldb/Utility/Iterable.h" 190b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 20fe6060f1SDimitry Andric #include "lldb/Utility/TraceGDBRemotePackets.h" 21e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h" 220b57cec5SDimitry Andric #include "lldb/lldb-private-forward.h" 230b57cec5SDimitry Andric #include "lldb/lldb-types.h" 240b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 250b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 270b57cec5SDimitry Andric #include "llvm/Support/Error.h" 280b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 290b57cec5SDimitry Andric #include <mutex> 30bdd1243dSDimitry Andric #include <optional> 310b57cec5SDimitry Andric #include <unordered_map> 320b57cec5SDimitry Andric #include <vector> 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace lldb_private { 35fe6060f1SDimitry Andric LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 36fe6060f1SDimitry Andric 370b57cec5SDimitry Andric class MemoryRegionInfo; 380b57cec5SDimitry Andric class ResumeActionList; 390b57cec5SDimitry Andric 409dba64beSDimitry Andric struct SVR4LibraryInfo { 419dba64beSDimitry Andric std::string name; 429dba64beSDimitry Andric lldb::addr_t link_map; 439dba64beSDimitry Andric lldb::addr_t base_addr; 449dba64beSDimitry Andric lldb::addr_t ld_addr; 459dba64beSDimitry Andric lldb::addr_t next; 469dba64beSDimitry Andric }; 479dba64beSDimitry Andric 480b57cec5SDimitry Andric // NativeProcessProtocol 490b57cec5SDimitry Andric class NativeProcessProtocol { 500b57cec5SDimitry Andric public: 51fe6060f1SDimitry Andric virtual ~NativeProcessProtocol() = default; 520b57cec5SDimitry Andric 5381ad6265SDimitry Andric typedef std::vector<std::unique_ptr<NativeThreadProtocol>> thread_collection; 5481ad6265SDimitry Andric template <typename I> thread_list_adapter(I & iter)5581ad6265SDimitry Andric static NativeThreadProtocol &thread_list_adapter(I &iter) { 5681ad6265SDimitry Andric assert(*iter); 5781ad6265SDimitry Andric return **iter; 5881ad6265SDimitry Andric } 5981ad6265SDimitry Andric typedef LockingAdaptedIterable<thread_collection, NativeThreadProtocol &, 6081ad6265SDimitry Andric thread_list_adapter, std::recursive_mutex> 6181ad6265SDimitry Andric ThreadIterable; 6281ad6265SDimitry Andric 630b57cec5SDimitry Andric virtual Status Resume(const ResumeActionList &resume_actions) = 0; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric virtual Status Halt() = 0; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric virtual Status Detach() = 0; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric /// Sends a process a UNIX signal \a signal. 700b57cec5SDimitry Andric /// 710b57cec5SDimitry Andric /// \return 720b57cec5SDimitry Andric /// Returns an error object. 730b57cec5SDimitry Andric virtual Status Signal(int signo) = 0; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric /// Tells a process to interrupt all operations as if by a Ctrl-C. 760b57cec5SDimitry Andric /// 770b57cec5SDimitry Andric /// The default implementation will send a local host's equivalent of 780b57cec5SDimitry Andric /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() 790b57cec5SDimitry Andric /// operation. 800b57cec5SDimitry Andric /// 810b57cec5SDimitry Andric /// \return 820b57cec5SDimitry Andric /// Returns an error object. 830b57cec5SDimitry Andric virtual Status Interrupt(); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric virtual Status Kill() = 0; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Tells a process not to stop the inferior on given signals and just 880b57cec5SDimitry Andric // reinject them back. 890b57cec5SDimitry Andric virtual Status IgnoreSignals(llvm::ArrayRef<int> signals); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // Memory and memory region functions 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr, 940b57cec5SDimitry Andric MemoryRegionInfo &range_info); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, 970b57cec5SDimitry Andric size_t &bytes_read) = 0; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, 1000b57cec5SDimitry Andric size_t &bytes_read); 1010b57cec5SDimitry Andric 102fe6060f1SDimitry Andric virtual Status ReadMemoryTags(int32_t type, lldb::addr_t addr, size_t len, 103fe6060f1SDimitry Andric std::vector<uint8_t> &tags); 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric virtual Status WriteMemoryTags(int32_t type, lldb::addr_t addr, size_t len, 106fe6060f1SDimitry Andric const std::vector<uint8_t> &tags); 107fe6060f1SDimitry Andric 1089dba64beSDimitry Andric /// Reads a null terminated string from memory. 1099dba64beSDimitry Andric /// 1109dba64beSDimitry Andric /// Reads up to \p max_size bytes of memory until it finds a '\0'. 1119dba64beSDimitry Andric /// If a '\0' is not found then it reads max_size-1 bytes as a string and a 1129dba64beSDimitry Andric /// '\0' is added as the last character of the \p buffer. 1139dba64beSDimitry Andric /// 1149dba64beSDimitry Andric /// \param[in] addr 1159dba64beSDimitry Andric /// The address in memory to read from. 1169dba64beSDimitry Andric /// 1179dba64beSDimitry Andric /// \param[in] buffer 1189dba64beSDimitry Andric /// An allocated buffer with at least \p max_size size. 1199dba64beSDimitry Andric /// 1209dba64beSDimitry Andric /// \param[in] max_size 1219dba64beSDimitry Andric /// The maximum number of bytes to read from memory until it reads the 1229dba64beSDimitry Andric /// string. 1239dba64beSDimitry Andric /// 1249dba64beSDimitry Andric /// \param[out] total_bytes_read 1259dba64beSDimitry Andric /// The number of bytes read from memory into \p buffer. 1269dba64beSDimitry Andric /// 1279dba64beSDimitry Andric /// \return 1289dba64beSDimitry Andric /// Returns a StringRef backed up by the \p buffer passed in. 1299dba64beSDimitry Andric llvm::Expected<llvm::StringRef> 1309dba64beSDimitry Andric ReadCStringFromMemory(lldb::addr_t addr, char *buffer, size_t max_size, 1319dba64beSDimitry Andric size_t &total_bytes_read); 1329dba64beSDimitry Andric 1330b57cec5SDimitry Andric virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, 1340b57cec5SDimitry Andric size_t &bytes_written) = 0; 1350b57cec5SDimitry Andric AllocateMemory(size_t size,uint32_t permissions)136e8d8bef9SDimitry Andric virtual llvm::Expected<lldb::addr_t> AllocateMemory(size_t size, 137e8d8bef9SDimitry Andric uint32_t permissions) { 138e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 139e8d8bef9SDimitry Andric } 1400b57cec5SDimitry Andric DeallocateMemory(lldb::addr_t addr)141e8d8bef9SDimitry Andric virtual llvm::Error DeallocateMemory(lldb::addr_t addr) { 142e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 143e8d8bef9SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0; 1460b57cec5SDimitry Andric 1479dba64beSDimitry Andric virtual llvm::Expected<std::vector<SVR4LibraryInfo>> GetLoadedSVR4Libraries()1489dba64beSDimitry Andric GetLoadedSVR4Libraries() { 1499dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1509dba64beSDimitry Andric "Not implemented"); 1519dba64beSDimitry Andric } 1529dba64beSDimitry Andric 1530b57cec5SDimitry Andric virtual bool IsAlive() const; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric virtual size_t UpdateThreads() = 0; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric virtual const ArchSpec &GetArchitecture() const = 0; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric // Breakpoint functions 1600b57cec5SDimitry Andric virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, 1610b57cec5SDimitry Andric bool hardware) = 0; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Hardware Breakpoint functions 1660b57cec5SDimitry Andric virtual const HardwareBreakpointMap &GetHardwareBreakpointMap() const; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Watchpoint functions 1730b57cec5SDimitry Andric virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const; 1740b57cec5SDimitry Andric 175bdd1243dSDimitry Andric virtual std::optional<std::pair<uint32_t, uint32_t>> 1760b57cec5SDimitry Andric GetHardwareDebugSupportInfo() const; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, 1790b57cec5SDimitry Andric uint32_t watch_flags, bool hardware); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric virtual Status RemoveWatchpoint(lldb::addr_t addr); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Accessors GetID()1840b57cec5SDimitry Andric lldb::pid_t GetID() const { return m_pid; } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric lldb::StateType GetState() const; 1870b57cec5SDimitry Andric IsRunning()1880b57cec5SDimitry Andric bool IsRunning() const { 1890b57cec5SDimitry Andric return m_state == lldb::eStateRunning || IsStepping(); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric IsStepping()1920b57cec5SDimitry Andric bool IsStepping() const { return m_state == lldb::eStateStepping; } 1930b57cec5SDimitry Andric CanResume()1940b57cec5SDimitry Andric bool CanResume() const { return m_state == lldb::eStateStopped; } 1950b57cec5SDimitry Andric GetByteOrder()1960b57cec5SDimitry Andric lldb::ByteOrder GetByteOrder() const { 1970b57cec5SDimitry Andric return GetArchitecture().GetByteOrder(); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric GetAddressByteSize()2000b57cec5SDimitry Andric uint32_t GetAddressByteSize() const { 2010b57cec5SDimitry Andric return GetArchitecture().GetAddressByteSize(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 2050b57cec5SDimitry Andric GetAuxvData() const = 0; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric // Exit Status 208bdd1243dSDimitry Andric virtual std::optional<WaitStatus> GetExitStatus(); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // Access to threads 2130b57cec5SDimitry Andric NativeThreadProtocol *GetThreadAtIndex(uint32_t idx); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric NativeThreadProtocol *GetThreadByID(lldb::tid_t tid); 2160b57cec5SDimitry Andric SetCurrentThreadID(lldb::tid_t tid)2170b57cec5SDimitry Andric void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; } 2180b57cec5SDimitry Andric GetCurrentThreadID()21904eeddc0SDimitry Andric lldb::tid_t GetCurrentThreadID() const { return m_current_thread_id; } 2200b57cec5SDimitry Andric GetCurrentThread()2210b57cec5SDimitry Andric NativeThreadProtocol *GetCurrentThread() { 2220b57cec5SDimitry Andric return GetThreadByID(m_current_thread_id); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric Threads()22581ad6265SDimitry Andric ThreadIterable Threads() const { 22681ad6265SDimitry Andric return ThreadIterable(m_threads, m_threads_mutex); 22781ad6265SDimitry Andric } 22881ad6265SDimitry Andric 2290b57cec5SDimitry Andric // Access to inferior stdio GetTerminalFileDescriptor()2300b57cec5SDimitry Andric virtual int GetTerminalFileDescriptor() { return m_terminal_fd; } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric // Stop id interface 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric uint32_t GetStopID() const; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Callbacks for low-level process state changes 2370b57cec5SDimitry Andric class NativeDelegate { 2380b57cec5SDimitry Andric public: 239fe6060f1SDimitry Andric virtual ~NativeDelegate() = default; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric virtual void InitializeDelegate(NativeProcessProtocol *process) = 0; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric virtual void ProcessStateChanged(NativeProcessProtocol *process, 2440b57cec5SDimitry Andric lldb::StateType state) = 0; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric virtual void DidExec(NativeProcessProtocol *process) = 0; 247fe6060f1SDimitry Andric 248fe6060f1SDimitry Andric virtual void 249fe6060f1SDimitry Andric NewSubprocess(NativeProcessProtocol *parent_process, 250fe6060f1SDimitry Andric std::unique_ptr<NativeProcessProtocol> child_process) = 0; 2510b57cec5SDimitry Andric }; 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric virtual Status GetLoadedModuleFileSpec(const char *module_path, 2540b57cec5SDimitry Andric FileSpec &file_spec) = 0; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric virtual Status GetFileLoadAddress(const llvm::StringRef &file_name, 2570b57cec5SDimitry Andric lldb::addr_t &load_addr) = 0; 2580b57cec5SDimitry Andric 25906c3fb27SDimitry Andric /// Extension flag constants, returned by Manager::GetSupportedExtensions() 260fe6060f1SDimitry Andric /// and passed to SetEnabledExtension() 261fe6060f1SDimitry Andric enum class Extension { 262fe6060f1SDimitry Andric multiprocess = (1u << 0), 263fe6060f1SDimitry Andric fork = (1u << 1), 264fe6060f1SDimitry Andric vfork = (1u << 2), 265fe6060f1SDimitry Andric pass_signals = (1u << 3), 266fe6060f1SDimitry Andric auxv = (1u << 4), 267fe6060f1SDimitry Andric libraries_svr4 = (1u << 5), 268fe6060f1SDimitry Andric memory_tagging = (1u << 6), 269349cc55cSDimitry Andric savecore = (1u << 7), 27004eeddc0SDimitry Andric siginfo_read = (1u << 8), 271fe6060f1SDimitry Andric 27204eeddc0SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(siginfo_read) 273fe6060f1SDimitry Andric }; 274fe6060f1SDimitry Andric 27506c3fb27SDimitry Andric class Manager { 2760b57cec5SDimitry Andric public: Manager(MainLoop & mainloop)27706c3fb27SDimitry Andric Manager(MainLoop &mainloop) : m_mainloop(mainloop) {} 27806c3fb27SDimitry Andric Manager(const Manager &) = delete; 27906c3fb27SDimitry Andric Manager &operator=(const Manager &) = delete; 28006c3fb27SDimitry Andric 28106c3fb27SDimitry Andric virtual ~Manager(); 28206c3fb27SDimitry Andric 2830b57cec5SDimitry Andric /// Launch a process for debugging. 2840b57cec5SDimitry Andric /// 2850b57cec5SDimitry Andric /// \param[in] launch_info 2860b57cec5SDimitry Andric /// Information required to launch the process. 2870b57cec5SDimitry Andric /// 2880b57cec5SDimitry Andric /// \param[in] native_delegate 2890b57cec5SDimitry Andric /// The delegate that will receive messages regarding the 2900b57cec5SDimitry Andric /// inferior. Must outlive the NativeProcessProtocol 2910b57cec5SDimitry Andric /// instance. 2920b57cec5SDimitry Andric /// 2930b57cec5SDimitry Andric /// \param[in] mainloop 2940b57cec5SDimitry Andric /// The mainloop instance with which the process can register 2950b57cec5SDimitry Andric /// callbacks. Must outlive the NativeProcessProtocol 2960b57cec5SDimitry Andric /// instance. 2970b57cec5SDimitry Andric /// 2980b57cec5SDimitry Andric /// \return 2990b57cec5SDimitry Andric /// A NativeProcessProtocol shared pointer if the operation succeeded or 3000b57cec5SDimitry Andric /// an error object if it failed. 3010b57cec5SDimitry Andric virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 30206c3fb27SDimitry Andric Launch(ProcessLaunchInfo &launch_info, 30306c3fb27SDimitry Andric NativeDelegate &native_delegate) = 0; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric /// Attach to an existing process. 3060b57cec5SDimitry Andric /// 3070b57cec5SDimitry Andric /// \param[in] pid 3080b57cec5SDimitry Andric /// pid of the process locatable 3090b57cec5SDimitry Andric /// 3100b57cec5SDimitry Andric /// \param[in] native_delegate 3110b57cec5SDimitry Andric /// The delegate that will receive messages regarding the 3120b57cec5SDimitry Andric /// inferior. Must outlive the NativeProcessProtocol 3130b57cec5SDimitry Andric /// instance. 3140b57cec5SDimitry Andric /// 3150b57cec5SDimitry Andric /// \param[in] mainloop 3160b57cec5SDimitry Andric /// The mainloop instance with which the process can register 3170b57cec5SDimitry Andric /// callbacks. Must outlive the NativeProcessProtocol 3180b57cec5SDimitry Andric /// instance. 3190b57cec5SDimitry Andric /// 3200b57cec5SDimitry Andric /// \return 3210b57cec5SDimitry Andric /// A NativeProcessProtocol shared pointer if the operation succeeded or 3220b57cec5SDimitry Andric /// an error object if it failed. 3230b57cec5SDimitry Andric virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 32406c3fb27SDimitry Andric Attach(lldb::pid_t pid, NativeDelegate &native_delegate) = 0; 325fe6060f1SDimitry Andric 326fe6060f1SDimitry Andric /// Get the bitmask of extensions supported by this process plugin. 327fe6060f1SDimitry Andric /// 328fe6060f1SDimitry Andric /// \return 329fe6060f1SDimitry Andric /// A NativeProcessProtocol::Extension bitmask. GetSupportedExtensions()330fe6060f1SDimitry Andric virtual Extension GetSupportedExtensions() const { return {}; } 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric protected: 33306c3fb27SDimitry Andric MainLoop &m_mainloop; 3340b57cec5SDimitry Andric }; 3350b57cec5SDimitry Andric 33681ad6265SDimitry Andric /// Notify tracers that the target process will resume NotifyTracersProcessWillResume()33781ad6265SDimitry Andric virtual void NotifyTracersProcessWillResume() {} 33881ad6265SDimitry Andric 33981ad6265SDimitry Andric /// Notify tracers that the target process just stopped NotifyTracersProcessDidStop()34081ad6265SDimitry Andric virtual void NotifyTracersProcessDidStop() {} 34181ad6265SDimitry Andric 342fe6060f1SDimitry Andric /// Start tracing a process or its threads. 3430b57cec5SDimitry Andric /// 344fe6060f1SDimitry Andric /// \param[in] json_params 345fe6060f1SDimitry Andric /// JSON object with the information of what and how to trace. 346fe6060f1SDimitry Andric /// In the case of gdb-remote, this object should conform to the 347fe6060f1SDimitry Andric /// jLLDBTraceStart packet. 3480b57cec5SDimitry Andric /// 349fe6060f1SDimitry Andric /// This object should have a string entry called "type", which is the 350fe6060f1SDimitry Andric /// tracing technology name. 351fe6060f1SDimitry Andric /// 352fe6060f1SDimitry Andric /// \param[in] type 353fe6060f1SDimitry Andric /// Tracing technology type, as described in the \a json_params. 3540b57cec5SDimitry Andric /// 3550b57cec5SDimitry Andric /// \return 356fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or an 357fe6060f1SDimitry Andric /// \a llvm::Error otherwise. TraceStart(llvm::StringRef json_params,llvm::StringRef type)358fe6060f1SDimitry Andric virtual llvm::Error TraceStart(llvm::StringRef json_params, 359fe6060f1SDimitry Andric llvm::StringRef type) { 360fe6060f1SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 361fe6060f1SDimitry Andric "Unsupported tracing type '%s'", 362fe6060f1SDimitry Andric type.data()); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 365fe6060f1SDimitry Andric /// \copydoc Process::TraceStop(const TraceStopRequest &) TraceStop(const TraceStopRequest & request)366fe6060f1SDimitry Andric virtual llvm::Error TraceStop(const TraceStopRequest &request) { 367fe6060f1SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 368fe6060f1SDimitry Andric "Unsupported tracing type '%s'", 369fe6060f1SDimitry Andric request.type.data()); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 372fe6060f1SDimitry Andric /// \copydoc Process::TraceGetState(llvm::StringRef type) 373fe6060f1SDimitry Andric virtual llvm::Expected<llvm::json::Value> TraceGetState(llvm::StringRef type)374fe6060f1SDimitry Andric TraceGetState(llvm::StringRef type) { 375fe6060f1SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 376fe6060f1SDimitry Andric "Unsupported tracing type '%s'", 377fe6060f1SDimitry Andric type.data()); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 380fe6060f1SDimitry Andric /// \copydoc Process::TraceGetBinaryData(const TraceGetBinaryDataRequest &) 381fe6060f1SDimitry Andric virtual llvm::Expected<std::vector<uint8_t>> TraceGetBinaryData(const TraceGetBinaryDataRequest & request)382fe6060f1SDimitry Andric TraceGetBinaryData(const TraceGetBinaryDataRequest &request) { 383fe6060f1SDimitry Andric return llvm::createStringError( 384fe6060f1SDimitry Andric llvm::inconvertibleErrorCode(), 385fe6060f1SDimitry Andric "Unsupported data kind '%s' for the '%s' tracing technology", 386fe6060f1SDimitry Andric request.kind.c_str(), request.type.c_str()); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 389fe6060f1SDimitry Andric /// \copydoc Process::TraceSupported() TraceSupported()390fe6060f1SDimitry Andric virtual llvm::Expected<TraceSupportedResponse> TraceSupported() { 391e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 392e8d8bef9SDimitry Andric } 393e8d8bef9SDimitry Andric 394fe6060f1SDimitry Andric /// Method called in order to propagate the bitmap of protocol 395fe6060f1SDimitry Andric /// extensions supported by the client. 396fe6060f1SDimitry Andric /// 397fe6060f1SDimitry Andric /// \param[in] flags 398fe6060f1SDimitry Andric /// The bitmap of enabled extensions. SetEnabledExtensions(Extension flags)399fe6060f1SDimitry Andric virtual void SetEnabledExtensions(Extension flags) { 400fe6060f1SDimitry Andric m_enabled_extensions = flags; 401fe6060f1SDimitry Andric } 402fe6060f1SDimitry Andric 403349cc55cSDimitry Andric /// Write a core dump (without crashing the program). 404349cc55cSDimitry Andric /// 405349cc55cSDimitry Andric /// \param[in] path_hint 406349cc55cSDimitry Andric /// Suggested core dump path (optional, can be empty). 407349cc55cSDimitry Andric /// 408349cc55cSDimitry Andric /// \return 409349cc55cSDimitry Andric /// Path to the core dump if successfully written, an error 410349cc55cSDimitry Andric /// otherwise. SaveCore(llvm::StringRef path_hint)411349cc55cSDimitry Andric virtual llvm::Expected<std::string> SaveCore(llvm::StringRef path_hint) { 412349cc55cSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 413349cc55cSDimitry Andric "Not implemented"); 414349cc55cSDimitry Andric } 415349cc55cSDimitry Andric 4160b57cec5SDimitry Andric protected: 4170b57cec5SDimitry Andric struct SoftwareBreakpoint { 4180b57cec5SDimitry Andric uint32_t ref_count; 4190b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 4> saved_opcodes; 4200b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> breakpoint_opcodes; 4210b57cec5SDimitry Andric }; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric std::unordered_map<lldb::addr_t, SoftwareBreakpoint> m_software_breakpoints; 4240b57cec5SDimitry Andric lldb::pid_t m_pid; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric std::vector<std::unique_ptr<NativeThreadProtocol>> m_threads; 4270b57cec5SDimitry Andric lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID; 4280b57cec5SDimitry Andric mutable std::recursive_mutex m_threads_mutex; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric lldb::StateType m_state = lldb::eStateInvalid; 4310b57cec5SDimitry Andric mutable std::recursive_mutex m_state_mutex; 4320b57cec5SDimitry Andric 433bdd1243dSDimitry Andric std::optional<WaitStatus> m_exit_status; 4340b57cec5SDimitry Andric 435fe6060f1SDimitry Andric NativeDelegate &m_delegate; 4360b57cec5SDimitry Andric NativeWatchpointList m_watchpoint_list; 4370b57cec5SDimitry Andric HardwareBreakpointMap m_hw_breakpoints_map; 4380b57cec5SDimitry Andric int m_terminal_fd; 4390b57cec5SDimitry Andric uint32_t m_stop_id = 0; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // Set of signal numbers that LLDB directly injects back to inferior without 4420b57cec5SDimitry Andric // stopping it. 4430b57cec5SDimitry Andric llvm::DenseSet<int> m_signals_to_ignore; 4440b57cec5SDimitry Andric 445fe6060f1SDimitry Andric // Extensions enabled per the last SetEnabledExtensions() call. 446fe6060f1SDimitry Andric Extension m_enabled_extensions; 447fe6060f1SDimitry Andric 4480b57cec5SDimitry Andric // lldb_private::Host calls should be used to launch a process for debugging, 4490b57cec5SDimitry Andric // and then the process should be attached to. When attaching to a process 4500b57cec5SDimitry Andric // lldb_private::Host calls should be used to locate the process to attach 4510b57cec5SDimitry Andric // to, and then this function should be called. 4520b57cec5SDimitry Andric NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, 4530b57cec5SDimitry Andric NativeDelegate &delegate); 4540b57cec5SDimitry Andric SetID(lldb::pid_t pid)4559dba64beSDimitry Andric void SetID(lldb::pid_t pid) { m_pid = pid; } 4569dba64beSDimitry Andric 4570b57cec5SDimitry Andric // interface for state handling 4580b57cec5SDimitry Andric void SetState(lldb::StateType state, bool notify_delegates = true); 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric // Derived classes need not implement this. It can be used as a hook to 4610b57cec5SDimitry Andric // clear internal caches that should be invalidated when stop ids change. 4620b57cec5SDimitry Andric // 4630b57cec5SDimitry Andric // Note this function is called with the state mutex obtained by the caller. 4640b57cec5SDimitry Andric virtual void DoStopIDBumped(uint32_t newBumpId); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric // interface for software breakpoints 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); 4690b57cec5SDimitry Andric Status RemoveSoftwareBreakpoint(lldb::addr_t addr); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric virtual llvm::Expected<llvm::ArrayRef<uint8_t>> 4720b57cec5SDimitry Andric GetSoftwareBreakpointTrapOpcode(size_t size_hint); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric /// Return the offset of the PC relative to the software breakpoint that was hit. If an 4750b57cec5SDimitry Andric /// architecture (e.g. arm) reports breakpoint hits before incrementing the PC, this offset 4760b57cec5SDimitry Andric /// will be 0. If an architecture (e.g. intel) reports breakpoints hits after incrementing the 4770b57cec5SDimitry Andric /// PC, this offset will be the size of the breakpoint opcode. 4780b57cec5SDimitry Andric virtual size_t GetSoftwareBreakpointPCOffset(); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric // Adjust the thread's PC after hitting a software breakpoint. On 4810b57cec5SDimitry Andric // architectures where the PC points after the breakpoint instruction, this 4820b57cec5SDimitry Andric // resets it to point to the breakpoint itself. 4830b57cec5SDimitry Andric void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric /// Notify the delegate that an exec occurred. 4860b57cec5SDimitry Andric /// 4870b57cec5SDimitry Andric /// Provide a mechanism for a delegate to clear out any exec- 4880b57cec5SDimitry Andric /// sensitive data. 48981ad6265SDimitry Andric virtual void NotifyDidExec(); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid); 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric private: 4940b57cec5SDimitry Andric void SynchronouslyNotifyProcessStateChanged(lldb::StateType state); 4950b57cec5SDimitry Andric llvm::Expected<SoftwareBreakpoint> 4960b57cec5SDimitry Andric EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); 4970b57cec5SDimitry Andric }; 4980b57cec5SDimitry Andric } // namespace lldb_private 4990b57cec5SDimitry Andric 5005ffd83dbSDimitry Andric #endif // LLDB_HOST_COMMON_NATIVEPROCESSPROTOCOL_H 501