aboutsummaryrefslogtreecommitdiff
path: root/tools/debugserver/source/RNBRemote.h
blob: 9d30106d5b82d4297dd45b0a140e7b091e59310e (plain) (blame)
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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 12/12/07.
//
//===----------------------------------------------------------------------===//

#ifndef __RNBRemote_h__
#define __RNBRemote_h__

#include "RNBDefs.h"
#include "DNB.h"
#include "RNBContext.h"
#include "RNBSocket.h"
#include "PThreadMutex.h"
#include <string>
#include <vector>
#include <deque>
#include <map>

class RNBSocket;
class RNBContext;
class PThreadEvents;

enum event_loop_mode { debug_nub, gdb_remote_protocol, done };

enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none };

class RNBRemote
{
public:

    typedef enum {
        invalid_packet = 0,
        ack,                            // '+'
        nack,                           // '-'
        halt,                           // ^C  (async halt)
        use_extended_mode,              // '!'
        why_halted,                     // '?'
        set_argv,                       // 'A'
        set_bp,                         // 'B'
        cont,                           // 'c'
        continue_with_sig,              // 'C'
        detach,                         // 'D'
        read_general_regs,              // 'g'
        write_general_regs,             // 'G'
        set_thread,                     // 'H'
        step_inferior_one_cycle,        // 'i'
        signal_and_step_inf_one_cycle,  // 'I'
        kill,                           // 'k'
        read_memory,                    // 'm'
        write_memory,                   // 'M'
        read_register,                  // 'p'
        write_register,                 // 'P'
        restart,                        // 'R'
        single_step,                    // 's'
        single_step_with_sig,           // 'S'
        search_mem_backwards,           // 't'
        thread_alive_p,                 // 'T'
        vattach,                        // 'vAttach;pid'
        vattachwait,                    // 'vAttachWait:XX...' where XX is one or more hex encoded process name ASCII bytes
        vattachorwait,                  // 'vAttachOrWait:XX...' where XX is one or more hex encoded process name ASCII bytes
        vattachname,                    // 'vAttachName:XX...' where XX is one or more hex encoded process name ASCII bytes
        vcont,                          // 'vCont'
        vcont_list_actions,             // 'vCont?'
        read_data_from_memory,          // 'x'
        write_data_to_memory,           // 'X'
        insert_mem_bp,                  // 'Z0'
        remove_mem_bp,                  // 'z0'
        insert_hardware_bp,             // 'Z1'
        remove_hardware_bp,             // 'z1'
        insert_write_watch_bp,          // 'Z2'
        remove_write_watch_bp,          // 'z2'
        insert_read_watch_bp,           // 'Z3'
        remove_read_watch_bp,           // 'z3'
        insert_access_watch_bp,         // 'Z4'
        remove_access_watch_bp,         // 'z4'

        query_monitor,                  // 'qRcmd'
        query_current_thread_id,        // 'qC'
        query_get_pid,                  // 'qGetPid'
        query_echo,                     // 'qEcho'
        query_thread_ids_first,         // 'qfThreadInfo'
        query_thread_ids_subsequent,    // 'qsThreadInfo'
        query_thread_extra_info,        // 'qThreadExtraInfo'
        query_thread_stop_info,         // 'qThreadStopInfo'
        query_image_offsets,            // 'qOffsets'
        query_symbol_lookup,            // 'qSymbol'
        query_launch_success,           // 'qLaunchSuccess'
        query_register_info,            // 'qRegisterInfo'
        query_shlib_notify_info_addr,   // 'qShlibInfoAddr'
        query_step_packet_supported,    // 'qStepPacketSupported'
        query_supported_features,       // 'qSupported'
        query_vattachorwait_supported,  // 'qVAttachOrWaitSupported'
        query_sync_thread_state_supported,// 'QSyncThreadState'
        query_host_info,                // 'qHostInfo'
        query_gdb_server_version,       // 'qGDBServerVersion'
        query_process_info,             // 'qProcessInfo'
        json_query_thread_extended_info,// 'jThreadExtendedInfo'
        json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos'
        json_query_threads_info,        // 'jThreadsInfo'
        pass_signals_to_inferior,       // 'QPassSignals'
        start_noack_mode,               // 'QStartNoAckMode'
        prefix_reg_packets_with_tid,    // 'QPrefixRegisterPacketsWithThreadID
        set_logging_mode,               // 'QSetLogging:'
        set_max_packet_size,            // 'QSetMaxPacketSize:'
        set_max_payload_size,           // 'QSetMaxPayloadSize:'
        set_environment_variable,       // 'QEnvironment:'
        set_environment_variable_hex,   // 'QEnvironmentHexEncoded:'
        set_launch_arch,                // 'QLaunchArch:'
        set_disable_aslr,               // 'QSetDisableASLR:'
        set_stdin,                      // 'QSetSTDIN:'
        set_stdout,                     // 'QSetSTDOUT:'
        set_stderr,                     // 'QSetSTDERR:'
        set_working_dir,                // 'QSetWorkingDir:'
        set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:'
        sync_thread_state,              // 'QSyncThreadState:'
        memory_region_info,             // 'qMemoryRegionInfo:'
        get_profile_data,               // 'qGetProfileData'
        set_enable_profiling,           // 'QSetEnableAsyncProfiling'
        enable_compression,             // 'QEnableCompression:'
        watchpoint_support_info,        // 'qWatchpointSupportInfo:'
        allocate_memory,                // '_M'
        deallocate_memory,              // '_m'
        set_process_event,               // 'QSetProcessEvent:'
        save_register_state,            // '_g'
        restore_register_state,         // '_G'
        speed_test,                     // 'qSpeedTest:'
        set_detach_on_error,            // 'QSetDetachOnError:'
        query_transfer,                 // 'qXfer:'
        unknown_type
    } PacketEnum;

    typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);

    RNBRemote ();
    ~RNBRemote ();

    void            Initialize();

    bool            InitializeRegisters (bool force = false);

    rnb_err_t       HandleAsyncPacket(PacketEnum *type = NULL);
    rnb_err_t       HandleReceivedPacket(PacketEnum *type = NULL);

    nub_thread_t    GetContinueThread () const
                    {
                        return m_continue_thread;
                    }

    void            SetContinueThread (nub_thread_t tid)
                    {
                        m_continue_thread = tid;
                    }

    nub_thread_t    GetCurrentThread () const
                    {
                        if (m_thread == 0 || m_thread == (nub_thread_t)-1)
                            return DNBProcessGetCurrentThread (m_ctx.ProcessID());
                        return m_thread;
                    }

    void            SetCurrentThread (nub_thread_t tid)
                    {
                        DNBProcessSetCurrentThread (m_ctx.ProcessID(), tid);
                        m_thread = tid;
                    }

    static void*    ThreadFunctionReadRemoteData(void *arg);
    void            StartReadRemoteDataThread ();
    void            StopReadRemoteDataThread ();

    void NotifyThatProcessStopped (void);

    rnb_err_t HandlePacket_A (const char *p);
    rnb_err_t HandlePacket_H (const char *p);
    rnb_err_t HandlePacket_qC (const char *p);
    rnb_err_t HandlePacket_qRcmd (const char *p);
    rnb_err_t HandlePacket_qGetPid (const char *p);
    rnb_err_t HandlePacket_qEcho (const char *p);
    rnb_err_t HandlePacket_qLaunchSuccess (const char *p);
    rnb_err_t HandlePacket_qRegisterInfo (const char *p);
    rnb_err_t HandlePacket_qShlibInfoAddr (const char *p);
    rnb_err_t HandlePacket_qStepPacketSupported (const char *p);
    rnb_err_t HandlePacket_qVAttachOrWaitSupported (const char *p);
    rnb_err_t HandlePacket_qSyncThreadStateSupported (const char *p);
    rnb_err_t HandlePacket_qThreadInfo (const char *p);
    rnb_err_t HandlePacket_jThreadExtendedInfo (const char *p);
    rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p);
    rnb_err_t HandlePacket_jThreadsInfo (const char *p);
    rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
    rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
    rnb_err_t HandlePacket_qHostInfo (const char *p);
    rnb_err_t HandlePacket_qGDBServerVersion (const char *p);
    rnb_err_t HandlePacket_qProcessInfo (const char *p);
    rnb_err_t HandlePacket_qSymbol (const char *p);
    rnb_err_t HandlePacket_QStartNoAckMode (const char *p);
    rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p);
    rnb_err_t HandlePacket_QSetLogging (const char *p);
    rnb_err_t HandlePacket_QSetDisableASLR (const char *p);
    rnb_err_t HandlePacket_QSetSTDIO (const char *p);
    rnb_err_t HandlePacket_QSetWorkingDir (const char *p);
    rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p);
    rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p);
    rnb_err_t HandlePacket_QEnvironment (const char *p);
    rnb_err_t HandlePacket_QEnvironmentHexEncoded (const char *p);
    rnb_err_t HandlePacket_QLaunchArch (const char *p);
    rnb_err_t HandlePacket_QListThreadsInStopReply (const char *p);
    rnb_err_t HandlePacket_QSyncThreadState (const char *p);
    rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p);
    rnb_err_t HandlePacket_QSetProcessEvent (const char *p);
    rnb_err_t HandlePacket_last_signal (const char *p);
    rnb_err_t HandlePacket_m (const char *p);
    rnb_err_t HandlePacket_M (const char *p);
    rnb_err_t HandlePacket_x (const char *p);
    rnb_err_t HandlePacket_X (const char *p);
    rnb_err_t HandlePacket_g (const char *p);
    rnb_err_t HandlePacket_G (const char *p);
    rnb_err_t HandlePacket_z (const char *p);
    rnb_err_t HandlePacket_T (const char *p);
    rnb_err_t HandlePacket_p (const char *p);
    rnb_err_t HandlePacket_P (const char *p);
    rnb_err_t HandlePacket_c (const char *p);
    rnb_err_t HandlePacket_C (const char *p);
    rnb_err_t HandlePacket_D (const char *p);
    rnb_err_t HandlePacket_k (const char *p);
    rnb_err_t HandlePacket_s (const char *p);
    rnb_err_t HandlePacket_S (const char *p);
    rnb_err_t HandlePacket_qSupported (const char *p);
    rnb_err_t HandlePacket_v (const char *p);
    rnb_err_t HandlePacket_UNIMPLEMENTED (const char *p);
    rnb_err_t HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description);
    rnb_err_t HandlePacket_AllocateMemory (const char *p);
    rnb_err_t HandlePacket_DeallocateMemory (const char *p);
    rnb_err_t HandlePacket_SaveRegisterState (const char *p);
    rnb_err_t HandlePacket_RestoreRegisterState (const char *p);
    rnb_err_t HandlePacket_MemoryRegionInfo (const char *p);
    rnb_err_t HandlePacket_GetProfileData(const char *p);
    rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p);
    rnb_err_t HandlePacket_QEnableCompression(const char *p);
    rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p);
    rnb_err_t HandlePacket_qSpeedTest (const char *p);
    rnb_err_t HandlePacket_qXfer (const char *p);
    rnb_err_t HandlePacket_stop_process (const char *p);
    rnb_err_t HandlePacket_QSetDetachOnError (const char *p);

    rnb_err_t SendStopReplyPacketForThread (nub_thread_t tid);
    rnb_err_t SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer);
    rnb_err_t SendSTDOUTPacket (char *buf, nub_size_t buf_size);
    rnb_err_t SendSTDERRPacket (char *buf, nub_size_t buf_size);
    void      FlushSTDIO ();
    void      SendAsyncProfileData ();
    rnb_err_t SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size);

    RNBContext&     Context() { return m_ctx; }
    RNBSocket&      Comm() { return m_comm; }

