summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
blob: c94a78bd2ea1080500f5e85f98b87d75fd0cd75d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
//===-- NativeProcessLinux.h ---------------------------------- -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_NativeProcessLinux_H_
#define liblldb_NativeProcessLinux_H_

// C Includes
#include <semaphore.h>
#include <signal.h>

// C++ Includes
#include <unordered_set>

// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/lldb-types.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/MemoryRegionInfo.h"

#include "Host/common/NativeProcessProtocol.h"

namespace lldb_private
{
    class Error;
    class Module;
    class Scalar;

    /// @class NativeProcessLinux
    /// @brief Manages communication with the inferior (debugee) process.
    ///
    /// Upon construction, this class prepares and launches an inferior process for
    /// debugging.
    ///
    /// Changes in the inferior process state are broadcasted.
    class NativeProcessLinux: public NativeProcessProtocol
    {
    public:

        // ---------------------------------------------------------------------
        // Public Static Methods
        // ---------------------------------------------------------------------
        static lldb_private::Error
        LaunchProcess (
            Module *exe_module,
            ProcessLaunchInfo &launch_info,
            lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
            NativeProcessProtocolSP &native_process_sp);

        static lldb_private::Error
        AttachToProcess (
            lldb::pid_t pid,
            lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
            NativeProcessProtocolSP &native_process_sp);

        // ---------------------------------------------------------------------
        // Public Instance Methods
        // ---------------------------------------------------------------------

        ~NativeProcessLinux() override;

        // ---------------------------------------------------------------------
        // NativeProcessProtocol Interface
        // ---------------------------------------------------------------------
        Error
        Resume (const ResumeActionList &resume_actions) override;

        Error
        Halt () override;

        Error
        Detach () override;

        Error
        Signal (int signo) override;

        Error
        Kill () override;

        Error
        GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) override;

        Error
        ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) override;

        Error
        WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) override;

        Error
        AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) override;

        Error
        DeallocateMemory (lldb::addr_t addr) override;

        lldb::addr_t
        GetSharedLibraryInfoAddress () override;

        size_t
        UpdateThreads () override;

        bool
        GetArchitecture (ArchSpec &arch) const override;

        Error
        SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override;

        void
        DoStopIDBumped (uint32_t newBumpId) override;

        // ---------------------------------------------------------------------
        // Interface used by NativeRegisterContext-derived classes.
        // ---------------------------------------------------------------------

        /// Reads the contents from the register identified by the given (architecture
        /// dependent) offset.
        ///
        /// This method is provided for use by RegisterContextLinux derivatives.
        bool
        ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
                          unsigned size, lldb_private::RegisterValue &value);

        /// Writes the given value to the register identified by the given
        /// (architecture dependent) offset.
        ///
        /// This method is provided for use by RegisterContextLinux derivatives.
        bool
        WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
                           const lldb_private::RegisterValue &value);

        /// Reads all general purpose registers into the specified buffer.
        bool
        ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);

        /// Reads generic floating point registers into the specified buffer.
        bool
        ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);

        /// Reads the specified register set into the specified buffer.
        /// For instance, the extended floating-point register set.
        bool
        ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);

        /// Writes all general purpose registers into the specified buffer.
        bool
        WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);

        /// Writes generic floating point registers into the specified buffer.
        bool
        WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);

        /// Writes the specified register set into the specified buffer.
        /// For instance, the extended floating-point register set.
        bool
        WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
        
    protected:
        // ---------------------------------------------------------------------
        // NativeProcessProtocol protected interface
        // ---------------------------------------------------------------------
        Error
        GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override;

    private:

        lldb_private::ArchSpec m_arch;

        HostThread m_operation_thread;
        HostThread m_monitor_thread;

        // current operation which must be executed on the priviliged thread
        void *m_operation;
        lldb_private::Mutex m_operation_mutex;

        // semaphores notified when Operation is ready to be processed and when
        // the operation is complete.
        sem_t m_operation_pending;
        sem_t m_operation_done;

        // Set of tids we're waiting to stop before we notify the delegate of
        // the stopped state.  We only notify the delegate after all threads
        // ordered to stop have signaled their stop.
        std::unordered_set<lldb::tid_t> m_wait_for_stop_tids;
        lldb_private::Mutex m_wait_for_stop_tids_mutex;

        lldb_private::LazyBool m_supports_mem_region;
        std::vector<MemoryRegionInfo> m_mem_region_cache;
        lldb_private::Mutex m_mem_region_cache_mutex;


        struct OperationArgs
        {
            OperationArgs(NativeProcessLinux *monitor);

            ~OperationArgs();

            NativeProcessLinux *m_monitor;      // The monitor performing the attach.
            sem_t m_semaphore;              // Posted to once operation complete.
            lldb_private::Error m_error;    // Set if process operation failed.
        };

        /// @class LauchArgs
        ///
        /// @brief Simple structure to pass data to the thread responsible for
        /// launching a child process.
        struct LaunchArgs : OperationArgs
        {
            LaunchArgs(NativeProcessLinux *monitor,
                    lldb_private::Module *module,
                    char const **argv,
                    char const **envp,
                    const char *stdin_path,
                    const char *stdout_path,
                    const char *stderr_path,
                    const char *working_dir,
                    const lldb_private::ProcessLaunchInfo &launch_info);

            ~LaunchArgs();

            lldb_private::Module *m_module; // The executable image to launch.
            char const **m_argv;            // Process arguments.
            char const **m_envp;            // Process environment.
            const char *m_stdin_path;       // Redirect stdin or NULL.
            const char *m_stdout_path;      // Redirect stdout or NULL.
            const char *m_stderr_path;      // Redirect stderr or NULL.
            const char *m_working_dir;      // Working directory or NULL.
            const lldb_private::ProcessLaunchInfo &m_launch_info;
        };

        struct AttachArgs : OperationArgs
        {
            AttachArgs(NativeProcessLinux *monitor,
                       lldb::pid_t pid);

            ~AttachArgs();

            lldb::pid_t m_pid;              // pid of the process to be attached.
        };

        // ---------------------------------------------------------------------
        // Private Instance Methods
        // ---------------------------------------------------------------------
        NativeProcessLinux ();

        /// Launches an inferior process ready for debugging.  Forms the
        /// implementation of Process::DoLaunch.
        void
        LaunchInferior (
            Module *module,
            char const *argv[],
            char const *envp[],
            const char *stdin_path,
            const char *stdout_path,
            const char *stderr_path,
            const char *working_dir,
            const lldb_private::ProcessLaunchInfo &launch_info,
            Error &error);

        /// Attaches to an existing process.  Forms the
        /// implementation of Process::DoLaunch.
        void
        AttachToInferior (lldb::pid_t pid, Error &error);

        void
        StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);

        static void *
        LaunchOpThread(void *arg);

        static bool
        Launch(LaunchArgs *args);

        void
        StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);

        static void *
        AttachOpThread(void *args);

        static bool
        Attach(AttachArgs *args);

        static bool
        SetDefaultPtraceOpts(const lldb::pid_t);

        static void
        ServeOperation(OperationArgs *args);

        static bool
        DupDescriptor(const char *path, int fd, int flags);

        static bool
        MonitorCallback(void *callback_baton,
                lldb::pid_t pid, bool exited, int signal, int status);

        void
        MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid);

        void
        MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited);

