all repos — mgba @ fa884d071ecaa3e05ff20b45a67bf9500dd3d6b6

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