private:
    // Outlaw some constructors
    RNBRemote (const RNBRemote &);

protected:

    rnb_err_t GetCommData ();
    void CommDataReceived(const std::string& data);
    struct Packet
    {
        typedef std::vector<Packet>         collection;
        typedef collection::iterator        iterator;
        typedef collection::const_iterator  const_iterator;
        PacketEnum type;
        HandlePacketCallback normal;    // Function to call when inferior is halted
        HandlePacketCallback async;     // Function to call when inferior is running
        std::string abbrev;
        std::string printable_name;
        
        bool
        IsPlatformPacket () const
        {
            switch (type)
            {
            case set_logging_mode:
            case query_host_info:
                return true;
            default:
                    break;
            }
            return false;
        }
        Packet() :
            type(invalid_packet),
            normal (NULL),
            async (NULL),
            abbrev (),
            printable_name ()
        {
        }

        Packet( PacketEnum in_type,
                HandlePacketCallback in_normal,
                HandlePacketCallback in_async,
                const char *in_abbrev,
                const char *in_printable_name) :
            type    (in_type),
            normal  (in_normal),
            async   (in_async),
            abbrev  (in_abbrev),
            printable_name (in_printable_name)
        {
        }
    };


    struct DispatchQueueOffsets
    {
        uint16_t dqo_version;
        uint16_t dqo_label;
        uint16_t dqo_label_size;
        uint16_t dqo_flags;
        uint16_t dqo_flags_size;
        uint16_t dqo_serialnum;
        uint16_t dqo_serialnum_size;
        uint16_t dqo_width;
        uint16_t dqo_width_size;
        uint16_t dqo_running;
        uint16_t dqo_running_size;
        uint16_t dqo_suspend_cnt;         // version 5 and later, starting with Mac OS X 10.10/iOS 8
        uint16_t dqo_suspend_cnt_size;    // version 5 and later, starting with Mac OS X 10.10/iOS 8
        uint16_t dqo_target_queue;        // version 5 and later, starting with Mac OS X 10.10/iOS 8
        uint16_t dqo_target_queue_size;   // version 5 and later, starting with Mac OS X 10.10/iOS 8
        uint16_t dqo_priority;            // version 5 and later, starting with Mac OS X 10.10/iOS 8
        uint16_t dqo_priority_size;       // version 5 and later, starting with Mac OS X 10.10/iOS 8

        DispatchQueueOffsets ()
        {
            Clear();
        }

        void
        Clear()
        {
            dqo_version = UINT16_MAX;
            dqo_label = UINT16_MAX;
            dqo_label_size = UINT16_MAX;
            dqo_flags = UINT16_MAX;
            dqo_flags_size = UINT16_MAX;
            dqo_serialnum = UINT16_MAX;
            dqo_serialnum_size = UINT16_MAX;
            dqo_width = UINT16_MAX;
            dqo_width_size = UINT16_MAX;
            dqo_running = UINT16_MAX;
            dqo_running_size = UINT16_MAX;
            dqo_suspend_cnt = UINT16_MAX;
            dqo_suspend_cnt_size = UINT16_MAX;
            dqo_target_queue = UINT16_MAX;
            dqo_target_queue_size = UINT16_MAX;
            dqo_priority = UINT16_MAX;
            dqo_priority_size = UINT16_MAX;
        }

        bool
        IsValid () const
        {
            return dqo_version != UINT16_MAX;
        }

        void
        GetThreadQueueInfo (nub_process_t pid,
                            nub_addr_t dispatch_qaddr,
                            std::string &queue_name,
                            uint64_t &queue_width,
                            uint64_t &queue_serialnum) const;
    };

    rnb_err_t       GetPacket (std::string &packet_data, RNBRemote::Packet& packet_info, bool wait);
    rnb_err_t       SendPacket (const std::string &);
    std::string     CompressString (const std::string &);

    void CreatePacketTable ();
    rnb_err_t GetPacketPayload (std::string &);

    nub_thread_t
    ExtractThreadIDFromThreadSuffix (const char *p);

    void
    EnableCompressionNextSendPacket (compression_types);

    compression_types
    GetCompressionType ();

    const DispatchQueueOffsets *
    GetDispatchQueueOffsets();

    JSONGenerator::ObjectSP
    GetJSONThreadsInfo (bool threads_with_valid_stop_info_only);

    RNBContext      m_ctx;              // process context
    RNBSocket       m_comm;             // communication port
    std::string     m_arch;
    nub_thread_t    m_continue_thread;  // thread to continue; 0 for any, -1 for all
    nub_thread_t    m_thread;           // thread for other ops; 0 for any, -1 for all
    PThreadMutex    m_mutex;            // Mutex that protects
    DispatchQueueOffsets m_dispatch_queue_offsets;
    nub_addr_t      m_dispatch_queue_offsets_addr;
    uint32_t        m_qSymbol_index;
    uint32_t        m_packets_recvd;
    Packet::collection m_packets;
    std::deque<std::string> m_rx_packets;
    std::string     m_rx_partial_data;  // For packets that may come in more than one batch, anything left over can be left here
    pthread_t       m_rx_pthread;
    uint32_t        m_max_payload_size;  // the maximum sized payload we should send to gdb
    bool            m_extended_mode;   // are we in extended mode?
    bool            m_noack_mode;      // are we in no-ack mode?
    bool            m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon:
                                                                // "$pRR;thread:TTTT;" instead of "$pRR"
                                                                // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV"
                                                                // "$g;thread:TTTT" instead of "$g"
                                                                // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV"
    bool            m_list_threads_in_stop_reply;

    size_t          m_compression_minsize;                      // only packets larger than this size will be compressed
    bool            m_enable_compression_next_send_packet;

    compression_types m_compression_mode;
};

/* We translate the /usr/include/mach/exception_types.h exception types
   (e.g. EXC_BAD_ACCESS) to the fake BSD signal numbers that gdb uses
   in include/gdb/signals.h (e.g. TARGET_EXC_BAD_ACCESS).  These hard
   coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb
   values in its include/gdb/signals.h.  */

#define TARGET_EXC_BAD_ACCESS      0x91
#define TARGET_EXC_BAD_INSTRUCTION 0x92
#define TARGET_EXC_ARITHMETIC      0x93
#define TARGET_EXC_EMULATION       0x94
#define TARGET_EXC_SOFTWARE        0x95
#define TARGET_EXC_BREAKPOINT      0x96

/* Generally speaking, you can't assume gdb can receive more than 399 bytes
   at a time with a random gdb.  This bufsize constant is only specifying
   how many bytes gdb can *receive* from debugserver -- it tells us nothing
   about how many bytes gdb might try to send in a single packet.  */
#define DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE 399

#endif // #ifndef __RNBRemote_h__