eclair: support for live debug
Change-Id: Ia9bc126e198ba4a80722529ce09de5eb0775d429
This commit is contained in:
@ -22,6 +22,7 @@
|
||||
#include <ihk/ihk_host_user.h>
|
||||
#include <eclair.h>
|
||||
#include <arch-eclair.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define CPU_TID_BASE 1000000
|
||||
|
||||
@ -78,6 +79,7 @@ uintptr_t kernel_base;
|
||||
static struct thread_info *tihead = NULL;
|
||||
static struct thread_info **titailp = &tihead;
|
||||
static struct thread_info *curr_thread = NULL;
|
||||
static int remote_running;
|
||||
|
||||
uintptr_t lookup_symbol(char *name)
|
||||
{
|
||||
@ -272,13 +274,15 @@ static int setup_threads(void) {
|
||||
uintptr_t current;
|
||||
uintptr_t locals;
|
||||
size_t locals_span;
|
||||
struct thread_info *ti;
|
||||
struct thread_info *tin;
|
||||
|
||||
error = read_symbol_64("num_processors", &num_processors);
|
||||
if (error) {
|
||||
perror("num_processors");
|
||||
return 1;
|
||||
}
|
||||
printf("%s: num_processors: %d\n", __FUNCTION__, num_processors);
|
||||
dprintf("%s: num_processors: %d\n", __func__, num_processors);
|
||||
|
||||
error = read_symbol_64("locals", &locals);
|
||||
if (error) {
|
||||
@ -298,6 +302,15 @@ static int setup_threads(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Drop previous threads */
|
||||
for (ti = tihead; ti; ) {
|
||||
tin = ti->next;
|
||||
free(ti);
|
||||
ti = tin;
|
||||
}
|
||||
tihead = NULL;
|
||||
titailp = &tihead;
|
||||
|
||||
for (cpu = 0; cpu < num_processors; ++cpu) {
|
||||
uintptr_t v;
|
||||
uintptr_t head;
|
||||
@ -558,6 +571,62 @@ static int setup_symbols(char *fname) {
|
||||
return 0;
|
||||
} /* setup_symbols() */
|
||||
|
||||
static int setup_dump_interactive(void)
|
||||
{
|
||||
int error;
|
||||
long mem_size;
|
||||
int dump_level = DUMP_LEVEL_ALL;
|
||||
dumpargs_t args;
|
||||
|
||||
args.cmd = DUMP_SET_LEVEL;
|
||||
args.level = dump_level;
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_SET_LEVEL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
args.cmd = DUMP_NMI;
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_NMI");
|
||||
return 1;
|
||||
}
|
||||
|
||||
remote_running = 0;
|
||||
|
||||
args.cmd = DUMP_QUERY_NUM_MEM_AREAS;
|
||||
args.size = 0;
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_QUERY_NUM_MEM_AREAS");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mem_size = args.size;
|
||||
mem_chunks = malloc(mem_size);
|
||||
if (!mem_chunks) {
|
||||
perror("allocating mem_chunks");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(mem_chunks, 0, mem_size);
|
||||
|
||||
args.cmd = DUMP_QUERY_MEM_AREAS;
|
||||
args.buf = (void *)mem_chunks;
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_QUERY_MEM_AREAS");
|
||||
return 1;
|
||||
}
|
||||
|
||||
kernel_base = mem_chunks->kernel_base;
|
||||
PHYS_OFFSET = mem_chunks->phys_start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int setup_dump(char *fname) {
|
||||
bfd_boolean ok;
|
||||
long mem_size;
|
||||
@ -670,11 +739,13 @@ ssize_t print_bin(char *buf, size_t buf_size, void *data, size_t size) {
|
||||
static void command(const char *cmd, char *res, size_t res_size) {
|
||||
const char *p;
|
||||
char *rbp;
|
||||
int error;
|
||||
|
||||
p = cmd;
|
||||
rbp = res;
|
||||
|
||||
do {
|
||||
dprintf("query: %s\n", p);
|
||||
if (!strncmp(p, "qSupported", 10)) {
|
||||
rbp += sprintf(rbp, "PacketSize=1024");
|
||||
rbp += sprintf(rbp, ";qXfer:features:read+");
|
||||
@ -704,9 +775,80 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
}
|
||||
rbp += sprintf(rbp, "OK");
|
||||
}
|
||||
else if (!strcmp(p, "Hc-1")) {
|
||||
else if (!strncmp(p, "Hc", 2)) {
|
||||
if (opt.interactive) {
|
||||
rbp += sprintf(rbp, "OK");
|
||||
}
|
||||
else {
|
||||
rbp += sprintf(rbp, "S02");
|
||||
}
|
||||
}
|
||||
else if (opt.interactive &&
|
||||
!strcmp(p, "vCtrlC")) {
|
||||
if (remote_running) {
|
||||
dumpargs_t args;
|
||||
args.cmd = DUMP_NMI;
|
||||
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_NMI");
|
||||
break;
|
||||
}
|
||||
|
||||
remote_running = 0;
|
||||
}
|
||||
rbp += sprintf(rbp, "OK");
|
||||
}
|
||||
else if (opt.interactive &&
|
||||
!strcmp(p, "Ctrl-C")) {
|
||||
if (remote_running) {
|
||||
dumpargs_t args;
|
||||
args.cmd = DUMP_NMI;
|
||||
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_NMI");
|
||||
break;
|
||||
}
|
||||
|
||||
remote_running = 0;
|
||||
}
|
||||
rbp += sprintf(rbp, "S02");
|
||||
}
|
||||
else if (!strcmp(p, "vCont?")) {
|
||||
if (opt.interactive) {
|
||||
rbp += sprintf(rbp, "vCont;c");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "c")) {
|
||||
if (opt.interactive) {
|
||||
if (!remote_running) {
|
||||
dumpargs_t args;
|
||||
args.cmd = DUMP_NMI_CONT;
|
||||
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_NMI_CONT for continue");
|
||||
break;
|
||||
}
|
||||
|
||||
remote_running = 1;
|
||||
}
|
||||
rbp += sprintf(rbp, "OK");
|
||||
}
|
||||
else {
|
||||
rbp += sprintf(rbp, "S02");
|
||||
}
|
||||
}
|
||||
else if (opt.interactive &&
|
||||
!strcmp(p, "?")) {
|
||||
if (remote_running) {
|
||||
rbp += sprintf(rbp, "S12");
|
||||
}
|
||||
else {
|
||||
rbp += sprintf(rbp, "S02");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "?")) {
|
||||
rbp += sprintf(rbp, "S02");
|
||||
}
|
||||
@ -727,12 +869,23 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
rbp += sprintf(rbp, "%s", str);
|
||||
}
|
||||
else if (!strcmp(p, "D")) {
|
||||
if (opt.interactive && !remote_running) {
|
||||
dumpargs_t args;
|
||||
args.cmd = DUMP_NMI_CONT;
|
||||
|
||||
error = ioctl(opt.mcos_fd, IHK_OS_DUMP, &args);
|
||||
if (error) {
|
||||
perror("DUMP_NMI_CONT for continue");
|
||||
break;
|
||||
}
|
||||
|
||||
remote_running = 1;
|
||||
}
|
||||
rbp += sprintf(rbp, "OK");
|
||||
f_done = 1;
|
||||
}
|
||||
else if (!strcmp(p, "g")) {
|
||||
if (curr_thread->cpu < 0) {
|
||||
|
||||
int error;
|
||||
struct arch_kregs kregs;
|
||||
|
||||
@ -790,7 +943,8 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
for (addr = start; addr < (start + size); ++addr) {
|
||||
error = read_mem(addr, &u8, sizeof(u8));
|
||||
if (error) {
|
||||
u8 = 0xE5;
|
||||
//u8 = 0xE5;
|
||||
u8 = 0x00;
|
||||
}
|
||||
rbp += sprintf(rbp, "%02x", u8);
|
||||
}
|
||||
@ -834,6 +988,14 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
else if (!strcmp(p, "qfThreadInfo")) {
|
||||
struct thread_info *ti;
|
||||
|
||||
if (opt.interactive) {
|
||||
error = setup_threads();
|
||||
if (error) {
|
||||
perror("setup_threads");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (ti = tihead; ti; ti = ti->next) {
|
||||
if (ti == tihead) {
|
||||
rbp += sprintf(rbp, "m%x", ti->tid);
|
||||
@ -871,29 +1033,29 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
q = buf;
|
||||
q += sprintf(q, "PID %d, ", ti->pid);
|
||||
if (ti->status & PS_RUNNING) {
|
||||
q += sprintf(q, "%srunning on cpu %d",
|
||||
q += sprintf(q, "%srunning on CPU %d",
|
||||
ti->idle ? "idle " : "", ti->lcpu);
|
||||
}
|
||||
else if (ti->status & (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE)) {
|
||||
q += sprintf(q, "%swaiting on cpu %d",
|
||||
q += sprintf(q, "%swaiting on CPU %d",
|
||||
ti->idle ? "idle " : "", ti->lcpu);
|
||||
}
|
||||
else if (ti->status & PS_STOPPED) {
|
||||
q += sprintf(q, "%sstopped on cpu %d",
|
||||
q += sprintf(q, "%sstopped on CPU %d",
|
||||
ti->idle ? "idle " : "", ti->lcpu);
|
||||
}
|
||||
else if (ti->status & PS_TRACED) {
|
||||
q += sprintf(q, "%straced on cpu %d",
|
||||
q += sprintf(q, "%straced on CPU %d",
|
||||
ti->idle ? "idle " : "", ti->lcpu);
|
||||
}
|
||||
else if (ti->status == CS_IDLE) {
|
||||
q += sprintf(q, "cpu %d idle", ti->cpu);
|
||||
q += sprintf(q, "CPU %d idle", ti->cpu);
|
||||
}
|
||||
else if (ti->status == CS_RUNNING) {
|
||||
q += sprintf(q, "cpu %d running", ti->cpu);
|
||||
q += sprintf(q, "CPU %d running", ti->cpu);
|
||||
}
|
||||
else if (ti->status == CS_RESERVED) {
|
||||
q += sprintf(q, "cpu %d reserved", ti->cpu);
|
||||
q += sprintf(q, "CPU %d reserved", ti->cpu);
|
||||
}
|
||||
else {
|
||||
q += sprintf(q, "status=%#x", ti->status);
|
||||
@ -903,6 +1065,7 @@ static void command(const char *cmd, char *res, size_t res_size) {
|
||||
} while (0);
|
||||
|
||||
*rbp = '\0';
|
||||
dprintf("res: %s\n", res);
|
||||
return;
|
||||
} /* command() */
|
||||
|
||||
@ -965,14 +1128,24 @@ static void options(int argc, char *argv[]) {
|
||||
static int sock = -1;
|
||||
static FILE *ifp = NULL;
|
||||
static FILE *ofp = NULL;
|
||||
pid_t gdbpid;
|
||||
|
||||
void intr_handler(int dummy)
|
||||
{
|
||||
kill(gdbpid, SIGINT);
|
||||
}
|
||||
|
||||
|
||||
static int start_gdb(void) {
|
||||
struct sockaddr_in sin;
|
||||
socklen_t slen;
|
||||
int error;
|
||||
pid_t pid;
|
||||
int ss;
|
||||
|
||||
if (opt.interactive) {
|
||||
signal(SIGINT, intr_handler);
|
||||
}
|
||||
|
||||
sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
perror("socket");
|
||||
@ -992,13 +1165,13 @@ static int start_gdb(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == (pid_t)-1) {
|
||||
gdbpid = fork();
|
||||
if (gdbpid == (pid_t)-1) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
if (!gdbpid) {
|
||||
char buf[32];
|
||||
|
||||
sprintf(buf, "target remote :%d", ntohs(sin.sin_port));
|
||||
@ -1046,8 +1219,10 @@ int main(int argc, char *argv[]) {
|
||||
char *lbp;
|
||||
char *p;
|
||||
|
||||
printf("eclair 0.20160314\n");
|
||||
options(argc, argv);
|
||||
printf("eclair 0.20160314 %s%s\n",
|
||||
opt.interactive ? "live debug mode" : "using dump file: ",
|
||||
opt.interactive ? "" : opt.dump_path);
|
||||
if (opt.help) {
|
||||
print_usage();
|
||||
return 2;
|
||||
@ -1060,7 +1235,13 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
error = setup_dump(opt.dump_path);
|
||||
if (opt.interactive) {
|
||||
error = setup_dump_interactive();
|
||||
}
|
||||
else {
|
||||
error = setup_dump(opt.dump_path);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
perror("setup_dump");
|
||||
print_usage();
|
||||
@ -1101,6 +1282,21 @@ int main(int argc, char *argv[]) {
|
||||
lbp = lbuf;
|
||||
continue;
|
||||
}
|
||||
// Interrupt remote
|
||||
else if (opt.interactive &&
|
||||
c == 0x03) {
|
||||
mode = 0;
|
||||
fputc('+', ofp);
|
||||
sprintf(lbuf, "%s", "Ctrl-C");
|
||||
command(lbuf, rbuf, sizeof(rbuf));
|
||||
sum = 0;
|
||||
for (p = rbuf; *p != '\0'; ++p) {
|
||||
sum += *p;
|
||||
}
|
||||
fprintf(ofp, "$%s#%02x", rbuf, sum);
|
||||
fflush(ofp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (mode == 1) {
|
||||
if (c == '#') {
|
||||
|
||||
Reference in New Issue
Block a user