Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2935 → Rev 2936

/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);
}