#if 0
        static ::ProcessMessage::CrashReason
        GetCrashReasonForSIGSEGV(const siginfo_t *info);

        static ::ProcessMessage::CrashReason
        GetCrashReasonForSIGILL(const siginfo_t *info);

        static ::ProcessMessage::CrashReason
        GetCrashReasonForSIGFPE(const siginfo_t *info);

        static ::ProcessMessage::CrashReason
        GetCrashReasonForSIGBUS(const siginfo_t *info);
#endif

        void
        DoOperation(void *op);

        /// Stops the child monitor thread.
        void
        StopMonitoringChildProcess();

        /// Stops the operation thread used to attach/launch a process.
        void
        StopOpThread();

        /// Stops monitoring the child process thread.
        void
        StopMonitor();

        bool
        HasThreadNoLock (lldb::tid_t thread_id);

        NativeThreadProtocolSP
        MaybeGetThreadNoLock (lldb::tid_t thread_id);

        bool
        StopTrackingThread (lldb::tid_t thread_id);

        NativeThreadProtocolSP
        AddThread (lldb::tid_t thread_id);

        NativeThreadProtocolSP
        GetOrCreateThread (lldb::tid_t thread_id, bool &created);

        Error
        GetSoftwareBreakpointSize (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size);

        Error
        FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp);

        /// Writes a siginfo_t structure corresponding to the given thread ID to the
        /// memory region pointed to by @p siginfo.
        bool
        GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err);

        /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
        /// corresponding to the given thread ID to the memory pointed to by @p
        /// message.
        bool
        GetEventMessage(lldb::tid_t tid, unsigned long *message);

        /// Resumes the given thread.  If @p signo is anything but
        /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
        bool
        Resume(lldb::tid_t tid, uint32_t signo);

        /// Single steps the given thread.  If @p signo is anything but
        /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
        bool
        SingleStep(lldb::tid_t tid, uint32_t signo);

        lldb_private::Error
        Detach(lldb::tid_t tid);
    };
} // End lldb_private namespace.

#endif // #ifndef liblldb_NativeProcessLinux_H_
OpenPOWER on IntegriCloud