all repos — mgba @ 4d383b129dd51083a917f5c82ec9f3314c577a65

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				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	if (cpu->executionMode == MODE_ARM) {
309		ARMWritePC(cpu);
310	} else {
311		ThumbWritePC(cpu);
312	}
313
314	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
315	_sendMessage(stub);
316}
317
318static void _readGPRs(struct GDBStub* stub, const char* message) {
319	struct ARMCore* cpu = stub->d.core->cpu;
320	UNUSED(message);
321	int r;
322	int i = 0;
323
324	// General purpose registers
325	for (r = 0; r < ARM_PC; ++r) {
326		_int2hex32(cpu->gprs[r], &stub->outgoing[i]);
327		i += 8;
328	}
329
330	// Program counter
331	_int2hex32(cpu->gprs[ARM_PC] - (cpu->cpsr.t ? WORD_SIZE_THUMB : WORD_SIZE_ARM), &stub->outgoing[i]);
332	i += 8;
333
334	// Floating point registers, unused on the GBA (8 of them, 24 bits each)
335	for (r = 0; r < 8 * 3; ++r) {
336		_int2hex32(0, &stub->outgoing[i]);
337		i += 8;
338	}
339
340	// Floating point status, unused on the GBA (32 bits)
341	_int2hex32(0, &stub->outgoing[i]);
342	i += 8;
343
344	// CPU status
345	_int2hex32(cpu->cpsr.packed, &stub->outgoing[i]);
346	i += 8;
347
348	stub->outgoing[i] = 0;
349	_sendMessage(stub);
350}
351
352static void _writeRegister(struct GDBStub* stub, const char* message) {
353	struct ARMCore* cpu = stub->d.core->cpu;
354	const char* readAddress = message;
355
356	unsigned i = 0;
357	uint32_t reg = _readHex(readAddress, &i);
358	readAddress += i + 1;
359
360	uint32_t value = _readHex(readAddress, &i);
361
362#ifdef _MSC_VER
363	value = _byteswap_ulong(value);
364#else
365	LOAD_32BE(value, 0, &value);
366#endif
367
368	if (reg <= ARM_PC) {
369		cpu->gprs[reg] = value;
370		if (reg == ARM_PC) {
371			if (cpu->executionMode == MODE_ARM) {
372				ARMWritePC(cpu);
373			} else {
374				ThumbWritePC(cpu);
375			}
376		}
377	} else if (reg == 0x19) {
378		cpu->cpsr.packed = value;
379	} else {
380		stub->outgoing[0] = '\0';
381		_sendMessage(stub);
382		return;
383	}
384
385	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
386	_sendMessage(stub);
387}
388
389static void _readRegister(struct GDBStub* stub, const char* message) {
390	struct ARMCore* cpu = stub->d.core->cpu;
391	const char* readAddress = message;
392	unsigned i = 0;
393	uint32_t reg = _readHex(readAddress, &i);
394	uint32_t value;
395	if (reg < 0x10) {
396		value = cpu->gprs[reg];
397	} else if (reg == 0x19) {
398		value = cpu->cpsr.packed;
399	} else {
400		stub->outgoing[0] = '\0';
401		_sendMessage(stub);
402		return;
403	}
404	_int2hex32(value, stub->outgoing);
405	stub->outgoing[8] = '\0';
406	_sendMessage(stub);
407}
408
409static void _processQSupportedCommand(struct GDBStub* stub, const char* message) {
410	const char* terminator = strrchr(message, '#');
411	stub->supportsSwbreak = false;
412	stub->supportsHwbreak = false;
413	while (message < terminator) {
414		const char* end = strchr(message, ';');
415		size_t len;
416		if (end && end < terminator) {
417			len = end - message;
418		} else {
419			len = terminator - message;
420		}
421		if (!strncmp(message, "swbreak+", len)) {
422			stub->supportsSwbreak = true;
423		} else if (!strncmp(message, "hwbreak+", len)) {
424			stub->supportsHwbreak = true;
425		} else if (!strncmp(message, "swbreak-", len)) {
426			stub->supportsSwbreak = false;
427		} else if (!strncmp(message, "hwbreak-", len)) {
428			stub->supportsHwbreak = false;
429		}
430		if (!end) {
431			break;
432		}
433		message = end + 1;
434	}
435	strncpy(stub->outgoing, "swbreak+;hwbreak+", GDB_STUB_MAX_LINE - 4);
436}
437
438static void _processQReadCommand(struct GDBStub* stub, const char* message) {
439	stub->outgoing[0] = '\0';
440	if (!strncmp("HostInfo#", message, 9)) {
441		_writeHostInfo(stub);
442		return;
443	}
444	if (!strncmp("Attached#", message, 9)) {
445		strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
446	} else if (!strncmp("VAttachOrWaitSupported#", message, 23)) {
447		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
448	} else if (!strncmp("C#", message, 2)) {
449		strncpy(stub->outgoing, "QC1", GDB_STUB_MAX_LINE - 4);
450	} else if (!strncmp("fThreadInfo#", message, 12)) {
451		strncpy(stub->outgoing, "m1", GDB_STUB_MAX_LINE - 4);
452	} else if (!strncmp("sThreadInfo#", message, 12)) {
453		strncpy(stub->outgoing, "l", GDB_STUB_MAX_LINE - 4);
454	} else if (!strncmp("Supported:", message, 10)) {
455		_processQSupportedCommand(stub, message + 10);
456	}
457	_sendMessage(stub);
458}
459
460static void _processQWriteCommand(struct GDBStub* stub, const char* message) {
461	stub->outgoing[0] = '\0';
462	if (!strncmp("StartNoAckMode#", message, 16)) {
463		stub->lineAck = GDB_ACK_OFF;
464		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
465	}
466	_sendMessage(stub);
467}
468
469static void _processVWriteCommand(struct GDBStub* stub, const char* message) {
470	UNUSED(message);
471	stub->outgoing[0] = '\0';
472	_sendMessage(stub);
473}
474
475static void _processVReadCommand(struct GDBStub* stub, const char* message) {
476	stub->outgoing[0] = '\0';
477	if (!strncmp("Attach", message, 6)) {
478		strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
479		mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
480	}
481	_sendMessage(stub);
482}
483
484static void _setBreakpoint(struct GDBStub* stub, const char* message) {
485	const char* readAddress = &message[2];
486	unsigned i = 0;
487	uint32_t address = _readHex(readAddress, &i);
488	readAddress += i + 1;
489	uint32_t kind = _readHex(readAddress, &i);
490
491	switch (message[0]) {
492	case '0':
493		ARMDebuggerSetSoftwareBreakpoint(stub->d.platform, address, kind == 2 ? MODE_THUMB : MODE_ARM);
494		break;
495	case '1':
496		stub->d.platform->setBreakpoint(stub->d.platform, address, -1);
497		break;
498	case '2':
499		stub->d.platform->setWatchpoint(stub->d.platform, address, -1, WATCHPOINT_WRITE);
500		break;
501	case '3':
502		stub->d.platform->setWatchpoint(stub->d.platform, address, -1, WATCHPOINT_READ);
503		break;
504	case '4':
505		stub->d.platform->setWatchpoint(stub->d.platform, address, -1, WATCHPOINT_RW);
506		break;
507	default:
508		stub->outgoing[0] = '\0';
509		_sendMessage(stub);
510		return;
511	}
512	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
513	_sendMessage(stub);
514}
515
516static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
517	const char* readAddress = &message[2];
518	unsigned i = 0;
519	uint32_t address = _readHex(readAddress, &i);
520	switch (message[0]) {
521	case '0':
522		ARMDebuggerClearSoftwareBreakpoint(stub->d.platform, address);
523		break;
524	case '1':
525		stub->d.platform->clearBreakpoint(stub->d.platform, address, -1);
526		break;
527	case '2':
528	case '3':
529	case '4':
530		stub->d.platform->clearWatchpoint(stub->d.platform, address, -1);
531		break;
532	default:
533		break;
534	}
535	strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
536	_sendMessage(stub);
537}
538
539size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
540	uint8_t checksum = 0;
541	int parsed = 1;
542	switch (*message) {
543	case '+':
544		stub->lineAck = GDB_ACK_RECEIVED;
545		return parsed;
546	case '-':
547		stub->lineAck = GDB_NAK_RECEIVED;
548		return parsed;
549	case '$':
550		++message;
551		break;
552	case '\x03':
553		mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
554		return parsed;
555	default:
556		_nak(stub);
557		return parsed;
558	}
559
560	int i;
561	char messageType = message[0];
562	for (i = 0; message[i] != '#'; ++i, ++parsed) {
563		checksum += message[i];
564	}
565	if (!message[i]) {
566		_nak(stub);
567		return parsed;
568	}
569	++i;
570	++parsed;
571	if (!message[i]) {
572		_nak(stub);
573		return parsed;
574	} else if (!message[i + 1]) {
575		++parsed;
576		_nak(stub);
577		return parsed;
578	}
579	parsed += 2;
580	int networkChecksum = _hex2int(&message[i], 2);
581	if (networkChecksum != checksum) {
582		mLOG(DEBUGGER, WARN, "Checksum error: expected %02x, got %02x", checksum, networkChecksum);
583		_nak(stub);
584		return parsed;
585	}
586
587	_ack(stub);
588	++message;
589	switch (messageType) {
590	case '?':
591		snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGINT);
592		_sendMessage(stub);
593		break;
594	case 'c':
595		_continue(stub, message);
596		break;
597	case 'G':
598		_writeGPRs(stub, message);
599		break;
600	case 'g':
601		_readGPRs(stub, message);
602		break;
603	case 'H':
604		// This is faked because we only have one thread
605		strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
606		_sendMessage(stub);
607		break;
608	case 'M':
609		_writeMemory(stub, message);
610		break;
611	case 'm':
612		_readMemory(stub, message);
613		break;
614	case 'P':
615		_writeRegister(stub, message);
616		break;
617	case 'p':
618		_readRegister(stub, message);
619		break;
620	case 'Q':
621		_processQWriteCommand(stub, message);
622		break;
623	case 'q':
624		_processQReadCommand(stub, message);
625		break;
626	case 's':
627		_step(stub, message);
628		break;
629	case 'V':
630		_processVWriteCommand(stub, message);
631		break;
632	case 'v':
633		_processVReadCommand(stub, message);
634		break;
635	case 'X':
636		_writeMemoryBinary(stub, message);
637                break;
638	case 'Z':
639		_setBreakpoint(stub, message);
640		break;
641	case 'z':
642		_clearBreakpoint(stub, message);
643		break;
644	default:
645		_error(stub, GDB_UNSUPPORTED_COMMAND);
646		break;
647	}
648	return parsed;
649}
650
651void GDBStubCreate(struct GDBStub* stub) {
652	stub->socket = INVALID_SOCKET;
653	stub->connection = INVALID_SOCKET;
654	stub->d.init = 0;
655	stub->d.deinit = _gdbStubDeinit;
656	stub->d.paused = _gdbStubWait;
657	stub->d.entered = _gdbStubEntered;
658	stub->d.custom = _gdbStubPoll;
659	stub->d.type = DEBUGGER_GDB;
660	stub->untilPoll = GDB_STUB_INTERVAL;
661	stub->lineAck = GDB_ACK_PENDING;
662	stub->shouldBlock = false;
663}
664
665bool GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) {
666	if (!SOCKET_FAILED(stub->socket)) {
667		GDBStubShutdown(stub);
668	}
669	stub->socket = SocketOpenTCP(port, bindAddress);
670	if (SOCKET_FAILED(stub->socket)) {
671		mLOG(DEBUGGER, ERROR, "Couldn't open socket");
672		return false;
673	}
674	if (!SocketSetBlocking(stub->socket, false)) {
675		goto cleanup;
676	}
677	int err = SocketListen(stub->socket, 1);
678	if (err) {
679		goto cleanup;
680	}
681
682	return true;
683
684cleanup:
685	mLOG(DEBUGGER, ERROR, "Couldn't listen on port");
686	SocketClose(stub->socket);
687	stub->socket = INVALID_SOCKET;
688	return false;
689}
690
691void GDBStubHangup(struct GDBStub* stub) {
692	if (!SOCKET_FAILED(stub->connection)) {
693		SocketClose(stub->connection);
694		stub->connection = INVALID_SOCKET;
695	}
696	if (stub->d.state == DEBUGGER_PAUSED) {
697		stub->d.state = DEBUGGER_RUNNING;
698	}
699}
700
701void GDBStubShutdown(struct GDBStub* stub) {
702	GDBStubHangup(stub);
703	if (!SOCKET_FAILED(stub->socket)) {
704		SocketClose(stub->socket);
705		stub->socket = INVALID_SOCKET;
706	}
707}
708
709void GDBStubUpdate(struct GDBStub* stub) {
710	if (stub->socket == INVALID_SOCKET) {
711		if (stub->d.state == DEBUGGER_PAUSED) {
712			stub->d.state = DEBUGGER_RUNNING;
713		}
714		return;
715	}
716	if (stub->connection == INVALID_SOCKET) {
717		if (stub->shouldBlock) {
718			Socket reads = stub->socket;
719			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
720		}
721		stub->connection = SocketAccept(stub->socket, 0);
722		if (!SOCKET_FAILED(stub->connection)) {
723			if (!SocketSetBlocking(stub->connection, false)) {
724				goto connectionLost;
725			}
726			mDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0);
727		} else if (SocketWouldBlock()) {
728			return;
729		} else {
730			goto connectionLost;
731		}
732	}
733	while (true) {
734		if (stub->shouldBlock) {
735			Socket reads = stub->connection;
736			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
737		}
738		ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
739		if (messageLen == 0) {
740			goto connectionLost;
741		}
742		if (messageLen == -1) {
743			if (SocketWouldBlock()) {
744				return;
745			}
746			goto connectionLost;
747		}
748		stub->line[messageLen] = '\0';
749		mLOG(DEBUGGER, DEBUG, "< %s", stub->line);
750		ssize_t position = 0;
751		while (position < messageLen) {
752			position += _parseGDBMessage(stub, &stub->line[position]);
753		}
754	}
755
756connectionLost:
757	mLOG(DEBUGGER, WARN, "Connection lost");
758	GDBStubHangup(stub);
759}