diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-09-23 14:47:00 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-09-23 14:47:00 +0100 |
commit | c180e655c186e6cacc56bbdd20bb301f5df2b10b (patch) | |
tree | 6c08620ec67ad46d5b60fd0091625371fb17a887 /xen/common/gdbstub.c | |
parent | d85cf94621ab3531828430b0b50f860d0ff81887 (diff) | |
download | xen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.tar.gz xen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.tar.bz2 xen-c180e655c186e6cacc56bbdd20bb301f5df2b10b.zip |
Use GDB 'O' packets for console output if the serial line is shared
and GDB is attached.
It may be necessary for gdb and the console to share a serial port.
This patch utilises the GDB protocol to encode console output.
Based on a patch from Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/common/gdbstub.c')
-rw-r--r-- | xen/common/gdbstub.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/xen/common/gdbstub.c b/xen/common/gdbstub.c index 8934122925..257547ed19 100644 --- a/xen/common/gdbstub.c +++ b/xen/common/gdbstub.c @@ -357,6 +357,25 @@ gdb_cmd_write_mem(unsigned long addr, unsigned long length, gdb_send_packet(ctx); } +static void +gdbstub_attach(struct gdb_context *ctx) +{ + static void gdbstub_console_puts(const char *str); + if ( ctx->currently_attached ) + return; + ctx->currently_attached = 1; + ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts); +} + +static void +gdbstub_detach(struct gdb_context *ctx) +{ + if ( !ctx->currently_attached ) + return; + ctx->currently_attached = 0; + console_giveback(ctx->console_steal_id); +} + /* command dispatcher */ static int process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) @@ -427,7 +446,7 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) gdb_arch_read_reg(addr, regs, ctx); break; case 'D': - ctx->currently_attached = 0; + gdbstub_detach(ctx); gdb_send_reply("OK", ctx); /* fall through */ case 'k': @@ -444,7 +463,7 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) ctx->in_buf[1] ) addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long)); if ( ctx->in_buf[0] != 'D' ) - ctx->currently_attached = 1; + gdbstub_attach(ctx); resume = 1; gdb_arch_resume(regs, addr, type, ctx); break; @@ -459,17 +478,29 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) static struct gdb_context __gdb_ctx = { - .serhnd = -1, - .currently_attached = 0, - .running = ATOMIC_INIT(1), - .connected = 0, - .signum = 1, - .in_bytes = 0, - .out_offset = 0, - .out_csum = 0, + .serhnd = -1, + .running = ATOMIC_INIT(1), + .signum = 1 }; static struct gdb_context *gdb_ctx = &__gdb_ctx; +static void +gdbstub_console_puts(const char *str) +{ + const char *p; + + gdb_start_packet(gdb_ctx); + gdb_write_to_packet_char('O', gdb_ctx); + + for ( p = str; *p != '\0'; p++ ) + { + gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx ); + gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx ); + } + + gdb_send_packet(gdb_ctx); +} + /* trap handler: main entry point */ int __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) @@ -525,6 +556,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) gdb_arch_enter(regs); gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); + /* If gdb is already attached, tell it we've stopped again. */ if ( gdb_ctx->currently_attached ) { |