From e313d43cbab5b933027c6292f5c49c6cce0f9c4f Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Fri, 28 May 2021 12:32:57 +0300 Subject: [PATCH] Disassembly, tracing --- main.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index d3d1e97..62a6fc7 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ #define _GNU_SOURCE +#include #include #include #include @@ -37,6 +38,7 @@ #define PROGSTART 0x20000000 #define MSR_64 (1UL<<63) +#define MSR_FP (1UL<<13) #define MSR_LE (1UL<<0) enum { @@ -262,6 +264,43 @@ static void getfpregs(const int vcpu, struct kvm_fpu *fpregs) { } } +static void disassemble(const char binpath[], char *disasm, const unsigned len) { + + char buf[PATH_MAX]; + snprintf(buf, PATH_MAX, + "objdump -b binary -m powerpc --no-show-raw-insn -D %s", + binpath); + buf[PATH_MAX - 1] = '\0'; + + FILE *f = popen(buf, "r"); + if (!f) { + printf("Disassembly failed, trace won't have disas\n"); + return; + } + + while (fgets(buf, PATH_MAX, f)) { + if (buf[0] != ' ') + continue; + const char *ptr = strchr(buf, ':'); + if (!ptr) + continue; + nukenewline(buf); + + const unsigned addr = strtol(buf, NULL, 16) / 4 * 32; + if (addr / 32 + 1 >= len) + abort(); + + ptr++; + while (isspace(*ptr)) + ptr++; + + strncpy(&disasm[addr], ptr, 32); + disasm[addr + 31] = '\0'; + } + + pclose(f); +} + int main(int argc, char **argv) { const struct option longopts[] = { @@ -286,7 +325,8 @@ int main(int argc, char **argv) { char dumps[MAXDUMPS][PATH_MAX]; unsigned num_dumps = 0; uint8_t *ram, *progmem; - const char *binpath; + const char *binpath = NULL; + const char *disasm = NULL; // Yes, we're frugal if (posix_memalign((void **) &ram, 64 * 1024, RAMSIZE)) @@ -298,7 +338,7 @@ int main(int argc, char **argv) { regs.lr = -1; regs.pc = PROGSTART; - regs.msr = MSR_64 | MSR_LE; + regs.msr = MSR_64 | MSR_FP | MSR_LE; while (1) { const int c = getopt_long(argc, argv, opts, longopts, NULL); @@ -380,6 +420,14 @@ int main(int argc, char **argv) { abort(); fclose(binary); + + if (trace) { + const unsigned disaslen = binlen / 4 + 64; + disasm = calloc(disaslen, 32); + + disassemble(binpath, (char *) disasm, disaslen); + } + kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC); if (kvm < 0) { printf("Failed to open kvm, perhaps you lack permissions?\n"); @@ -438,13 +486,51 @@ int main(int argc, char **argv) { abort(); // Runtime + uint64_t pc = PROGSTART; + unsigned i; while (1) { if (ioctl(vcpu, KVM_RUN, NULL) == -1) abort(); - printf("Exited because %u\n", run->exit_reason); + + if (ioctl(vcpu, KVM_GET_REGS, ®s) == -1) + abort(); + //printf("PC %lx LR %lx\n", regs.pc, regs.lr); + + if (run->exit_reason == KVM_EXIT_DEBUG) { + if (trace) { + getfpregs(vcpu, &fpregs); + + fprintf(trace, "%lx: %s\n", pc, &disasm[(pc - PROGSTART) / 4 * 32]); + for (i = 0; i < 32; i++) { + if (i % 8 == 0) + fprintf(trace, "GPR: "); + fprintf(trace, "%08lx", regs.gpr[i]); + if (i % 8 == 7) + fprintf(trace, "\n"); + else + fprintf(trace, " "); + } + for (i = 0; i < 32; i++) { + if (i % 8 == 0) + fprintf(trace, "FPR: "); + fprintf(trace, "%08lx", fpregs.fpr[i]); + if (i % 8 == 7) + fprintf(trace, "\n"); + else + fprintf(trace, " "); + } + } + } else if (regs.pc < PROGSTART || regs.pc > PROGSTART + binlen) { + // Normal exit by blr + break; + } else { + printf("Unexpected exit because %u\n", run->exit_reason); + break; + } + + pc = regs.pc; } - unsigned i; for (i = 0; i < num_dumps; i++) { dump(dumps[i], ram); } @@ -453,5 +539,6 @@ int main(int argc, char **argv) { free(progmem); free(ram); free((char *) binpath); + free((char *) disasm); return 0; } -- 2.30.2