all repos — mgba @ f6523e2c0111710fa79823331eff360f73f5641e

mGBA Game Boy Advance Emulator

src/debugger/gdb-stub.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/internal/debugger/gdb-stub.h>
  7
  8#include <mgba/core/core.h>
  9#include <mgba/internal/arm/debugger/debugger.h>
 10#include <mgba/internal/arm/isa-inlines.h>
 11#include <mgba/internal/gba/memory.h>
 12
 13#include <signal.h>
 14
 15#ifndef SIGTRAP
 16#define SIGTRAP 5 /* Win32 Signals do not include SIGTRAP */
 17#endif
 18
 19#define SOCKET_TIMEOUT 50
 20
 21enum GDBError {
 22	GDB_NO_ERROR = 0x00,
 23	GDB_BAD_ARGUMENTS = 0x06,
 24	GDB_UNSUPPORTED_COMMAND = 0x07
 25};
 26
 27enum {
 28	MACH_O_ARM = 12,
 29	MACH_O_ARM_V4T = 5
 30};
 31
 32static void _sendMessage(struct GDBStub* stub);
 33
 34static void _gdbStubDeinit(struct mDebugger* debugger) {
 35	struct GDBStub* stub = (struct GDBStub*) debugger;
 36	if (!SOCKET_FAILED(stub->socket)) {
 37		GDBStubShutdown(stub);
 38	}
 39}
 40
 41static void _gdbStubEntered(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
 42	struct GDBStub* stub = (struct GDBStub*) debugger;
 43	switch (reason) {
 44	case DEBUGGER_ENTER_MANUAL:
 45		snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGINT);
 46		break;
 47	case DEBUGGER_ENTER_BREAKPOINT:
 48		if (stub->supportsHwbreak && stub->supportsSwbreak && info) {
 49			snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%cwbreak:;", SIGTRAP, info->type.bp.breakType == BREAKPOINT_SOFTWARE ? 's' : 'h');
 50		} else {
 51			snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02xk", SIGTRAP);
 52		}
 53		break;
 54	case DEBUGGER_ENTER_WATCHPOINT:
 55		if (info) {
 56			const char* type = 0;
 57			switch (info->type.wp.watchType) {
 58			case WATCHPOINT_WRITE:
 59				if (info->type.wp.newValue == info->type.wp.oldValue) {
 60					if (stub->d.state == DEBUGGER_PAUSED) {
 61						stub->d.state = DEBUGGER_RUNNING;
 62					}
 63					return;
 64				}
 65				// Fall through
 66			case WATCHPOINT_WRITE_CHANGE:
 67				type = "watch";
 68				break;
 69			case WATCHPOINT_READ:
 70				type = "rwatch";
 71				break;
 72			case WATCHPOINT_RW:
 73				type = "awatch";
 74				break;
 75			}
 76			snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%s:%08x;", SIGTRAP, type, info->address);
 77		} else {
 78			snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP);
 79		}
 80		break;
 81	case DEBUGGER_ENTER_ILLEGAL_OP:
 82		snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGILL);
 83		break;
 84	case DEBUGGER_ENTER_ATTACHED:
 85	case DEBUGGER_ENTER_STACK:
 86		return;
 87	}
 88	_sendMessage(stub);
 89}
 90
 91static void _gdbStubPoll(struct mDebugger* debugger) {
 92	struct GDBStub* stub = (struct GDBStub*) debugger;
 93	--stub->untilPoll;
 94	if (stub->untilPoll > 0) {
 95		return;
 96	}
 97	stub->untilPoll = GDB_STUB_INTERVAL;
 98	stub->shouldBlock = false;
 99	GDBStubUpdate(stub);
100}
101
102static void _gdbStubWait(struct mDebugger* debugger) {
103	struct GDBStub* stub = (struct GDBStub*) debugger;
104	stub->shouldBlock = true;
105	GDBStubUpdate(stub);
106}
107
108static void _ack(struct GDBStub* stub) {
109	char ack = '+';
110	SocketSend(stub->connection, &ack, 1);
111}
112
113static void _nak(struct GDBStub* stub) {
114	char nak = '-';
115	mLOG(DEBUGGER, WARN, "Packet error");
116	SocketSend(stub->connection, &nak, 1);
117}
118
119static uint32_t _hex2int(const char* hex, int maxDigits) {
120	uint32_t value = 0;
121	uint8_t letter;
122
123	while (maxDigits--) {
124		letter = *hex - '0';
125		if (letter > 9) {
126			letter = *hex - 'a';
127			if (letter > 5) {
128				break;
129			}
130			value *= 0x10;
131			value += letter + 10;
132		} else {
133			value *= 0x10;
134			value += letter;
135		}
136		++hex;
137	}
138	return value;
139}
140
141static void _int2hex8(uint8_t value, char* out) {
142	static const char language[] = "0123456789abcdef";
143	out[0] = language[value >> 4];
144	out[1] = language[value & 0xF];
145}
146
147static void _int2hex32(uint32_t value, char* out) {
148	static const char language[] = "0123456789abcdef";
149	out[6] = language[value >> 28];
150	out[7] = language[(value >> 24) & 0xF];
151	out[4] = language[(value >> 20) & 0xF];
152	out[5] = language[(value >> 16) & 0xF];
153	out[2] = language[(value >> 12) & 0xF];
154	out[3] = language[(value >> 8) & 0xF];
155	out[0] = language[(value >> 4) & 0xF];
156	out[1] = language[value & 0xF];
157}
158
159static uint32_t _readHex(const char* in, unsigned* out) {
160	unsigned i;
161	for (i = 0; i < 8; ++i) {
162		if (in[i] == ',' || in[i] == ':' || in[i] == '=') {
163			break;
164		}
165	}
166	*out += i;
167	return _hex2int(in, i);
168}
169
170static void _sendMessage(struct GDBStub* stub) {
171	if (stub->lineAck != GDB_ACK_OFF) {
172		stub->lineAck = GDB_ACK_PENDING;
173	}
174	uint8_t checksum = 0;
175	int i = 1;
176	char buffer = stub->outgoing[0];
177	char swap;
178	stub->outgoing[0] = '$';
179	if (buffer) {
180		for (; i < GDB_STUB_MAX_LINE - 5; ++i) {
181			checksum += buffer;
182			swap = stub->outgoing[i];
183			stub->outgoing[i] = buffer;
184			buffer = swap;
185			if (!buffer) {
186				++i;
187				break;
188			}
189		}
190	}
191	stub->outgoing[i] = '#';
192	_int2hex8(checksum, &stub->outgoing[i + 1]);
193	stub->outgoing[i + 3] = 0;
194	mLOG(DEBUGGER, DEBUG, "> %s", stub->outgoing);
195	SocketSend(stub->connection, stub->outgoing, i + 3);
196}
197
198static void _error(struct GDBStub* stub, enum GDBError error) {
199	snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "E%02x", error);
200	_sendMessage(stub);
201}
202
203static void _writeHostInfo(struct GDBStub* stub) {
204	snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "cputype:%u;cpusubtype:%u:ostype:none;vendor:none;endian:little;ptrsize:4;", MACH_O_ARM, MACH_O_ARM_V4T);
205	_sendMessage(stub);
206}
207
208static void _continue(struct GDBStub* stub, const char* message) {
209	stub->d.state = DEBUGGER_CALLBACK;
210	stub->untilPoll = GDB_STUB_INTERVAL;
211	// TODO: parse message
212	UNUSED(message);
213}
214
215static void _step(struct GDBStub* stub, const char* message) {
216	stub->d.core->step(stub->d.core);
217	snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP);
218	_sendMessage(stub);
219	// TODO: parse message
220	UNUSED(message);
221}
222
223static void _writeMemoryBinary(struct GDBStub* stub, const char* message) {
224	const char* readAddress = message;
225	unsigned i = 0;
226	uint32_t address = _readHex(readAddress, &i);
227	readAddress += i + 1;
228
229	i = 0;
230	uint32_t size = _readHex(readAddress, &i);
231	readAddress += i + 1;
232
233	if (size > 512) {
234		_error(stub, GDB_BAD_ARGUMENTS);
235		return;
236	}
237
238	struct ARMCore* cpu = stub->d.core->cpu;
239	for (i = 0; i < size; i++) {
240		uint8_t byte = *readAddress;
241		++readAddress;
242
243		// Parse escape char
244		if (byte == 0x7D) {
245			byte = *readAddress ^ 0x20;
246			++readAddress;
247		}
248
249		GBAPatch8(cpu, address + i, byte, 0);
250	}
251
252	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
253	_sendMessage(stub);
254}
255
256
257static void _writeMemory(struct GDBStub* stub, const char* message) {
258	const char* readAddress = message;
259	unsigned i = 0;
260	uint32_t address = _readHex(readAddress, &i);
261	readAddress += i + 1;
262
263	i = 0;
264	uint32_t size = _readHex(readAddress, &i);
265	readAddress += i + 1;
266
267	if (size > 512) {
268		_error(stub, GDB_BAD_ARGUMENTS);
269		return;
270	}
271
272	struct ARMCore* cpu = stub->d.core->cpu;
273	for (i = 0; i < size; ++i, readAddress += 2) {
274		uint8_t byte = _hex2int(readAddress, 2);
275		GBAPatch8(cpu, address + i, byte, 0);
276	}
277
278	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
279	_sendMessage(stub);
280}
281
282static void _readMemory(struct GDBStub* stub, const char* message) {
283	const char* readAddress = message;
284	unsigned i = 0;
285	uint32_t address = _readHex(readAddress, &i);
286	readAddress += i + 1;
287	uint32_t size = _readHex(readAddress, &i);
288	if (size > 512) {
289		_error(stub, GDB_BAD_ARGUMENTS);
290		return;
291	}
292	struct ARMCore* cpu = stub->d.core->cpu;
293	int writeAddress = 0;
294	for (i = 0; i < size; ++i, writeAddress += 2) {
295		uint8_t byte = cpu->memory.load8(cpu, address + i, 0);
296		_int2hex8(byte, &stub->outgoing[writeAddress]);
297	}
298	stub->outgoing[writeAddress] = 0;
299	_sendMessage(stub);
300}
301
302static void _writeGPRs(struct GDBStub* stub, const char* message) {
303	struct ARMCore* cpu = stub->d.core->cpu;
304	const char* readAddress = message;
305
306	int r;
307	for (r = 0; r <= ARM_PC; ++r) {
308		cpu->gprs[r] = _hex2int(readAddress, 8);
309		readAddress += 8;
310	}
311	if (cpu->executionMode == MODE_ARM) {
312		ARMWritePC(cpu);
313	} else {
314		ThumbWritePC(cpu);
315	}
316
317	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
318	_sendMessage(stub);
319}
320
321static void _readGPRs(struct GDBStub* stub, const char* message) {
322	struct ARMCore* cpu = stub->d.core->cpu;
323	UNUSED(message);
324	int r;
325	int i = 0;
326
327	// General purpose registers
328	for (r = 0; r < ARM_PC; ++r) {
329		_int2hex32(cpu->gprs[r], &stub->outgoing[i]);
330		i += 8;
331	}
332
333	// Program counter
334	_int2hex32(cpu->gprs[ARM_PC] - (cpu->cpsr.t ? WORD_SIZE_THUMB : WORD_SIZE_ARM), &stub->outgoing[i]);
335	i += 8;
336
337	// Floating point registers, unused on the GBA (8 of them, 24 bits each)
338	for (r = 0; r < 8 * 3; ++r) {
339		_int2hex32(0, &stub->outgoing[i]);
340		i += 8;
341	}
342
343	// Floating point status, unused on the GBA (32 bits)
344	_int2hex32(0, &stub->outgoing[i]);
345	i += 8;
346
347	// CPU status
348	_int2hex32(cpu->cpsr.packed, &stub->outgoing[i]);
349	i += 8;
350
351	stub->outgoing[i] = 0;
352	_sendMessage(stub);
353}
354
355static void _writeRegister(struct GDBStub* stub, const char* message) {
356	struct ARMCore* cpu = stub->d.core->cpu;
357	const char* readAddress = message;
358
359	unsigned i = 0;
360	uint32_t reg = _readHex(readAddress, &i);
361	readAddress += i + 1;
362
363	uint32_t value = _readHex(readAddress, &i);
364
365#ifdef _MSC_VER
366	value = _byteswap_ulong(value);
367#else
368	LOAD_32BE(value, 0, &value);
369#endif
370
371	if (reg <= ARM_PC) {
372		cpu->gprs[reg] = value;
373		if (reg == ARM_PC) {
374			if (cpu->executionMode == MODE_ARM) {
375				ARMWritePC(cpu);
376			} else {
377				ThumbWritePC(cpu);
378			}
379		}
380	} else if (reg == 0x19) {
381		cpu->cpsr.packed = value;
382	} else {
383		stub->outgoing[0] = '\0';
384		_sendMessage(stub);
385		return;
386	}
387
388	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
389	_sendMessage(stub);
390}
391
392static void _readRegister(struct GDBStub* stub, const char* message) {
393	struct ARMCore* cpu = stub->d.core->cpu;
394	const char* readAddress = message;
395	unsigned i = 0;
396	uint32_t reg = _readHex(readAddress, &i);
397	uint32_t value;
398	if (reg < 0x10) {
399		value = cpu->gprs[reg];
400	} else if (reg == 0x19) {
401		value = cpu->cpsr.packed;
402	} else {
403		stub->outgoing[0] = '\0';
404		_sendMessage(stub);
405		return;
406	}
407	_int2hex32(value, stub->outgoing);
408	stub->outgoing[8] = '\0';
409	_sendMessage(stub);
410}
411
412static void _processQSupportedCommand(struct GDBStub* stub, const char* message) {
413	const char* terminator = strrchr(message, '#');
414	stub->supportsSwbreak = false;
415	stub->supportsHwbreak = false;
416	while (message < terminator) {
417		const char* end = strchr(message, ';');
418		size_t len;
419		if (end && end < terminator) {
420			len = end - message;
421		} else {
422			len = terminator - message;
423		}
424		if (!strncmp(message, "swbreak+", len)) {
425			stub->supportsSwbreak = true;
426		} else if (!strncmp(message, "hwbreak+", len)) {
427			stub->supportsHwbreak = true;
428		} else if (!strncmp(message, "swbreak-", len)) {
429			stub->supportsSwbreak = false;
430		} else if (!strncmp(message, "hwbreak-", len)) {
431			stub->supportsHwbreak = false;
432		}
433		if (!end) {
434			break;
435		}
436		message = end + 1;
437	}
438	strncpy(stub->outgoing, "swbreak+;hwbreak+", GDB_STUB_MAX_LINE - 4);
439}
440
441static void _processQReadCommand(struct GDBStub* stub, const char* message) {
442	stub->outgoing[0] = '\0';
443	if (!strncmp("HostInfo#", message, 9)) {
444		_writeHostInfo(stub);
445		return;
446	}
447	if (!strncmp("Attached#", message, 9)) {
448		strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
449	} else if (!strncmp("VAttachOrWaitSupported#", message, 23)) {
450		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
451	} else if (!strncmp("C#", message, 2)) {
452		strncpy(stub->outgoing, "QC1", GDB_STUB_MAX_LINE - 4);
453	} else if (!strncmp("fThreadInfo#", message, 12)) {
454		strncpy(stub->outgoing, "m1", GDB_STUB_MAX_LINE - 4);
455	} else if (!strncmp("sThreadInfo#", message, 12)) {
456		strncpy(stub->outgoing, "l", GDB_STUB_MAX_LINE - 4);
457	} else if (!strncmp("Supported:", message, 10)) {
458		_processQSupportedCommand(stub, message + 10);
459	}
460	_sendMessage(stub);
461}
462
463static void _processQWriteCommand(struct GDBStub* stub, const char* message) {
464	stub->outgoing[0] = '\0';
465	if (!strncmp("StartNoAckMode#", message, 16)) {
466		stub->lineAck = GDB_ACK_OFF;
467		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
468	}
469	_sendMessage(stub);
470}
471
472static void _processVWriteCommand(struct GDBStub* stub, const char* message) {
473	UNUSED(message);
474	stub->outgoing[0] = '\0';
475	_sendMessage(stub);
476}
477
478static void _processVReadCommand(struct GDBStub* stub, const char* message) {
479	stub->outgoing[0] = '\0';
480	if (!strncmp("Attach", message, 6)) {
481		strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
482		mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
483	}
484	_sendMessage(stub);
485}
486
487static void _setBreakpoint(struct GDBStub* stub, const char* message) {
488	const char* readAddress = &message[2];
489	unsigned i = 0;
490	uint32_t address = _readHex(readAddress, &i);
491	readAddress += i + 1;
492	uint32_t kind = _readHex(readAddress, &i);
493
494	struct mBreakpoint breakpoint = {
495		.address = address,
496		.type = BREAKPOINT_HARDWARE
497	};
498	struct mWatchpoint watchpoint = {
499		.address = address
500	};
501
502	switch (message[0]) {
503	case '0':
504		ARMDebuggerSetSoftwareBreakpoint(stub->d.platform, address, kind == 2 ? MODE_THUMB : MODE_ARM);
505		break;
506	case '1':
507		stub->d.platform->setBreakpoint(stub->d.platform, &breakpoint);
508		break;
509	case '2':
510		watchpoint.type = WATCHPOINT_WRITE_CHANGE;
511		stub->d.platform->setWatchpoint(stub->d.platform, &watchpoint);
512		break;
513	case '3':
514		watchpoint.type = WATCHPOINT_READ;
515		stub->d.platform->setWatchpoint(stub->d.platform, &watchpoint);
516		break;
517	case '4':
518		watchpoint.type = WATCHPOINT_RW;
519		stub->d.platform->setWatchpoint(stub->d.platform, &watchpoint);
520		break;
521	default:
522		stub->outgoing[0] = '\0';
523		_sendMessage(stub);
524		return;
525	}
526	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
527	_sendMessage(stub);
528}
529
530static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
531	const char* readAddress = &message[2];
532	unsigned i = 0;
533	uint32_t address = _readHex(readAddress, &i);
534	struct mBreakpointList breakpoints;
535	struct mWatchpointList watchpoints;
536
537	size_t index;
538	switch (message[0]) {
539	case '0':
540	case '1':
541		mBreakpointListInit(&breakpoints, 0);
542		stub->d.platform->listBreakpoints(stub->d.platform, &breakpoints);
543		for (index = 0; index < mBreakpointListSize(&breakpoints); ++index) {
544			if (mBreakpointListGetPointer(&breakpoints, index)->address != address) {
545				continue;
546			}
547			stub->d.platform->clearBreakpoint(stub->d.platform, mBreakpointListGetPointer(&breakpoints, index)->id);
548		}
549		mBreakpointListDeinit(&breakpoints);
550		break;
551	case '2':
552	case '3':
553	case '4':
554		mWatchpointListInit(&watchpoints, 0);
555		stub->d.platform->listWatchpoints(stub->d.platform, &watchpoints);
556		for (index = 0; index < mWatchpointListSize(&watchpoints); ++index) {
557			if (mWatchpointListGetPointer(&watchpoints, index)->address != address) {
558				continue;
559			}
560			stub->d.platform->clearBreakpoint(stub->d.platform, mWatchpointListGetPointer(&watchpoints, index)->id);
561		}
562		mWatchpointListDeinit(&watchpoints);
563		break;
564	default:
565		break;
566	}
567	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
568	_sendMessage(stub);
569}
570
571size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
572	uint8_t checksum = 0;
573	int parsed = 1;
574	switch (*message) {
575	case '+':
576		stub->lineAck = GDB_ACK_RECEIVED;
577		return parsed;
578	case '-':
579		stub->lineAck = GDB_NAK_RECEIVED;
580		return parsed;
581	case '$':
582		++message;
583		break;
584	case '\x03':
585		mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
586		return parsed;
587	default:
588		_nak(stub);
589		return parsed;
590	}
591
592	int i;
593	char messageType = message[0];
594	for (i = 0; message[i] != '#'; ++i, ++parsed) {
595		checksum += message[i];
596	}
597	if (!message[i]) {
598		_nak(stub);
599		return parsed;
600	}
601	++i;
602	++parsed;
603	if (!message[i]) {
604		_nak(stub);
605		return parsed;
606	} else if (!message[i + 1]) {
607		++parsed;
608		_nak(stub);
609		return parsed;
610	}
611	parsed += 2;
612	int networkChecksum = _hex2int(&message[i], 2);
613	if (networkChecksum != checksum) {
614		mLOG(DEBUGGER, WARN, "Checksum error: expected %02x, got %02x", checksum, networkChecksum);
615		_nak(stub);
616		return parsed;
617	}
618
619	_ack(stub);
620	++message;
621	switch (messageType) {
622	case '?':
623		snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGINT);
624		_sendMessage(stub);
625		break;
626	case 'c':
627		_continue(stub, message);
628		break;
629	case 'G':
630		_writeGPRs(stub, message);
631		break;
632	case 'g':
633		_readGPRs(stub, message);
634		break;
635	case 'H':
636		// This is faked because we only have one thread
637		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
638		_sendMessage(stub);
639		break;
640	case 'M':
641		_writeMemory(stub, message);
642		break;
643	case 'm':
644		_readMemory(stub, message);
645		break;
646	case 'P':
647		_writeRegister(stub, message);
648		break;
649	case 'p':
650		_readRegister(stub, message);
651		break;
652	case 'Q':
653		_processQWriteCommand(stub, message);
654		break;
655	case 'q':
656		_processQReadCommand(stub, message);
657		break;
658	case 's':
659		_step(stub, message);
660		break;
661	case 'V':
662		_processVWriteCommand(stub, message);
663		break;
664	case 'v':
665		_processVReadCommand(stub, message);
666		break;
667	case 'X':
668		_writeMemoryBinary(stub, message);
669                break;
670	case 'Z':
671		_setBreakpoint(stub, message);
672		break;
673	case 'z':
674		_clearBreakpoint(stub, message);
675		break;
676	default:
677		_error(stub, GDB_UNSUPPORTED_COMMAND);
678		break;
679	}
680	return parsed;
681}
682
683void GDBStubCreate(struct GDBStub* stub) {
684	stub->socket = INVALID_SOCKET;
685	stub->connection = INVALID_SOCKET;
686	stub->d.init = 0;
687	stub->d.deinit = _gdbStubDeinit;
688	stub->d.paused = _gdbStubWait;
689	stub->d.entered = _gdbStubEntered;
690	stub->d.custom = _gdbStubPoll;
691	stub->d.type = DEBUGGER_GDB;
692	stub->untilPoll = GDB_STUB_INTERVAL;
693	stub->lineAck = GDB_ACK_PENDING;
694	stub->shouldBlock = false;
695}
696
697bool GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) {
698	if (!SOCKET_FAILED(stub->socket)) {
699		GDBStubShutdown(stub);
700	}
701	stub->socket = SocketOpenTCP(port, bindAddress);
702	if (SOCKET_FAILED(stub->socket)) {
703		mLOG(DEBUGGER, ERROR, "Couldn't open socket");
704		return false;
705	}
706	if (!SocketSetBlocking(stub->socket, false)) {
707		goto cleanup;
708	}
709	int err = SocketListen(stub->socket, 1);
710	if (err) {
711		goto cleanup;
712	}
713
714	return true;
715
716cleanup:
717	mLOG(DEBUGGER, ERROR, "Couldn't listen on port");
718	SocketClose(stub->socket);
719	stub->socket = INVALID_SOCKET;
720	return false;
721}
722
723void GDBStubHangup(struct GDBStub* stub) {
724	if (!SOCKET_FAILED(stub->connection)) {
725		SocketClose(stub->connection);
726		stub->connection = INVALID_SOCKET;
727	}
728	if (stub->d.state == DEBUGGER_PAUSED) {
729		stub->d.state = DEBUGGER_RUNNING;
730	}
731}
732
733void GDBStubShutdown(struct GDBStub* stub) {
734	GDBStubHangup(stub);
735	if (!SOCKET_FAILED(stub->socket)) {
736		SocketClose(stub->socket);
737		stub->socket = INVALID_SOCKET;
738	}
739}
740
741void GDBStubUpdate(struct GDBStub* stub) {
742	if (stub->socket == INVALID_SOCKET) {
743		if (stub->d.state == DEBUGGER_PAUSED) {
744			stub->d.state = DEBUGGER_RUNNING;
745		}
746		return;
747	}
748	if (stub->connection == INVALID_SOCKET) {
749		if (stub->shouldBlock) {
750			Socket reads = stub->socket;
751			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
752		}
753		stub->connection = SocketAccept(stub->socket, 0);
754		if (!SOCKET_FAILED(stub->connection)) {
755			if (!SocketSetBlocking(stub->connection, false)) {
756				goto connectionLost;
757			}
758			mDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0);
759		} else if (SocketWouldBlock()) {
760			return;
761		} else {
762			goto connectionLost;
763		}
764	}
765	while (true) {
766		if (stub->shouldBlock) {
767			Socket reads = stub->connection;
768			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
769		}
770		ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
771		if (messageLen == 0) {
772			goto connectionLost;
773		}
774		if (messageLen == -1) {
775			if (SocketWouldBlock()) {
776				return;
777			}
778			goto connectionLost;
779		}
780		stub->line[messageLen] = '\0';
781		mLOG(DEBUGGER, DEBUG, "< %s", stub->line);
782		ssize_t position = 0;
783		while (position < messageLen) {
784			position += _parseGDBMessage(stub, &stub->line[position]);
785		}
786	}
787
788connectionLost:
789	mLOG(DEBUGGER, WARN, "Connection lost");
790	GDBStubHangup(stub);
791}