mirror of https://github.com/mgba-emu/mgba.git
Add debugging logging interface
This commit is contained in:
parent
d97976d0df
commit
b9f8955890
|
@ -31,6 +31,13 @@ enum DebuggerEntryReason {
|
||||||
DEBUGGER_ENTER_ILLEGAL_OP
|
DEBUGGER_ENTER_ILLEGAL_OP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DebuggerLogLevel {
|
||||||
|
DEBUGGER_LOG_DEBUG = 0x01,
|
||||||
|
DEBUGGER_LOG_INFO = 0x02,
|
||||||
|
DEBUGGER_LOG_WARN = 0x04,
|
||||||
|
DEBUGGER_LOG_ERROR = 0x08
|
||||||
|
};
|
||||||
|
|
||||||
struct ARMDebugger {
|
struct ARMDebugger {
|
||||||
enum DebuggerState state;
|
enum DebuggerState state;
|
||||||
struct ARMCore* cpu;
|
struct ARMCore* cpu;
|
||||||
|
@ -42,6 +49,9 @@ struct ARMDebugger {
|
||||||
void (*deinit)(struct ARMDebugger*);
|
void (*deinit)(struct ARMDebugger*);
|
||||||
void (*paused)(struct ARMDebugger*);
|
void (*paused)(struct ARMDebugger*);
|
||||||
void (*entered)(struct ARMDebugger*, enum DebuggerEntryReason);
|
void (*entered)(struct ARMDebugger*, enum DebuggerEntryReason);
|
||||||
|
|
||||||
|
__attribute__((format (printf, 3, 4)))
|
||||||
|
void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*);
|
void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*);
|
||||||
|
|
|
@ -71,7 +71,9 @@ static void _ack(struct GDBStub* stub) {
|
||||||
|
|
||||||
static void _nak(struct GDBStub* stub) {
|
static void _nak(struct GDBStub* stub) {
|
||||||
char nak = '-';
|
char nak = '-';
|
||||||
printf("Packet error\n");
|
if (stub->d.log) {
|
||||||
|
stub->d.log(&stub->d, DEBUGGER_LOG_WARN, "Packet error");
|
||||||
|
}
|
||||||
send(stub->connection, &nak, 1, 0);
|
send(stub->connection, &nak, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +152,9 @@ static void _sendMessage(struct GDBStub* stub) {
|
||||||
stub->outgoing[i] = '#';
|
stub->outgoing[i] = '#';
|
||||||
_int2hex8(checksum, &stub->outgoing[i + 1]);
|
_int2hex8(checksum, &stub->outgoing[i + 1]);
|
||||||
stub->outgoing[i + 3] = 0;
|
stub->outgoing[i + 3] = 0;
|
||||||
|
if (stub->d.log) {
|
||||||
|
stub->d.log(&stub->d, DEBUGGER_LOG_DEBUG, "> %s", stub->outgoing);
|
||||||
|
}
|
||||||
send(stub->connection, stub->outgoing, i + 3, 0);
|
send(stub->connection, stub->outgoing, i + 3, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +371,9 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
|
||||||
parsed += 2;
|
parsed += 2;
|
||||||
int networkChecksum = _hex2int(&message[i], 2);
|
int networkChecksum = _hex2int(&message[i], 2);
|
||||||
if (networkChecksum != checksum) {
|
if (networkChecksum != checksum) {
|
||||||
printf("Checksum error: expected %02x, got %02x\n", checksum, networkChecksum);
|
if (stub->d.log) {
|
||||||
|
stub->d.log(&stub->d, DEBUGGER_LOG_WARN, "Checksum error: expected %02x, got %02x", checksum, networkChecksum);
|
||||||
|
}
|
||||||
_nak(stub);
|
_nak(stub);
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
@ -430,6 +437,7 @@ void GDBStubCreate(struct GDBStub* stub) {
|
||||||
stub->d.deinit = _gdbStubDeinit;
|
stub->d.deinit = _gdbStubDeinit;
|
||||||
stub->d.paused = _gdbStubPoll;
|
stub->d.paused = _gdbStubPoll;
|
||||||
stub->d.entered = _gdbStubEntered;
|
stub->d.entered = _gdbStubEntered;
|
||||||
|
stub->d.log = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
|
int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
|
||||||
|
@ -439,7 +447,9 @@ int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
|
||||||
// TODO: support IPv6
|
// TODO: support IPv6
|
||||||
stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (stub->socket < 0) {
|
if (stub->socket < 0) {
|
||||||
printf("Couldn't open socket\n");
|
if (stub->d.log) {
|
||||||
|
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't open socket");
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,6 +528,9 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
goto connectionLost;
|
goto connectionLost;
|
||||||
}
|
}
|
||||||
stub->line[messageLen] = '\0';
|
stub->line[messageLen] = '\0';
|
||||||
|
if (stub->d.log) {
|
||||||
|
stub->d.log(&stub->d, DEBUGGER_LOG_DEBUG, "< %s", stub->line);
|
||||||
|
}
|
||||||
ssize_t position = 0;
|
ssize_t position = 0;
|
||||||
while (position < messageLen) {
|
while (position < messageLen) {
|
||||||
position += _parseGDBMessage(stub, &stub->line[position]);
|
position += _parseGDBMessage(stub, &stub->line[position]);
|
||||||
|
@ -525,7 +538,8 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionLost:
|
connectionLost:
|
||||||
// TODO: add logging support to the debugging interface
|
if (stub->d.log) {
|
||||||
printf("Connection lost\n");
|
stub->d.log(&stub->d, DEBUGGER_LOG_INFO, "Connection lost");
|
||||||
|
}
|
||||||
GDBStubHangup(stub);
|
GDBStubHangup(stub);
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,7 +503,7 @@ int GBAHalt(struct GBA* gba) {
|
||||||
return GBAWaitForIRQ(gba);
|
return GBAWaitForIRQ(gba);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
static void _GBAVLog(struct GBA* gba, enum GBALogLevel level, const char* format, va_list args) {
|
||||||
if (!gba) {
|
if (!gba) {
|
||||||
struct GBAThread* threadContext = GBAThreadGetContext();
|
struct GBAThread* threadContext = GBAThreadGetContext();
|
||||||
if (threadContext) {
|
if (threadContext) {
|
||||||
|
@ -512,10 +512,7 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gba && gba->logHandler) {
|
if (gba && gba->logHandler) {
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
gba->logHandler(gba, level, format, args);
|
gba->logHandler(gba, level, format, args);
|
||||||
va_end(args);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,10 +520,7 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
vprintf(format, args);
|
vprintf(format, args);
|
||||||
va_end(args);
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (level == GBA_LOG_FATAL) {
|
if (level == GBA_LOG_FATAL) {
|
||||||
|
@ -534,6 +528,38 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
_GBAVLog(gba, level, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
|
||||||
|
struct GBABoard* gbaBoard = (struct GBABoard*) debugger->cpu->board;
|
||||||
|
|
||||||
|
enum GBALogLevel gbaLevel;
|
||||||
|
switch (level) {
|
||||||
|
case DEBUGGER_LOG_DEBUG:
|
||||||
|
gbaLevel = GBA_LOG_DEBUG;
|
||||||
|
break;
|
||||||
|
case DEBUGGER_LOG_INFO:
|
||||||
|
gbaLevel = GBA_LOG_INFO;
|
||||||
|
break;
|
||||||
|
case DEBUGGER_LOG_WARN:
|
||||||
|
gbaLevel = GBA_LOG_WARN;
|
||||||
|
break;
|
||||||
|
case DEBUGGER_LOG_ERROR:
|
||||||
|
gbaLevel = GBA_LOG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
_GBAVLog(gbaBoard->p, gbaLevel, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
|
void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
|
||||||
struct GBABoard* gbaBoard = (struct GBABoard*) board;
|
struct GBABoard* gbaBoard = (struct GBABoard*) board;
|
||||||
enum GBALogLevel level = GBA_LOG_FATAL;
|
enum GBALogLevel level = GBA_LOG_FATAL;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GBA_H
|
#define GBA_H
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
#include "gba-memory.h"
|
#include "gba-memory.h"
|
||||||
#include "gba-video.h"
|
#include "gba-video.h"
|
||||||
|
@ -146,4 +147,7 @@ void GBALoadBIOS(struct GBA* gba, int fd);
|
||||||
__attribute__((format (printf, 3, 4)))
|
__attribute__((format (printf, 3, 4)))
|
||||||
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...);
|
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...);
|
||||||
|
|
||||||
|
__attribute__((format (printf, 3, 4)))
|
||||||
|
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue