1af245d11STodd Fiala //===-- NativeProcessLinux.h ---------------------------------- -*- C++ -*-===// 2af245d11STodd Fiala // 3af245d11STodd Fiala // The LLVM Compiler Infrastructure 4af245d11STodd Fiala // 5af245d11STodd Fiala // This file is distributed under the University of Illinois Open Source 6af245d11STodd Fiala // License. See LICENSE.TXT for details. 7af245d11STodd Fiala // 8af245d11STodd Fiala //===----------------------------------------------------------------------===// 9af245d11STodd Fiala 10af245d11STodd Fiala #ifndef liblldb_NativeProcessLinux_H_ 11af245d11STodd Fiala #define liblldb_NativeProcessLinux_H_ 12af245d11STodd Fiala 13af245d11STodd Fiala // C++ Includes 14af245d11STodd Fiala #include <unordered_set> 15af245d11STodd Fiala 16af245d11STodd Fiala // Other libraries and framework includes 17af245d11STodd Fiala #include "lldb/Core/ArchSpec.h" 18af245d11STodd Fiala #include "lldb/lldb-types.h" 19af245d11STodd Fiala #include "lldb/Host/Debug.h" 20*d3173f34SChaoren Lin #include "lldb/Host/FileSpec.h" 2139de3110SZachary Turner #include "lldb/Host/HostThread.h" 22af245d11STodd Fiala #include "lldb/Host/Mutex.h" 23af245d11STodd Fiala #include "lldb/Target/MemoryRegionInfo.h" 24af245d11STodd Fiala 252fe1d0abSChaoren Lin #include "lldb/Host/common/NativeProcessProtocol.h" 268c8ff7afSPavel Labath #include "NativeThreadLinux.h" 27af245d11STodd Fiala 28db264a6dSTamas Berghammer namespace lldb_private { 29af245d11STodd Fiala class Error; 30af245d11STodd Fiala class Module; 31af245d11STodd Fiala class Scalar; 32af245d11STodd Fiala 33db264a6dSTamas Berghammer namespace process_linux { 34af245d11STodd Fiala /// @class NativeProcessLinux 35af245d11STodd Fiala /// @brief Manages communication with the inferior (debugee) process. 36af245d11STodd Fiala /// 37af245d11STodd Fiala /// Upon construction, this class prepares and launches an inferior process for 38af245d11STodd Fiala /// debugging. 39af245d11STodd Fiala /// 40af245d11STodd Fiala /// Changes in the inferior process state are broadcasted. 41af245d11STodd Fiala class NativeProcessLinux: public NativeProcessProtocol 42af245d11STodd Fiala { 43af245d11STodd Fiala public: 44af245d11STodd Fiala 45db264a6dSTamas Berghammer static Error 46af245d11STodd Fiala LaunchProcess ( 47af245d11STodd Fiala Module *exe_module, 48af245d11STodd Fiala ProcessLaunchInfo &launch_info, 49db264a6dSTamas Berghammer NativeProcessProtocol::NativeDelegate &native_delegate, 50af245d11STodd Fiala NativeProcessProtocolSP &native_process_sp); 51af245d11STodd Fiala 52db264a6dSTamas Berghammer static Error 53af245d11STodd Fiala AttachToProcess ( 54af245d11STodd Fiala lldb::pid_t pid, 55db264a6dSTamas Berghammer NativeProcessProtocol::NativeDelegate &native_delegate, 56af245d11STodd Fiala NativeProcessProtocolSP &native_process_sp); 57af245d11STodd Fiala 58068f8a7eSTamas Berghammer //------------------------------------------------------------------------------ 59068f8a7eSTamas Berghammer /// @class Operation 60068f8a7eSTamas Berghammer /// @brief Represents a NativeProcessLinux operation. 61068f8a7eSTamas Berghammer /// 62068f8a7eSTamas Berghammer /// Under Linux, it is not possible to ptrace() from any other thread but the 63068f8a7eSTamas Berghammer /// one that spawned or attached to the process from the start. Therefore, when 64068f8a7eSTamas Berghammer /// a NativeProcessLinux is asked to deliver or change the state of an inferior 65068f8a7eSTamas Berghammer /// process the operation must be "funneled" to a specific thread to perform the 66068f8a7eSTamas Berghammer /// task. The Operation class provides an abstract base for all services the 67068f8a7eSTamas Berghammer /// NativeProcessLinux must perform via the single virtual function Execute, thus 68068f8a7eSTamas Berghammer /// encapsulating the code that needs to run in the privileged context. 69068f8a7eSTamas Berghammer class Operation 70068f8a7eSTamas Berghammer { 71068f8a7eSTamas Berghammer public: 72068f8a7eSTamas Berghammer Operation () : m_error() { } 73068f8a7eSTamas Berghammer 74068f8a7eSTamas Berghammer virtual 75068f8a7eSTamas Berghammer ~Operation() {} 76068f8a7eSTamas Berghammer 77068f8a7eSTamas Berghammer virtual void 78068f8a7eSTamas Berghammer Execute (NativeProcessLinux *process) = 0; 79068f8a7eSTamas Berghammer 80068f8a7eSTamas Berghammer const Error & 81068f8a7eSTamas Berghammer GetError () const { return m_error; } 82068f8a7eSTamas Berghammer 83068f8a7eSTamas Berghammer protected: 84068f8a7eSTamas Berghammer Error m_error; 85068f8a7eSTamas Berghammer }; 86068f8a7eSTamas Berghammer 87068f8a7eSTamas Berghammer typedef std::unique_ptr<Operation> OperationUP; 88068f8a7eSTamas Berghammer 89af245d11STodd Fiala // --------------------------------------------------------------------- 90af245d11STodd Fiala // NativeProcessProtocol Interface 91af245d11STodd Fiala // --------------------------------------------------------------------- 92af245d11STodd Fiala Error 93af245d11STodd Fiala Resume (const ResumeActionList &resume_actions) override; 94af245d11STodd Fiala 95af245d11STodd Fiala Error 96af245d11STodd Fiala Halt () override; 97af245d11STodd Fiala 98af245d11STodd Fiala Error 99af245d11STodd Fiala Detach () override; 100af245d11STodd Fiala 101af245d11STodd Fiala Error 102af245d11STodd Fiala Signal (int signo) override; 103af245d11STodd Fiala 104af245d11STodd Fiala Error 105e9547b80SChaoren Lin Interrupt () override; 106e9547b80SChaoren Lin 107e9547b80SChaoren Lin Error 108af245d11STodd Fiala Kill () override; 109af245d11STodd Fiala 110af245d11STodd Fiala Error 111af245d11STodd Fiala GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; 112af245d11STodd Fiala 113af245d11STodd Fiala Error 1143eb4b458SChaoren Lin ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; 115af245d11STodd Fiala 116af245d11STodd Fiala Error 1173eb4b458SChaoren Lin ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; 118af245d11STodd Fiala 119af245d11STodd Fiala Error 1203eb4b458SChaoren Lin WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override; 1213eb4b458SChaoren Lin 1223eb4b458SChaoren Lin Error 1233eb4b458SChaoren Lin AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) override; 124af245d11STodd Fiala 125af245d11STodd Fiala Error 126af245d11STodd Fiala DeallocateMemory (lldb::addr_t addr) override; 127af245d11STodd Fiala 128af245d11STodd Fiala lldb::addr_t 129af245d11STodd Fiala GetSharedLibraryInfoAddress () override; 130af245d11STodd Fiala 131af245d11STodd Fiala size_t 132af245d11STodd Fiala UpdateThreads () override; 133af245d11STodd Fiala 134af245d11STodd Fiala bool 135af245d11STodd Fiala GetArchitecture (ArchSpec &arch) const override; 136af245d11STodd Fiala 137af245d11STodd Fiala Error 138af245d11STodd Fiala SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override; 139af245d11STodd Fiala 14045f5cb31SPavel Labath Error 14145f5cb31SPavel Labath SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; 14245f5cb31SPavel Labath 14345f5cb31SPavel Labath Error 14445f5cb31SPavel Labath RemoveWatchpoint (lldb::addr_t addr) override; 14545f5cb31SPavel Labath 146af245d11STodd Fiala void 147af245d11STodd Fiala DoStopIDBumped (uint32_t newBumpId) override; 148af245d11STodd Fiala 1498bc34f4dSOleksiy Vyalov void 1508bc34f4dSOleksiy Vyalov Terminate () override; 1518bc34f4dSOleksiy Vyalov 152068f8a7eSTamas Berghammer Error 153068f8a7eSTamas Berghammer GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override; 154068f8a7eSTamas Berghammer 155af245d11STodd Fiala // --------------------------------------------------------------------- 156af245d11STodd Fiala // Interface used by NativeRegisterContext-derived classes. 157af245d11STodd Fiala // --------------------------------------------------------------------- 15897ccc294SChaoren Lin Error 159068f8a7eSTamas Berghammer DoOperation(Operation* op); 160af245d11STodd Fiala 1617cb18bf5STamas Berghammer Error 162068f8a7eSTamas Berghammer DoOperation(OperationUP op) { return DoOperation(op.get()); } 163068f8a7eSTamas Berghammer 164068f8a7eSTamas Berghammer static long 165068f8a7eSTamas Berghammer PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error); 1667cb18bf5STamas Berghammer 167af245d11STodd Fiala protected: 168af245d11STodd Fiala // --------------------------------------------------------------------- 169af245d11STodd Fiala // NativeProcessProtocol protected interface 170af245d11STodd Fiala // --------------------------------------------------------------------- 171af245d11STodd Fiala Error 172af245d11STodd Fiala GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override; 173af245d11STodd Fiala 174af245d11STodd Fiala private: 175af245d11STodd Fiala 1761107b5a5SPavel Labath class Monitor; 1771107b5a5SPavel Labath 178db264a6dSTamas Berghammer ArchSpec m_arch; 179af245d11STodd Fiala 1801107b5a5SPavel Labath std::unique_ptr<Monitor> m_monitor_up; 181af245d11STodd Fiala 182db264a6dSTamas Berghammer LazyBool m_supports_mem_region; 183af245d11STodd Fiala std::vector<MemoryRegionInfo> m_mem_region_cache; 184db264a6dSTamas Berghammer Mutex m_mem_region_cache_mutex; 185af245d11STodd Fiala 186d8c338d4STamas Berghammer // List of thread ids stepping with a breakpoint with the address of 187d8c338d4STamas Berghammer // the relevan breakpoint 188d8c338d4STamas Berghammer std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint; 189d8c338d4STamas Berghammer 190af245d11STodd Fiala /// @class LauchArgs 191af245d11STodd Fiala /// 192af245d11STodd Fiala /// @brief Simple structure to pass data to the thread responsible for 193af245d11STodd Fiala /// launching a child process. 194bd7cbc5aSPavel Labath struct LaunchArgs 195af245d11STodd Fiala { 196bd7cbc5aSPavel Labath LaunchArgs(Module *module, 197af245d11STodd Fiala char const **argv, 198af245d11STodd Fiala char const **envp, 199*d3173f34SChaoren Lin const FileSpec &stdin_file_spec, 200*d3173f34SChaoren Lin const FileSpec &stdout_file_spec, 201*d3173f34SChaoren Lin const FileSpec &stderr_file_spec, 202*d3173f34SChaoren Lin const FileSpec &working_dir, 203db264a6dSTamas Berghammer const ProcessLaunchInfo &launch_info); 204af245d11STodd Fiala 205af245d11STodd Fiala ~LaunchArgs(); 206af245d11STodd Fiala 207db264a6dSTamas Berghammer Module *m_module; // The executable image to launch. 208af245d11STodd Fiala char const **m_argv; // Process arguments. 209af245d11STodd Fiala char const **m_envp; // Process environment. 210*d3173f34SChaoren Lin const FileSpec m_stdin_file_spec; // Redirect stdin if not empty. 211*d3173f34SChaoren Lin const FileSpec m_stdout_file_spec; // Redirect stdout if not empty. 212*d3173f34SChaoren Lin const FileSpec m_stderr_file_spec; // Redirect stderr if not empty. 213*d3173f34SChaoren Lin const FileSpec m_working_dir; // Working directory or empty. 214db264a6dSTamas Berghammer const ProcessLaunchInfo &m_launch_info; 215af245d11STodd Fiala }; 216af245d11STodd Fiala 217bd7cbc5aSPavel Labath typedef std::function<::pid_t(Error &)> InitialOperation; 218af245d11STodd Fiala 219af245d11STodd Fiala // --------------------------------------------------------------------- 220af245d11STodd Fiala // Private Instance Methods 221af245d11STodd Fiala // --------------------------------------------------------------------- 222af245d11STodd Fiala NativeProcessLinux (); 223af245d11STodd Fiala 224af245d11STodd Fiala /// Launches an inferior process ready for debugging. Forms the 225af245d11STodd Fiala /// implementation of Process::DoLaunch. 226af245d11STodd Fiala void 227af245d11STodd Fiala LaunchInferior ( 228af245d11STodd Fiala Module *module, 229af245d11STodd Fiala char const *argv[], 230af245d11STodd Fiala char const *envp[], 231*d3173f34SChaoren Lin const FileSpec &stdin_file_spec, 232*d3173f34SChaoren Lin const FileSpec &stdout_file_spec, 233*d3173f34SChaoren Lin const FileSpec &stderr_file_spec, 234*d3173f34SChaoren Lin const FileSpec &working_dir, 235db264a6dSTamas Berghammer const ProcessLaunchInfo &launch_info, 236af245d11STodd Fiala Error &error); 237af245d11STodd Fiala 238af245d11STodd Fiala /// Attaches to an existing process. Forms the 2390cbf0b13STamas Berghammer /// implementation of Process::DoAttach 240af245d11STodd Fiala void 241af245d11STodd Fiala AttachToInferior (lldb::pid_t pid, Error &error); 242af245d11STodd Fiala 243af245d11STodd Fiala void 244bd7cbc5aSPavel Labath StartMonitorThread(const InitialOperation &operation, Error &error); 2451107b5a5SPavel Labath 246bd7cbc5aSPavel Labath ::pid_t 247bd7cbc5aSPavel Labath Launch(LaunchArgs *args, Error &error); 248af245d11STodd Fiala 249bd7cbc5aSPavel Labath ::pid_t 250bd7cbc5aSPavel Labath Attach(lldb::pid_t pid, Error &error); 251af245d11STodd Fiala 25297ccc294SChaoren Lin static Error 253af245d11STodd Fiala SetDefaultPtraceOpts(const lldb::pid_t); 254af245d11STodd Fiala 255af245d11STodd Fiala static bool 256*d3173f34SChaoren Lin DupDescriptor(const FileSpec &file_spec, int fd, int flags); 257af245d11STodd Fiala 2581107b5a5SPavel Labath static void * 2591107b5a5SPavel Labath MonitorThread(void *baton); 2601107b5a5SPavel Labath 2611107b5a5SPavel Labath void 2621107b5a5SPavel Labath MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status); 263af245d11STodd Fiala 264af245d11STodd Fiala void 265426bdf88SPavel Labath WaitForNewThread(::pid_t tid); 266426bdf88SPavel Labath 267426bdf88SPavel Labath void 268af245d11STodd Fiala MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid); 269af245d11STodd Fiala 270af245d11STodd Fiala void 271c16f5dcaSChaoren Lin MonitorTrace(lldb::pid_t pid, NativeThreadProtocolSP thread_sp); 272c16f5dcaSChaoren Lin 273c16f5dcaSChaoren Lin void 274c16f5dcaSChaoren Lin MonitorBreakpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp); 275c16f5dcaSChaoren Lin 276c16f5dcaSChaoren Lin void 277c16f5dcaSChaoren Lin MonitorWatchpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp, uint32_t wp_index); 278c16f5dcaSChaoren Lin 279c16f5dcaSChaoren Lin void 280af245d11STodd Fiala MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited); 281af245d11STodd Fiala 282e7708688STamas Berghammer bool 283e7708688STamas Berghammer SupportHardwareSingleStepping() const; 284e7708688STamas Berghammer 285e7708688STamas Berghammer Error 286e7708688STamas Berghammer SetupSoftwareSingleStepping(NativeThreadProtocolSP thread_sp); 287e7708688STamas Berghammer 288af245d11STodd Fiala #if 0 289af245d11STodd Fiala static ::ProcessMessage::CrashReason 290af245d11STodd Fiala GetCrashReasonForSIGSEGV(const siginfo_t *info); 291af245d11STodd Fiala 292af245d11STodd Fiala static ::ProcessMessage::CrashReason 293af245d11STodd Fiala GetCrashReasonForSIGILL(const siginfo_t *info); 294af245d11STodd Fiala 295af245d11STodd Fiala static ::ProcessMessage::CrashReason 296af245d11STodd Fiala GetCrashReasonForSIGFPE(const siginfo_t *info); 297af245d11STodd Fiala 298af245d11STodd Fiala static ::ProcessMessage::CrashReason 299af245d11STodd Fiala GetCrashReasonForSIGBUS(const siginfo_t *info); 300af245d11STodd Fiala #endif 301af245d11STodd Fiala 302af245d11STodd Fiala bool 303af245d11STodd Fiala HasThreadNoLock (lldb::tid_t thread_id); 304af245d11STodd Fiala 305af245d11STodd Fiala NativeThreadProtocolSP 306af245d11STodd Fiala MaybeGetThreadNoLock (lldb::tid_t thread_id); 307af245d11STodd Fiala 308af245d11STodd Fiala bool 309af245d11STodd Fiala StopTrackingThread (lldb::tid_t thread_id); 310af245d11STodd Fiala 311af245d11STodd Fiala NativeThreadProtocolSP 312af245d11STodd Fiala AddThread (lldb::tid_t thread_id); 313af245d11STodd Fiala 314af245d11STodd Fiala Error 31563c8be95STamas Berghammer GetSoftwareBreakpointPCOffset (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size); 316af245d11STodd Fiala 317af245d11STodd Fiala Error 318af245d11STodd Fiala FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp); 319af245d11STodd Fiala 320af245d11STodd Fiala /// Writes a siginfo_t structure corresponding to the given thread ID to the 321af245d11STodd Fiala /// memory region pointed to by @p siginfo. 32297ccc294SChaoren Lin Error 32397ccc294SChaoren Lin GetSignalInfo(lldb::tid_t tid, void *siginfo); 324af245d11STodd Fiala 325af245d11STodd Fiala /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) 326af245d11STodd Fiala /// corresponding to the given thread ID to the memory pointed to by @p 327af245d11STodd Fiala /// message. 32897ccc294SChaoren Lin Error 329af245d11STodd Fiala GetEventMessage(lldb::tid_t tid, unsigned long *message); 330af245d11STodd Fiala 331af245d11STodd Fiala /// Resumes the given thread. If @p signo is anything but 332af245d11STodd Fiala /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. 33397ccc294SChaoren Lin Error 334af245d11STodd Fiala Resume(lldb::tid_t tid, uint32_t signo); 335af245d11STodd Fiala 336af245d11STodd Fiala /// Single steps the given thread. If @p signo is anything but 337af245d11STodd Fiala /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. 33897ccc294SChaoren Lin Error 339af245d11STodd Fiala SingleStep(lldb::tid_t tid, uint32_t signo); 340af245d11STodd Fiala 341511e5cdcSTodd Fiala void 342fa03ad2eSChaoren Lin NotifyThreadDeath (lldb::tid_t tid); 343fa03ad2eSChaoren Lin 344db264a6dSTamas Berghammer Error 345af245d11STodd Fiala Detach(lldb::tid_t tid); 34686fd8e45SChaoren Lin 347c076559aSPavel Labath 348c076559aSPavel Labath // Typedefs. 349c076559aSPavel Labath typedef std::unordered_set<lldb::tid_t> ThreadIDSet; 350c076559aSPavel Labath 3511dbc6c9cSPavel Labath // This method is requests a stop on all threads which are still running. It sets up a 3521dbc6c9cSPavel Labath // deferred delegate notification, which will fire once threads report as stopped. The 3531dbc6c9cSPavel Labath // triggerring_tid will be set as the current thread (main stop reason). 354c076559aSPavel Labath void 355337f3eb9SPavel Labath StopRunningThreads(lldb::tid_t triggering_tid); 356c076559aSPavel Labath 357c076559aSPavel Labath struct PendingNotification 358c076559aSPavel Labath { 359337f3eb9SPavel Labath PendingNotification (lldb::tid_t triggering_tid): 360337f3eb9SPavel Labath triggering_tid (triggering_tid), 361108c325dSPavel Labath wait_for_stop_tids () 362337f3eb9SPavel Labath { 363337f3eb9SPavel Labath } 364337f3eb9SPavel Labath 365c076559aSPavel Labath const lldb::tid_t triggering_tid; 366c076559aSPavel Labath ThreadIDSet wait_for_stop_tids; 367c076559aSPavel Labath }; 368c076559aSPavel Labath typedef std::unique_ptr<PendingNotification> PendingNotificationUP; 369c076559aSPavel Labath 3709eb1ecb9SPavel Labath // Notify the delegate if all threads have stopped. 3719eb1ecb9SPavel Labath void SignalIfAllThreadsStopped(); 372c076559aSPavel Labath 373c076559aSPavel Labath void 374c076559aSPavel Labath RequestStopOnAllRunningThreads(); 375c076559aSPavel Labath 3765eb721edSPavel Labath Error 3775eb721edSPavel Labath ThreadDidStop(lldb::tid_t tid, bool initiated_by_llgs); 378c076559aSPavel Labath 3791dbc6c9cSPavel Labath // Resume the thread with the given thread id using the request_thread_resume_function 3801dbc6c9cSPavel Labath // called. If error_when_already_running is then then an error is raised if we think this 3811dbc6c9cSPavel Labath // thread is already running. 3825eb721edSPavel Labath Error 3831dbc6c9cSPavel Labath ResumeThread(lldb::tid_t tid, NativeThreadLinux::ResumeThreadFunction request_thread_resume_function, 3845eb721edSPavel Labath bool error_when_already_running); 385c076559aSPavel Labath 386c076559aSPavel Labath void 387ed89c7feSPavel Labath DoStopThreads(PendingNotificationUP &¬ification_up); 388c076559aSPavel Labath 389c076559aSPavel Labath void 3908c8ff7afSPavel Labath ThreadWasCreated (lldb::tid_t tid); 391c076559aSPavel Labath 392c076559aSPavel Labath // Member variables. 393c076559aSPavel Labath PendingNotificationUP m_pending_notification_up; 394af245d11STodd Fiala }; 395db264a6dSTamas Berghammer 396db264a6dSTamas Berghammer } // namespace process_linux 397db264a6dSTamas Berghammer } // namespace lldb_private 398af245d11STodd Fiala 399af245d11STodd Fiala #endif // #ifndef liblldb_NativeProcessLinux_H_ 400