From d1df17ffb75e84a913d35522c33360ca74d247b3 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Fri, 27 Dec 2019 08:45:49 +0000 Subject: [PATCH] eclair: fix register GDB response for descheduled threads Change-Id: I0001d094b624bc03f2b178ec28a4cab51e2acaf0 --- arch/arm64/kernel/syscall.c | 2 +- executer/user/arch/arm64/arch-eclair.c | 67 +++++++++++++++++++++++-- executer/user/arch/x86_64/arch-eclair.c | 15 ++++-- executer/user/eclair.c | 8 +-- executer/user/eclair.h | 10 ++++ 5 files changed, 89 insertions(+), 13 deletions(-) diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 1d189cef..c7403cd4 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -44,7 +44,7 @@ uintptr_t debug_constants[] = { offsetof(struct cpu_local_var, runq), offsetof(struct cpu_local_var, status), offsetof(struct cpu_local_var, idle), - offsetof(struct thread, ctx) + offsetof(struct thread_info, cpu_context), + offsetof(struct thread, ctx), offsetof(struct thread, sched_list), offsetof(struct thread, proc), offsetof(struct thread, status), diff --git a/executer/user/arch/arm64/arch-eclair.c b/executer/user/arch/arm64/arch-eclair.c index ca2e583e..93be202e 100644 --- a/executer/user/arch/arm64/arch-eclair.c +++ b/executer/user/arch/arm64/arch-eclair.c @@ -2,16 +2,19 @@ #include #include #include +#include +#include int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) { int i, ret, total = 0; + uint32_t pstate; const unsigned long *regs[] = {&kregs->x19, &kregs->x20, &kregs->x21, &kregs->x22, &kregs->x23, &kregs->x24, &kregs->x25, &kregs->x26, &kregs->x27, &kregs->x28}; - for (i = 0; i < 18; i++) /* x0-x18 */{ + for (i = 0; i <= 18; i++) /* x0-x18 */{ ret = snprintf(rbp, rbp_size, "xxxxxxxxxxxxxxxx"); if (ret < 0) { return ret; @@ -31,7 +34,18 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) rbp_size -= ret; } - for (i = 0; i < 2; i++) { /* x29-x30 */ + // X29 FP + ret = print_bin(rbp, rbp_size, (void *)&kregs->fp, sizeof(kregs->fp)); + if (ret < 0) { + return ret; + } + total += ret; + dprintf("%s: FP: %s, kregs->fp: 0x%lx\n", __func__, rbp, kregs->fp); + rbp += ret; + rbp_size -= ret; + + // x30 LR + for (i = 0; i < 1; i++) { ret = snprintf(rbp, rbp_size, "xxxxxxxxxxxxxxxx"); if (ret < 0) { return ret; @@ -41,12 +55,38 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) rbp_size -= ret; } - ret += print_bin(rbp, rbp_size, (void *)&kregs->sp, sizeof(kregs->sp)); + // X31 SP + ret = print_bin(rbp, rbp_size, (void *)&kregs->sp, sizeof(kregs->sp)); if (ret < 0) { return ret; } total += ret; + dprintf("%s: SP: %s, kregs->sp: 0x%lx\n", __func__, rbp, kregs->sp); + rbp += ret; + rbp_size -= ret; + // X32 PC + ret = print_bin(rbp, rbp_size, (void *)&kregs->pc, sizeof(kregs->pc)); + if (ret < 0) { + return ret; + } + total += ret; + dprintf("%s: PC: %s, kregs->pc: 0x%lx\n", __func__, rbp, kregs->pc); + rbp += ret; + rbp_size -= ret; + + // PSTATE +#define PSR_MODE_EL1h 0x00000005 + pstate = PSR_MODE_EL1h; + ret = print_bin(rbp, rbp_size, (void *)&pstate, sizeof(pstate)); + if (ret < 0) { + return ret; + } + total += ret; + rbp += ret; + rbp_size -= ret; + + dprintf("%s: total: %d\n", __func__, total); return total; } @@ -70,3 +110,24 @@ int arch_setup_constants(void) /* Nothing here */ return 0; } + +/* + * NOTE: in ARM64, ctx is a pointer to thread_info, in which + * cpu_context is the real member we are looking for thus an extra + * indirection is needed. + */ +int arch_read_kregs(unsigned long ctx, struct arch_kregs *kregs) +{ + int error; + error = read_mem(ctx, &ctx, sizeof(ctx)); + if (error) { + return error; + } + + /* + * TODO: the 16 below is offsetof(struct thread_info, cpu_context) + * add this to debug_constants or move the whole thing over DWARF + * based inspection... + */ + return read_mem(ctx + 16, kregs, sizeof(*kregs)); +} diff --git a/executer/user/arch/x86_64/arch-eclair.c b/executer/user/arch/x86_64/arch-eclair.c index da3a7cf8..f8620a7f 100644 --- a/executer/user/arch/x86_64/arch-eclair.c +++ b/executer/user/arch/x86_64/arch-eclair.c @@ -25,7 +25,7 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) total += ret; rbp_size -= ret; - ret += print_bin(rbp, rbp_size, (void *)&kregs->rbx, sizeof(uint64_t)); /* rbx */ + ret = print_bin(rbp, rbp_size, (void *)&kregs->rbx, sizeof(uint64_t)); /* rbx */ if (ret < 0) { return ret; } @@ -44,7 +44,7 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) } for (i = 0; i < sizeof(regs_1)/sizeof(regs_1[0]); i++) { /* rsi, rdi, rbp, rsp */ - ret = print_bin(rbp, rbp_size, regs_1 + i, sizeof(regs_1[0])); + ret = print_bin(rbp, rbp_size, (void *)regs_1[i], sizeof(regs_1[0])); if (ret < 0) { return ret; } @@ -64,7 +64,7 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) } for (i = 0; i < sizeof(regs_2)/sizeof(regs_2[0]); i++) { /* r12-r15 */ - ret = print_bin(rbp, rbp_size, regs_2 + i, sizeof(regs_2[0])); + ret = print_bin(rbp, rbp_size, (void *)regs_2[i], sizeof(regs_2[0])); if (ret < 0) { return ret; } @@ -73,7 +73,7 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) rbp_size -= ret; } - ret += print_bin(rbp, rbp_size, (void *)&ihk_mc_switch_context, sizeof(uint64_t)); /* rip */ + ret = print_bin(rbp, rbp_size, (void *)&ihk_mc_switch_context, sizeof(uint64_t)); /* rip */ if (ret < 0) { return ret; } @@ -81,7 +81,7 @@ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs) total += ret; rbp_size -= ret; - ret += print_bin(rbp, rbp_size, (void *)&kregs->rflags, sizeof(uint32_t)); /* rflags */ + ret = print_bin(rbp, rbp_size, (void *)&kregs->rflags, sizeof(uint32_t)); /* rflags */ if (ret < 0) { return ret; } @@ -131,6 +131,11 @@ int arch_setup_constants(void) } printf("x86 linux_page_offset: 0x%lx\n", linux_page_offset); + return 0; } +int arch_read_kregs(unsigned long ctx, struct arch_kregs *kregs) +{ + return read_mem(ctx, kregs, sizeof(*kregs)); +} diff --git a/executer/user/eclair.c b/executer/user/eclair.c index 35a06237..69ece3c2 100644 --- a/executer/user/eclair.c +++ b/executer/user/eclair.c @@ -731,14 +731,14 @@ static void command(const char *cmd, char *res, size_t res_size) { int error; struct arch_kregs kregs; - error = read_mem(curr_thread->process+K(CTX_OFFSET), - &kregs, sizeof(kregs)); + error = arch_read_kregs(curr_thread->process+K(CTX_OFFSET), + &kregs); if (error) { - perror("read_mem"); + perror("arch_read_kregs"); break; } - print_kregs(rbp, res_size, &kregs); + rbp += print_kregs(rbp, res_size, &kregs); } else { int error; diff --git a/executer/user/eclair.h b/executer/user/eclair.h index 524c8c97..9542253c 100644 --- a/executer/user/eclair.h +++ b/executer/user/eclair.h @@ -9,16 +9,26 @@ #include /* common */ +int read_mem(uintptr_t va, void *buf, size_t size); +#define NOSYMBOL ((uintptr_t)-1) uintptr_t lookup_symbol(char *name); int read_symbol_64(char *name, void *buf); ssize_t print_bin(char *buf, size_t buf_size, void *data, size_t size); /* arch depend */ int print_kregs(char *rbp, size_t rbp_size, const struct arch_kregs *kregs); +int arch_read_kregs(unsigned long ctx, struct arch_kregs *kregs); #define NOPHYS ((uintptr_t)-1) uintptr_t virt_to_phys(uintptr_t va); int arch_setup_constants(void); +//#define DEBUG +#ifdef DEBUG +#define dprintf printf +#else +#define dprintf(...) do {} while (0) +#endif + #endif /* HEADER_USER_COMMON_ECLAIR_H */