Disassembly, tracing
authorLauri Kasanen <cand@gmx.com>
Fri, 28 May 2021 09:32:57 +0000 (12:32 +0300)
committerLauri Kasanen <cand@gmx.com>
Fri, 28 May 2021 09:32:57 +0000 (12:32 +0300)
main.c

diff --git a/main.c b/main.c
index d3d1e97687b6009c1bef3e9efb51469b5d96021c..62a6fc7dc41a17c685e34b5dcf89127301156bf2 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,6 +16,7 @@
 
 #define _GNU_SOURCE
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
@@ -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, &regs) == -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;
 }