all repos — mgba @ f96b08c52f6effe8cb882a2f4cf7b03c1dfec38e

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