LLDB  mainline
NativeProcessProtocol.h
Go to the documentation of this file.
1 //===-- NativeProcessProtocol.h ---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef liblldb_NativeProcessProtocol_h_
10 #define liblldb_NativeProcessProtocol_h_
11 
12 #include "NativeBreakpointList.h"
13 #include "NativeThreadProtocol.h"
14 #include "NativeWatchpointList.h"
15 #include "lldb/Host/Host.h"
16 #include "lldb/Host/MainLoop.h"
17 #include "lldb/Utility/ArchSpec.h"
18 #include "lldb/Utility/Status.h"
21 #include "lldb/lldb-types.h"
22 #include "llvm/ADT/ArrayRef.h"
23 #include "llvm/ADT/DenseSet.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Support/Error.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include <mutex>
28 #include <unordered_map>
29 #include <vector>
30 
31 namespace lldb_private {
32 class MemoryRegionInfo;
33 class ResumeActionList;
34 
35 // NativeProcessProtocol
37 public:
39 
40  virtual Status Resume(const ResumeActionList &resume_actions) = 0;
41 
42  virtual Status Halt() = 0;
43 
44  virtual Status Detach() = 0;
45 
46  /// Sends a process a UNIX signal \a signal.
47  ///
48  /// \return
49  /// Returns an error object.
50  virtual Status Signal(int signo) = 0;
51 
52  /// Tells a process to interrupt all operations as if by a Ctrl-C.
53  ///
54  /// The default implementation will send a local host's equivalent of
55  /// a SIGSTOP to the process via the NativeProcessProtocol::Signal()
56  /// operation.
57  ///
58  /// \return
59  /// Returns an error object.
60  virtual Status Interrupt();
61 
62  virtual Status Kill() = 0;
63 
64  // Tells a process not to stop the inferior on given signals and just
65  // reinject them back.
66  virtual Status IgnoreSignals(llvm::ArrayRef<int> signals);
67 
68  // Memory and memory region functions
69 
70  virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr,
71  MemoryRegionInfo &range_info);
72 
73  virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
74  size_t &bytes_read) = 0;
75 
76  Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
77  size_t &bytes_read);
78 
79  virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
80  size_t &bytes_written) = 0;
81 
82  virtual Status AllocateMemory(size_t size, uint32_t permissions,
83  lldb::addr_t &addr) = 0;
84 
85  virtual Status DeallocateMemory(lldb::addr_t addr) = 0;
86 
88 
89  virtual bool IsAlive() const;
90 
91  virtual size_t UpdateThreads() = 0;
92 
93  virtual const ArchSpec &GetArchitecture() const = 0;
94 
95  // Breakpoint functions
96  virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size,
97  bool hardware) = 0;
98 
99  virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false);
100 
101  // Hardware Breakpoint functions
102  virtual const HardwareBreakpointMap &GetHardwareBreakpointMap() const;
103 
104  virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size);
105 
107 
108  // Watchpoint functions
110 
111  virtual llvm::Optional<std::pair<uint32_t, uint32_t>>
113 
114  virtual Status SetWatchpoint(lldb::addr_t addr, size_t size,
115  uint32_t watch_flags, bool hardware);
116 
117  virtual Status RemoveWatchpoint(lldb::addr_t addr);
118 
119  // Accessors
120  lldb::pid_t GetID() const { return m_pid; }
121 
122  lldb::StateType GetState() const;
123 
124  bool IsRunning() const {
125  return m_state == lldb::eStateRunning || IsStepping();
126  }
127 
128  bool IsStepping() const { return m_state == lldb::eStateStepping; }
129 
130  bool CanResume() const { return m_state == lldb::eStateStopped; }
131 
133  return GetArchitecture().GetByteOrder();
134  }
135 
136  virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
137  GetAuxvData() const = 0;
138 
139  // Exit Status
140  virtual llvm::Optional<WaitStatus> GetExitStatus();
141 
142  virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange);
143 
144  // Access to threads
146 
148 
150 
152 
155  }
156 
157  // Access to inferior stdio
158  virtual int GetTerminalFileDescriptor() { return m_terminal_fd; }
159 
160  // Stop id interface
161 
162  uint32_t GetStopID() const;
163 
164  // Callbacks for low-level process state changes
166  public:
167  virtual ~NativeDelegate() {}
168 
169  virtual void InitializeDelegate(NativeProcessProtocol *process) = 0;
170 
171  virtual void ProcessStateChanged(NativeProcessProtocol *process,
172  lldb::StateType state) = 0;
173 
174  virtual void DidExec(NativeProcessProtocol *process) = 0;
175  };
176 
177  /// Register a native delegate.
178  ///
179  /// Clients can register nofication callbacks by passing in a
180  /// NativeDelegate impl and passing it into this function.
181  ///
182  /// Note: it is required that the lifetime of the
183  /// native_delegate outlive the NativeProcessProtocol.
184  ///
185  /// \param[in] native_delegate
186  /// A NativeDelegate impl to be called when certain events
187  /// happen within the NativeProcessProtocol or related threads.
188  ///
189  /// \return
190  /// true if the delegate was registered successfully;
191  /// false if the delegate was already registered.
192  ///
193  /// \see NativeProcessProtocol::NativeDelegate.
194  bool RegisterNativeDelegate(NativeDelegate &native_delegate);
195 
196  /// Unregister a native delegate previously registered.
197  ///
198  /// \param[in] native_delegate
199  /// A NativeDelegate impl previously registered with this process.
200  ///
201  /// \return Returns \b true if the NativeDelegate was
202  /// successfully removed from the process, \b false otherwise.
203  ///
204  /// \see NativeProcessProtocol::NativeDelegate
205  bool UnregisterNativeDelegate(NativeDelegate &native_delegate);
206 
207  virtual Status GetLoadedModuleFileSpec(const char *module_path,
208  FileSpec &file_spec) = 0;
209 
210  virtual Status GetFileLoadAddress(const llvm::StringRef &file_name,
211  lldb::addr_t &load_addr) = 0;
212 
213  class Factory {
214  public:
215  virtual ~Factory();
216  /// Launch a process for debugging.
217  ///
218  /// \param[in] launch_info
219  /// Information required to launch the process.
220  ///
221  /// \param[in] native_delegate
222  /// The delegate that will receive messages regarding the
223  /// inferior. Must outlive the NativeProcessProtocol
224  /// instance.
225  ///
226  /// \param[in] mainloop
227  /// The mainloop instance with which the process can register
228  /// callbacks. Must outlive the NativeProcessProtocol
229  /// instance.
230  ///
231  /// \return
232  /// A NativeProcessProtocol shared pointer if the operation succeeded or
233  /// an error object if it failed.
234  virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
235  Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
236  MainLoop &mainloop) const = 0;
237 
238  /// Attach to an existing process.
239  ///
240  /// \param[in] pid
241  /// pid of the process locatable
242  ///
243  /// \param[in] native_delegate
244  /// The delegate that will receive messages regarding the
245  /// inferior. Must outlive the NativeProcessProtocol
246  /// instance.
247  ///
248  /// \param[in] mainloop
249  /// The mainloop instance with which the process can register
250  /// callbacks. Must outlive the NativeProcessProtocol
251  /// instance.
252  ///
253  /// \return
254  /// A NativeProcessProtocol shared pointer if the operation succeeded or
255  /// an error object if it failed.
256  virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
257  Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
258  MainLoop &mainloop) const = 0;
259  };
260 
261  /// StartTracing API for starting a tracing instance with the
262  /// TraceOptions on a specific thread or process.
263  ///
264  /// \param[in] config
265  /// The configuration to use when starting tracing.
266  ///
267  /// \param[out] error
268  /// Status indicates what went wrong.
269  ///
270  /// \return
271  /// The API returns a user_id which can be used to get trace
272  /// data, trace configuration or stopping the trace instance.
273  /// The user_id is a key to identify and operate with a tracing
274  /// instance. It may refer to the complete process or a single
275  /// thread.
276  virtual lldb::user_id_t StartTrace(const TraceOptions &config,
277  Status &error) {
278  error.SetErrorString("Not implemented");
279  return LLDB_INVALID_UID;
280  }
281 
282  /// StopTracing API as the name suggests stops a tracing instance.
283  ///
284  /// \param[in] traceid
285  /// The user id of the trace intended to be stopped. Now a
286  /// user_id may map to multiple threads in which case this API
287  /// could be used to stop the tracing for a specific thread by
288  /// supplying its thread id.
289  ///
290  /// \param[in] thread
291  /// Thread is needed when the complete process is being traced
292  /// and the user wishes to stop tracing on a particular thread.
293  ///
294  /// \return
295  /// Status indicating what went wrong.
298  return Status("Not implemented");
299  }
300 
301  /// This API provides the trace data collected in the form of raw
302  /// data.
303  ///
304  /// \param[in] traceid thread
305  /// The traceid and thread provide the context for the trace
306  /// instance.
307  ///
308  /// \param[in] buffer
309  /// The buffer provides the destination buffer where the trace
310  /// data would be read to. The buffer should be truncated to the
311  /// filled length by this function.
312  ///
313  /// \param[in] offset
314  /// There is possibility to read partially the trace data from
315  /// a specified offset where in such cases the buffer provided
316  /// may be smaller than the internal trace collection container.
317  ///
318  /// \return
319  /// The size of the data actually read.
320  virtual Status GetData(lldb::user_id_t traceid, lldb::tid_t thread,
321  llvm::MutableArrayRef<uint8_t> &buffer,
322  size_t offset = 0) {
323  return Status("Not implemented");
324  }
325 
326  /// Similar API as above except it aims to provide any extra data
327  /// useful for decoding the actual trace data.
329  llvm::MutableArrayRef<uint8_t> &buffer,
330  size_t offset = 0) {
331  return Status("Not implemented");
332  }
333 
334  /// API to query the TraceOptions for a given user id
335  ///
336  /// \param[in] traceid
337  /// The user id of the tracing instance.
338  ///
339  /// \param[in] config
340  /// The thread id of the tracing instance, in case configuration
341  /// for a specific thread is needed should be specified in the
342  /// config.
343  ///
344  /// \param[out] error
345  /// Status indicates what went wrong.
346  ///
347  /// \param[out] config
348  /// The actual configuration being used for tracing.
349  virtual Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) {
350  return Status("Not implemented");
351  }
352 
353 protected:
356  llvm::SmallVector<uint8_t, 4> saved_opcodes;
357  llvm::ArrayRef<uint8_t> breakpoint_opcodes;
358  };
359 
360  std::unordered_map<lldb::addr_t, SoftwareBreakpoint> m_software_breakpoints;
362 
363  std::vector<std::unique_ptr<NativeThreadProtocol>> m_threads;
365  mutable std::recursive_mutex m_threads_mutex;
366 
368  mutable std::recursive_mutex m_state_mutex;
369 
370  llvm::Optional<WaitStatus> m_exit_status;
371 
372  std::recursive_mutex m_delegates_mutex;
373  std::vector<NativeDelegate *> m_delegates;
378 
379  // Set of signal numbers that LLDB directly injects back to inferior without
380  // stopping it.
381  llvm::DenseSet<int> m_signals_to_ignore;
382 
383  // lldb_private::Host calls should be used to launch a process for debugging,
384  // and then the process should be attached to. When attaching to a process
385  // lldb_private::Host calls should be used to locate the process to attach
386  // to, and then this function should be called.
387  NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
388  NativeDelegate &delegate);
389 
390  // interface for state handling
391  void SetState(lldb::StateType state, bool notify_delegates = true);
392 
393  // Derived classes need not implement this. It can be used as a hook to
394  // clear internal caches that should be invalidated when stop ids change.
395  //
396  // Note this function is called with the state mutex obtained by the caller.
397  virtual void DoStopIDBumped(uint32_t newBumpId);
398 
399  // interface for software breakpoints
400 
403 
404  virtual llvm::Expected<llvm::ArrayRef<uint8_t>>
405  GetSoftwareBreakpointTrapOpcode(size_t size_hint);
406 
407  /// Return the offset of the PC relative to the software breakpoint that was hit. If an
408  /// architecture (e.g. arm) reports breakpoint hits before incrementing the PC, this offset
409  /// will be 0. If an architecture (e.g. intel) reports breakpoints hits after incrementing the
410  /// PC, this offset will be the size of the breakpoint opcode.
411  virtual size_t GetSoftwareBreakpointPCOffset();
412 
413  // Adjust the thread's PC after hitting a software breakpoint. On
414  // architectures where the PC points after the breakpoint instruction, this
415  // resets it to point to the breakpoint itself.
417 
418  /// Notify the delegate that an exec occurred.
419  ///
420  /// Provide a mechanism for a delegate to clear out any exec-
421  /// sensitive data.
422  void NotifyDidExec();
423 
425 
426 private:
427  void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
428  llvm::Expected<SoftwareBreakpoint>
429  EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
430 };
431 } // namespace lldb_private
432 
433 #endif // #ifndef liblldb_NativeProcessProtocol_h_
virtual Status GetData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef< uint8_t > &buffer, size_t offset=0)
This API provides the trace data collected in the form of raw data.
virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)=0
NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, NativeDelegate &delegate)
virtual void InitializeDelegate(NativeProcessProtocol *process)=0
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
virtual Status RemoveWatchpoint(lldb::addr_t addr)
virtual void ProcessStateChanged(NativeProcessProtocol *process, lldb::StateType state)=0
virtual const NativeWatchpointList::WatchpointMap & GetWatchpointMap() const
virtual void DidExec(NativeProcessProtocol *process)=0
virtual llvm::Optional< WaitStatus > GetExitStatus()
virtual Status IgnoreSignals(llvm::ArrayRef< int > signals)
std::vector< NativeDelegate * > m_delegates
virtual const HardwareBreakpointMap & GetHardwareBreakpointMap() const
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size)
bool UnregisterNativeDelegate(NativeDelegate &native_delegate)
Unregister a native delegate previously registered.
virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange)
virtual Status DeallocateMemory(lldb::addr_t addr)=0
bool RegisterNativeDelegate(NativeDelegate &native_delegate)
Register a native delegate.
Process or thread is stopped and can be examined.
Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
#define LLDB_INVALID_UID
Definition: lldb-defines.h:91
virtual Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec)=0
NativeThreadProtocol * GetThreadByID(lldb::tid_t tid)
virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware=false)
llvm::Optional< WaitStatus > m_exit_status
virtual llvm::Optional< std::pair< uint32_t, uint32_t > > GetHardwareDebugSupportInfo() const
Status RemoveSoftwareBreakpoint(lldb::addr_t addr)
virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware)=0
uint64_t user_id_t
Definition: lldb-types.h:84
virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr)
virtual llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint)
virtual lldb::addr_t GetSharedLibraryInfoAddress()=0
virtual Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef< uint8_t > &buffer, size_t offset=0)
Similar API as above except it aims to provide any extra data useful for decoding the actual trace da...
virtual const ArchSpec & GetArchitecture() const =0
virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)=0
void NotifyDidExec()
Notify the delegate that an exec occurred.
virtual size_t GetSoftwareBreakpointPCOffset()
Return the offset of the PC relative to the software breakpoint that was hit.
uint64_t tid_t
Definition: lldb-types.h:86
virtual Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config)
API to query the TraceOptions for a given user id.
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
virtual void DoStopIDBumped(uint32_t newBumpId)
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > GetAuxvData() const =0
virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info)
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
virtual Status Resume(const ResumeActionList &resume_actions)=0
Process or thread is in the process of stepping and can not be examined.
virtual Status Interrupt()
Tells a process to interrupt all operations as if by a Ctrl-C.
void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread)
virtual Status StopTrace(lldb::user_id_t traceid, lldb::tid_t thread=LLDB_INVALID_THREAD_ID)
StopTracing API as the name suggests stops a tracing instance.
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint)
virtual Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr)=0
#define LLDB_INVALID_THREAD_ID
Definition: lldb-defines.h:93
uint64_t addr_t
Definition: lldb-types.h:83
std::map< lldb::addr_t, HardwareBreakpoint > HardwareBreakpointMap
virtual lldb::user_id_t StartTrace(const TraceOptions &config, Status &error)
StartTracing API for starting a tracing instance with the TraceOptions on a specific thread or proces...
void SetState(lldb::StateType state, bool notify_delegates=true)
std::map< lldb::addr_t, NativeWatchpoint > WatchpointMap
uint64_t pid_t
Definition: lldb-types.h:85
virtual Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr)=0
std::unordered_map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
virtual Status Signal(int signo)=0
Sends a process a UNIX signal signal.
std::vector< std::unique_ptr< NativeThreadProtocol > > m_threads
NativeThreadProtocol * GetThreadByIDUnlocked(lldb::tid_t tid)
An error handling class.
Definition: Status.h:44
NativeThreadProtocol * GetThreadAtIndex(uint32_t idx)
Process or thread is running and can&#39;t be examined.