/branches/tracing/uspace/app/debug/cons.c |
---|
0,0 → 1,108 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup debug |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "cons.h" |
static char *line_buffer; |
static int line_chars; |
static int line_active = 0; |
static void line_show(void) |
{ |
int i; |
printf("> "); |
for (i = 0; i < line_chars; ++i) |
putchar(line_buffer[i]); |
} |
static void line_hide(void) |
{ |
int i; |
printf("\b\b"); |
for (i = 0; i < line_chars; ++i) |
putchar('\b'); |
} |
void cons_printf(const char *fmt, ...) |
{ |
va_list ap; |
if (line_active) line_hide(); |
va_start(ap, fmt); |
vprintf(fmt, ap); |
va_end(ap); |
if (line_active) line_show(); |
} |
void cons_read_line(char *buffer, int n) |
{ |
char c; |
int i; |
line_buffer = buffer; |
line_chars = 0; |
line_active = 1; |
line_show(); |
line_chars = 0; |
while (line_chars < n - 1) { |
c = getchar(); |
if (c == '\n') break; |
if (c == '\b') { |
if (line_chars > 0) { |
putchar('\b'); |
--line_chars; |
} |
continue; |
} |
putchar(c); |
buffer[line_chars++] = c; |
} |
putchar('\n'); |
buffer[line_chars] = '\0'; |
line_active = 0; |
} |
/** @} |
*/ |
/branches/tracing/uspace/app/debug/cmd.c |
---|
40,6 → 40,7 |
#include <sys/types.h> |
#include "main.h" |
#include "cons.h" |
#include "include/arch.h" |
#include "cmd.h" |
67,7 → 68,7 |
(void)argc; |
addr = strtoul(argv[1], NULL, 0); |
printf("You requested a breakpoint at 0x%x\n", addr); |
cons_printf("You requested a breakpoint at 0x%x\n", addr); |
arch_breakpoint_add(addr); |
} |
83,7 → 84,7 |
(void)argc; (void)argv; |
i = 0; |
while (cmd_table[i].name != NULL) { |
printf("%s\n", cmd_table[i].name); |
cons_printf("%s\n", cmd_table[i].name); |
++i; |
} |
} |
107,16 → 108,16 |
rc = udebug_mem_read(app_phone, buf, addr, to_read); |
if (rc < 0) { |
printf("error %d\n", rc); |
cons_printf("error %d\n", rc); |
return; |
} |
printf("0x%x:", addr); |
cons_printf("0x%x:", addr); |
for (i = 0; i < to_read; ++i) { |
printf(" %02x", buf[i]); |
cons_printf(" %02x", buf[i]); |
} |
for (i = to_read; i < BYTES_PER_LINE; ++i) { |
printf(" "); |
cons_printf(" "); |
} |
putchar ('\t'); |
127,7 → 128,7 |
else |
putchar('.'); |
} |
printf("\n"); |
cons_printf("\n"); |
addr += to_read; |
length -= to_read; |
/branches/tracing/uspace/app/debug/main.c |
---|
44,6 → 44,7 |
#include <string.h> |
#include "cmd.h" |
#include "cons.h" |
#include "include/arch.h" |
#include "fib_synch.h" |
#include "main.h" |
50,8 → 51,8 |
void thread_debug_start(unsigned thread_hash); |
#define INBUF_SIZE 64 |
char in_buf[INBUF_SIZE]; |
#define IN_BUF_SIZE 64 |
static char in_buf[IN_BUF_SIZE]; |
#define MAX_ARGC 10 |
int cmd_argc; |
74,31 → 75,6 |
fcv_t go_cv; |
void read_line(char *buffer, int n) |
{ |
char c; |
int i; |
i = 0; |
while (i < n - 1) { |
c = getchar(); |
if (c == '\n') break; |
if (c == '\b') { |
if (i > 0) { |
putchar('\b'); |
--i; |
} |
continue; |
} |
putchar(c); |
buffer[i++] = c; |
} |
putchar('\n'); |
buffer[i] = '\0'; |
} |
void command_split(char *cmd_str) |
{ |
char *p = cmd_str; |
150,13 → 126,13 |
} |
if (num_found == 0) { |
printf("Unknown command. Try one of:\n"); |
cons_printf("Unknown command. Try one of:\n"); |
cmd_help(0, NULL); |
return; |
} |
if (cmd_argc - 1 != cmd_table[idx_found].argc) { |
printf("Command '%s' expects %d arguments\n", |
cons_printf("Command '%s' expects %d arguments\n", |
cmd_table[idx_found].name, cmd_table[idx_found].argc); |
return; |
} |
164,12 → 140,20 |
(*cmd_table[idx_found].proc)(cmd_argc, cmd_argv); |
} |
void thread_stop(void) |
{ |
cons_printf("[t] stopped\n"); |
fcv_wait(&go_cv); |
cons_printf("[t] go\n"); |
} |
/* |
* Called by a fibril (from arch code) when a breakpoint is hit. |
*/ |
void breakpoint_hit(void) |
{ |
fcv_wait(&go_cv); |
cons_printf("breakpoint hit\n"); |
thread_stop(); |
} |
int task_connect(int taskid) |
177,21 → 161,21 |
int rc; |
unsigned evmask; |
printf("ipc_connect_kbox(%d)... ", taskid); |
cons_printf("ipc_connect_kbox(%d)... ", taskid); |
rc = ipc_connect_kbox(taskid); |
printf("-> %d\n", rc); |
cons_printf("-> %d\n", rc); |
app_phone = rc; |
if (rc < 0) return rc; |
printf("udebug_begin()... "); |
cons_printf("udebug_begin()... "); |
rc = udebug_begin(app_phone); |
printf("-> %d\n", rc); |
cons_printf("-> %d\n", rc); |
if (rc < 0) return rc; |
evmask = UDEBUG_EM_ALL & ~(UDEBUG_EM_SYSCALL_B | UDEBUG_EM_SYSCALL_E); |
printf("udebug_set_evmask(0x%x)... ", evmask); |
cons_printf("udebug_set_evmask(0x%x)... ", evmask); |
rc = udebug_set_evmask(app_phone, evmask); |
printf("-> %d\n", rc); |
cons_printf("-> %d\n", rc); |
if (rc < 0) return rc; |
return 0; |
204,19 → 188,19 |
int tb_needed; |
int i; |
printf("send IPC_M_DEBUG_THREAD_READ message\n"); |
cons_printf("send IPC_M_DEBUG_THREAD_READ message\n"); |
rc = udebug_thread_read(app_phone, (unsigned)thread_hash_buf, |
THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed); |
printf("-> %d\n", rc); |
cons_printf("-> %d\n", rc); |
if (rc < 0) return rc; |
n_threads = tb_copied / sizeof(unsigned); |
printf("thread IDs:"); |
cons_printf("thread IDs:"); |
for (i=0; i<n_threads; i++) { |
printf(" %u", thread_hash_buf[i]); |
cons_printf(" %u", thread_hash_buf[i]); |
} |
printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned)); |
cons_printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned)); |
return 0; |
} |
224,7 → 208,7 |
void event_thread_b(unsigned hash) |
{ |
async_serialize_start(); |
printf("new thread, hash 0x%x\n", hash); |
cons_printf("new thread, hash 0x%x\n", hash); |
async_serialize_end(); |
thread_debug_start(hash); |
236,20 → 220,20 |
{ |
switch (ev_type) { |
case UDEBUG_EVENT_STOP: |
printf("stop event\n"); |
printf("waiting for resume\n"); |
cons_printf("stop event\n"); |
cons_printf("waiting for resume\n"); |
while (paused) { |
usleep(1000000); |
fibril_yield(); |
printf("."); |
cons_printf("."); |
} |
printf("resumed\n"); |
cons_printf("resumed\n"); |
break; |
case UDEBUG_EVENT_THREAD_B: |
event_thread_b(val0); |
break; |
case UDEBUG_EVENT_THREAD_E: |
printf("thread 0x%x exited\n", val0); |
cons_printf("thread 0x%x exited\n", val0); |
abort_debug = true; |
break; |
case UDEBUG_EVENT_BREAKPOINT: |
259,7 → 243,7 |
arch_event_trap(thash); |
break; |
default: |
printf("unknown event type %d\n", ev_type); |
cons_printf("unknown event type %d\n", ev_type); |
break; |
} |
} |
275,24 → 259,22 |
thread_hash = (unsigned)thread_hash_arg; |
thread_id = next_thread_id++; |
printf("debug_loop(%d)\n", thread_id); |
cons_printf("debug_loop(%d)\n", thread_id); |
while (!abort_debug) { |
printf("[t%d] go...\n", thread_id); |
/* Run thread until an event occurs */ |
rc = udebug_go(app_phone, thread_hash, |
&ev_type, &val0, &val1); |
printf("[t%d] stopped\n", thread_id); |
if (ev_type == UDEBUG_EVENT_FINISHED) { |
printf("thread %u debugging finished\n", thread_id); |
cons_printf("thread %u debugging finished\n", thread_id); |
break; |
} |
if (rc >= 0) debug_event(thread_hash, ev_type, val0); |
} |
printf("debug_loop(%d) exiting\n", thread_id); |
cons_printf("debug_loop(%d) exiting\n", thread_id); |
} |
void thread_debug_start(unsigned thread_hash) |
303,7 → 285,7 |
fid = fibril_create(debug_loop, (void *)thread_hash); |
if (fid == 0) { |
printf("Warning: Failed creating fibril\n"); |
cons_printf("Warning: Failed creating fibril\n"); |
} |
fibril_add_ready(fid); |
} |
315,8 → 297,8 |
int rc; |
int c; |
printf("Breakpoint Debugger\n"); |
printf("Press 'c' to connect\n"); |
cons_printf("Breakpoint Debugger\n"); |
cons_printf("Press 'c' to connect\n"); |
while ((i = getchar()) != 'c') |
putchar(i); |
323,15 → 305,15 |
taskid = 14; |
rc = task_connect(taskid); |
if (rc < 0) { |
printf("Failed to connect to task %d\n", taskid); |
cons_printf("Failed to connect to task %d\n", taskid); |
return; |
} |
printf("Connected to task %d\n", taskid); |
cons_printf("Connected to task %d\n", taskid); |
rc = get_thread_list(); |
if (rc < 0) { |
printf("Failed to get thread list (error %d)\n", rc); |
cons_printf("Failed to get thread list (error %d)\n", rc); |
return; |
} |
342,8 → 324,7 |
} |
while (!quit) { |
printf("> "); |
read_line(in_buf, INBUF_SIZE); |
cons_read_line(in_buf, IN_BUF_SIZE); |
command_split(in_buf); |
if (cmd_argc == 0) continue; |
350,12 → 331,12 |
command_run(); |
} |
printf("terminate debugging session...\n"); |
cons_printf("terminate debugging session...\n"); |
abort_debug = true; |
udebug_end(app_phone); |
ipc_hangup(app_phone); |
printf("done\n"); |
cons_printf("done\n"); |
return; |
} |
/branches/tracing/uspace/app/debug/cons.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup debug |
* @{ |
*/ |
/** @file |
*/ |
#ifndef CONS_H_ |
#define CONS_H_ |
void cons_printf(const char *fmt, ...); |
void cons_read_line(char *buffer, int n); |
#endif |
/** @} |
*/ |
/branches/tracing/uspace/app/debug/Makefile |
---|
45,6 → 45,7 |
OUTPUT = debug |
GENERIC_SOURCES = cmd.c \ |
fib_synch.c \ |
cons.c \ |
main.c |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
/branches/tracing/uspace/app/debug/arch/mips32/src/mips32.c |
---|
38,6 → 38,7 |
#include <udebug.h> |
#include <kernel/arch/context_offset.h> |
#include "../../../cons.h" |
#include "../../../main.h" |
#include "../../../include/arch.h" |
58,16 → 59,16 |
} |
if (!brk) { |
printf("too many breakpoints\n"); |
cons_printf("too many breakpoints\n"); |
return; |
} |
rc = udebug_mem_read(app_phone, &brk->arch.back, addr, sizeof(&brk->arch.back)); |
printf("udebug_mem_read() -> %d\n", rc); |
cons_printf("udebug_mem_read() -> %d\n", rc); |
brkp = OPCODE_BREAK; |
rc = udebug_mem_write(app_phone, &brkp, addr, sizeof(brkp)); |
// for (i=0; i<256; i++) rc = udebug_mem_write(app_phone, &brkp, addr+4*i, sizeof(brkp)); |
printf("udebug_mem_write() -> %d\n", rc); |
cons_printf("udebug_mem_write() -> %d\n", rc); |
brk->addr = addr; |
brk->set = 1; |
86,9 → 87,9 |
brkp = OPCODE_BREAK; |
rc = udebug_regs_read(app_phone, thread_hash, buffer); |
printf("udebug_regs_read -> %d\n", rc); |
cons_printf("udebug_regs_read -> %d\n", rc); |
epc = buffer[EOFFSET_EPC/sizeof(unsigned)]; |
printf("EPC was 0x%08x\n", epc); |
cons_printf("EPC was 0x%08x\n", epc); |
brk_addr = epc; |
int bi; |
97,11 → 98,11 |
break; |
} |
if (bi < MAX_BRKPTS) { |
printf("breakpoint %d hit\n", bi); |
cons_printf("breakpoint %d hit\n", bi); |
breakpoint_hit(); |
rc = udebug_mem_write(app_phone, &brk_list[bi].arch.back, brk_addr, 4); |
printf("udebug_mem_write(phone, 0x%x, 0x%02x, 1) -> %d\n", brk_addr, brk_list[bi].arch.back, rc); |
cons_printf("udebug_mem_write(phone, 0x%x, 0x%02x, 1) -> %d\n", brk_addr, brk_list[bi].arch.back, rc); |
rc = udebug_mem_read(app_phone, &brk_list[bi].arch.back, brk_addr+4, 4); |
rc = udebug_mem_write(app_phone, &brkp, brk_addr+4, 4); |
lifted_brkpt = &brk_list[bi]; |
113,7 → 114,7 |
break; |
} |
if (bi < MAX_BRKPTS) { |
printf("restoring breakpoint %d\n", bi); |
cons_printf("restoring breakpoint %d\n", bi); |
rc = udebug_mem_write(app_phone, &brk_list[bi].arch.back, brk_addr, 4); |
rc = udebug_mem_read(app_phone, &brk_list[bi].arch.back, brk_addr-4, 4); |
rc = udebug_mem_write(app_phone, &brkp, brk_addr-4, 4); |
121,7 → 122,7 |
return; |
} |
printf("unrecognized breakpoint at 0x%x\n", brk_addr); |
cons_printf("unrecognized breakpoint at 0x%x\n", brk_addr); |
} |
void arch_event_trap(thash_t thread_hash) |
/branches/tracing/uspace/app/debug/arch/ia32/src/ia32.c |
---|
37,6 → 37,7 |
#include <sys/types.h> |
#include <udebug.h> |
#include "../../../cons.h" |
#include "../../../main.h" |
#include "../../../include/arch.h" |
57,15 → 58,15 |
if (brk_list[i].set == 0) brk = brk_list+i; |
if (!brk) { |
printf("too many breakpoints\n"); |
cons_printf("too many breakpoints\n"); |
return; |
} |
rc = udebug_mem_read(app_phone, &brk->arch.back, addr, 1); |
printf("udebug_mem_read() -> %d\n", rc); |
cons_printf("udebug_mem_read() -> %d\n", rc); |
brkp[0] = OPCODE_INT3; |
rc = udebug_mem_write(app_phone, brkp, addr, 1); |
printf("udebug_mem_write() -> %d\n", rc); |
cons_printf("udebug_mem_write() -> %d\n", rc); |
brk->addr = addr; |
brk->set = 1; |
79,8 → 80,8 |
int rc; |
rc = udebug_regs_read(app_phone, thread_hash, buffer); |
printf("udebug_regs_read -> %d\n", rc); |
printf("EIP was 0x%08x\n", buffer[ISTATE_OFF_EIP]); |
cons_printf("udebug_regs_read -> %d\n", rc); |
cons_printf("EIP was 0x%08x\n", buffer[ISTATE_OFF_EIP]); |
int brk_addr = buffer[ISTATE_OFF_EIP] - 1; |
int bi; |
for (bi = 0; bi < MAX_BRKPTS; bi++) { |
89,18 → 90,18 |
} |
if (bi < MAX_BRKPTS) { |
printf("breakpoint %d hit\n", bi); |
cons_printf("breakpoint %d hit\n", bi); |
breakpoint_hit(); |
buffer[ISTATE_OFF_EIP] = brk_addr; |
buffer[ISTATE_OFF_EFLAGS] |= 0x0100; /* trap flag */ |
printf("setting EIP to 0x%08x\n", buffer[ISTATE_OFF_EIP]); |
cons_printf("setting EIP to 0x%08x\n", buffer[ISTATE_OFF_EIP]); |
rc = udebug_regs_write(app_phone, thread_hash, buffer); |
rc = udebug_mem_write(app_phone, &brk_list[bi].arch.back, brk_addr, 1); |
printf("udebug_mem_write(phone, 0x%x, 0x%02x, 1) -> %d\n", brk_addr, brk_list[bi].arch.back, rc); |
cons_printf("udebug_mem_write(phone, 0x%x, 0x%02x, 1) -> %d\n", brk_addr, brk_list[bi].arch.back, rc); |
lifted_brkpt = &brk_list[bi]; |
} else { |
printf("unrecognized breakpoint at 0x%x\n", brk_addr); |
cons_printf("unrecognized breakpoint at 0x%x\n", brk_addr); |
} |
} |
109,15 → 110,15 |
unsigned char brkinstr[1]; |
int rc; |
printf("trap event\n"); |
cons_printf("trap event\n"); |
breakpoint_t *lb = lifted_brkpt; |
brkinstr[0] = OPCODE_INT3; |
rc = udebug_mem_write(app_phone, brkinstr, lb->addr, 1); |
printf("restore breakpoint -> %d\n", rc); |
cons_printf("restore breakpoint -> %d\n", rc); |
rc = udebug_regs_read(app_phone, thread_hash, buffer); |
printf("udebug_regs_read -> %d\n", rc); |
cons_printf("udebug_regs_read -> %d\n", rc); |
buffer[ISTATE_OFF_EFLAGS] &= ~0x0100; /* trap flag */ |
rc = udebug_regs_write(app_phone, thread_hash, buffer); |
} |