1 //===-- NativeProcessProtocol.h ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_NativeProcessProtocol_h_
10 #define liblldb_NativeProcessProtocol_h_
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"
19 #include "lldb/Utility/TraceOptions.h"
20 #include "lldb/lldb-private-forward.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"
28 #include <unordered_map>
31 namespace lldb_private {
32 class MemoryRegionInfo;
33 class ResumeActionList;
35 // NativeProcessProtocol
36 class NativeProcessProtocol {
38 virtual ~NativeProcessProtocol() {}
40 virtual Status Resume(const ResumeActionList &resume_actions) = 0;
42 virtual Status Halt() = 0;
44 virtual Status Detach() = 0;
46 /// Sends a process a UNIX signal \a signal.
49 /// Returns an error object.
50 virtual Status Signal(int signo) = 0;
52 /// Tells a process to interrupt all operations as if by a Ctrl-C.
54 /// The default implementation will send a local host's equivalent of
55 /// a SIGSTOP to the process via the NativeProcessProtocol::Signal()
59 /// Returns an error object.
60 virtual Status Interrupt();
62 virtual Status Kill() = 0;
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);
68 // Memory and memory region functions
70 virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr,
71 MemoryRegionInfo &range_info);
73 virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
74 size_t &bytes_read) = 0;
76 Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
79 virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
80 size_t &bytes_written) = 0;
82 virtual Status AllocateMemory(size_t size, uint32_t permissions,
83 lldb::addr_t &addr) = 0;
85 virtual Status DeallocateMemory(lldb::addr_t addr) = 0;
87 virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0;
89 virtual bool IsAlive() const;
91 virtual size_t UpdateThreads() = 0;
93 virtual const ArchSpec &GetArchitecture() const = 0;
95 // Breakpoint functions
96 virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size,
99 virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false);
101 // Hardware Breakpoint functions
102 virtual const HardwareBreakpointMap &GetHardwareBreakpointMap() const;
104 virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size);
106 virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr);
108 // Watchpoint functions
109 virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const;
111 virtual llvm::Optional<std::pair<uint32_t, uint32_t>>
112 GetHardwareDebugSupportInfo() const;
114 virtual Status SetWatchpoint(lldb::addr_t addr, size_t size,
115 uint32_t watch_flags, bool hardware);
117 virtual Status RemoveWatchpoint(lldb::addr_t addr);
120 lldb::pid_t GetID() const { return m_pid; }
122 lldb::StateType GetState() const;
124 bool IsRunning() const {
125 return m_state == lldb::eStateRunning || IsStepping();
128 bool IsStepping() const { return m_state == lldb::eStateStepping; }
130 bool CanResume() const { return m_state == lldb::eStateStopped; }
132 lldb::ByteOrder GetByteOrder() const {
133 return GetArchitecture().GetByteOrder();
136 uint32_t GetAddressByteSize() const {
137 return GetArchitecture().GetAddressByteSize();
140 virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
141 GetAuxvData() const = 0;
144 virtual llvm::Optional<WaitStatus> GetExitStatus();
146 virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange);
149 NativeThreadProtocol *GetThreadAtIndex(uint32_t idx);
151 NativeThreadProtocol *GetThreadByID(lldb::tid_t tid);
153 void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; }
155 lldb::tid_t GetCurrentThreadID() { return m_current_thread_id; }
157 NativeThreadProtocol *GetCurrentThread() {
158 return GetThreadByID(m_current_thread_id);
161 // Access to inferior stdio
162 virtual int GetTerminalFileDescriptor() { return m_terminal_fd; }
166 uint32_t GetStopID() const;
168 // Callbacks for low-level process state changes
169 class NativeDelegate {
171 virtual ~NativeDelegate() {}
173 virtual void InitializeDelegate(NativeProcessProtocol *process) = 0;
175 virtual void ProcessStateChanged(NativeProcessProtocol *process,
176 lldb::StateType state) = 0;
178 virtual void DidExec(NativeProcessProtocol *process) = 0;
181 /// Register a native delegate.
183 /// Clients can register nofication callbacks by passing in a
184 /// NativeDelegate impl and passing it into this function.
186 /// Note: it is required that the lifetime of the
187 /// native_delegate outlive the NativeProcessProtocol.
189 /// \param[in] native_delegate
190 /// A NativeDelegate impl to be called when certain events
191 /// happen within the NativeProcessProtocol or related threads.
194 /// true if the delegate was registered successfully;
195 /// false if the delegate was already registered.
197 /// \see NativeProcessProtocol::NativeDelegate.
198 bool RegisterNativeDelegate(NativeDelegate &native_delegate);
200 /// Unregister a native delegate previously registered.
202 /// \param[in] native_delegate
203 /// A NativeDelegate impl previously registered with this process.
205 /// \return Returns \b true if the NativeDelegate was
206 /// successfully removed from the process, \b false otherwise.
208 /// \see NativeProcessProtocol::NativeDelegate
209 bool UnregisterNativeDelegate(NativeDelegate &native_delegate);
211 virtual Status GetLoadedModuleFileSpec(const char *module_path,
212 FileSpec &file_spec) = 0;
214 virtual Status GetFileLoadAddress(const llvm::StringRef &file_name,
215 lldb::addr_t &load_addr) = 0;
220 /// Launch a process for debugging.
222 /// \param[in] launch_info
223 /// Information required to launch the process.
225 /// \param[in] native_delegate
226 /// The delegate that will receive messages regarding the
227 /// inferior. Must outlive the NativeProcessProtocol
230 /// \param[in] mainloop
231 /// The mainloop instance with which the process can register
232 /// callbacks. Must outlive the NativeProcessProtocol
236 /// A NativeProcessProtocol shared pointer if the operation succeeded or
237 /// an error object if it failed.
238 virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
239 Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
240 MainLoop &mainloop) const = 0;
242 /// Attach to an existing process.
245 /// pid of the process locatable
247 /// \param[in] native_delegate
248 /// The delegate that will receive messages regarding the
249 /// inferior. Must outlive the NativeProcessProtocol
252 /// \param[in] mainloop
253 /// The mainloop instance with which the process can register
254 /// callbacks. Must outlive the NativeProcessProtocol
258 /// A NativeProcessProtocol shared pointer if the operation succeeded or
259 /// an error object if it failed.
260 virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
261 Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
262 MainLoop &mainloop) const = 0;
265 /// StartTracing API for starting a tracing instance with the
266 /// TraceOptions on a specific thread or process.
268 /// \param[in] config
269 /// The configuration to use when starting tracing.
271 /// \param[out] error
272 /// Status indicates what went wrong.
275 /// The API returns a user_id which can be used to get trace
276 /// data, trace configuration or stopping the trace instance.
277 /// The user_id is a key to identify and operate with a tracing
278 /// instance. It may refer to the complete process or a single
280 virtual lldb::user_id_t StartTrace(const TraceOptions &config,
282 error.SetErrorString("Not implemented");
283 return LLDB_INVALID_UID;
286 /// StopTracing API as the name suggests stops a tracing instance.
288 /// \param[in] traceid
289 /// The user id of the trace intended to be stopped. Now a
290 /// user_id may map to multiple threads in which case this API
291 /// could be used to stop the tracing for a specific thread by
292 /// supplying its thread id.
294 /// \param[in] thread
295 /// Thread is needed when the complete process is being traced
296 /// and the user wishes to stop tracing on a particular thread.
299 /// Status indicating what went wrong.
300 virtual Status StopTrace(lldb::user_id_t traceid,
301 lldb::tid_t thread = LLDB_INVALID_THREAD_ID) {
302 return Status("Not implemented");
305 /// This API provides the trace data collected in the form of raw
308 /// \param[in] traceid thread
309 /// The traceid and thread provide the context for the trace
312 /// \param[in] buffer
313 /// The buffer provides the destination buffer where the trace
314 /// data would be read to. The buffer should be truncated to the
315 /// filled length by this function.
317 /// \param[in] offset
318 /// There is possibility to read partially the trace data from
319 /// a specified offset where in such cases the buffer provided
320 /// may be smaller than the internal trace collection container.
323 /// The size of the data actually read.
324 virtual Status GetData(lldb::user_id_t traceid, lldb::tid_t thread,
325 llvm::MutableArrayRef<uint8_t> &buffer,
327 return Status("Not implemented");
330 /// Similar API as above except it aims to provide any extra data
331 /// useful for decoding the actual trace data.
332 virtual Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread,
333 llvm::MutableArrayRef<uint8_t> &buffer,
335 return Status("Not implemented");
338 /// API to query the TraceOptions for a given user id
340 /// \param[in] traceid
341 /// The user id of the tracing instance.
343 /// \param[in] config
344 /// The thread id of the tracing instance, in case configuration
345 /// for a specific thread is needed should be specified in the
348 /// \param[out] error
349 /// Status indicates what went wrong.
351 /// \param[out] config
352 /// The actual configuration being used for tracing.
353 virtual Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) {
354 return Status("Not implemented");
358 struct SoftwareBreakpoint {
360 llvm::SmallVector<uint8_t, 4> saved_opcodes;
361 llvm::ArrayRef<uint8_t> breakpoint_opcodes;
364 std::unordered_map<lldb::addr_t, SoftwareBreakpoint> m_software_breakpoints;
367 std::vector<std::unique_ptr<NativeThreadProtocol>> m_threads;
368 lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID;
369 mutable std::recursive_mutex m_threads_mutex;
371 lldb::StateType m_state = lldb::eStateInvalid;
372 mutable std::recursive_mutex m_state_mutex;
374 llvm::Optional<WaitStatus> m_exit_status;
376 std::recursive_mutex m_delegates_mutex;
377 std::vector<NativeDelegate *> m_delegates;
378 NativeWatchpointList m_watchpoint_list;
379 HardwareBreakpointMap m_hw_breakpoints_map;
381 uint32_t m_stop_id = 0;
383 // Set of signal numbers that LLDB directly injects back to inferior without
385 llvm::DenseSet<int> m_signals_to_ignore;
387 // lldb_private::Host calls should be used to launch a process for debugging,
388 // and then the process should be attached to. When attaching to a process
389 // lldb_private::Host calls should be used to locate the process to attach
390 // to, and then this function should be called.
391 NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
392 NativeDelegate &delegate);
394 // interface for state handling
395 void SetState(lldb::StateType state, bool notify_delegates = true);
397 // Derived classes need not implement this. It can be used as a hook to
398 // clear internal caches that should be invalidated when stop ids change.
400 // Note this function is called with the state mutex obtained by the caller.
401 virtual void DoStopIDBumped(uint32_t newBumpId);
403 // interface for software breakpoints
405 Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
406 Status RemoveSoftwareBreakpoint(lldb::addr_t addr);
408 virtual llvm::Expected<llvm::ArrayRef<uint8_t>>
409 GetSoftwareBreakpointTrapOpcode(size_t size_hint);
411 /// Return the offset of the PC relative to the software breakpoint that was hit. If an
412 /// architecture (e.g. arm) reports breakpoint hits before incrementing the PC, this offset
413 /// will be 0. If an architecture (e.g. intel) reports breakpoints hits after incrementing the
414 /// PC, this offset will be the size of the breakpoint opcode.
415 virtual size_t GetSoftwareBreakpointPCOffset();
417 // Adjust the thread's PC after hitting a software breakpoint. On
418 // architectures where the PC points after the breakpoint instruction, this
419 // resets it to point to the breakpoint itself.
420 void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread);
422 /// Notify the delegate that an exec occurred.
424 /// Provide a mechanism for a delegate to clear out any exec-
426 void NotifyDidExec();
428 NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
431 void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
432 llvm::Expected<SoftwareBreakpoint>
433 EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
435 } // namespace lldb_private
437 #endif // #ifndef liblldb_NativeProcessProtocol_h_