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