Skip to content

Instantly share code, notes, and snippets.

@tekknolagi
Last active November 24, 2024 05:01
Show Gist options
  • Save tekknolagi/73e75306d6a04887af0f631c0e919991 to your computer and use it in GitHub Desktop.
Save tekknolagi/73e75306d6a04887af0f631c0e919991 to your computer and use it in GitHub Desktop.
// Compile this with -rdynamic and your emulator .so with -fPIC -fpie -shared
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "dcheck.h"
static char logfile_name[] = "/tmp/gbtracer.log.XXXXXX";
static int logfile_fd = 0;
static FILE* logfile_fp = NULL;
void gbtracer_open() {
fprintf(stderr, "gbtracer running...\n");
logfile_fd = mkstemp(logfile_name);
DCHECK(logfile_fd != -1, "gbtracer_open could not make a logfile");
logfile_fp = fdopen(logfile_fd, "w");
DCHECK(logfile_fp != NULL, "gbtracer_open could not open logfile");
}
void gbtracer_close() {
DCHECK(logfile_fd != -1, "gbtracer_close called before gbtracer_open");
DCHECK(logfile_fp != NULL, "gbtracer_close called before gbtracer_open");
fclose(logfile_fp);
close(logfile_fd);
fprintf(stderr, "gbtracer: %s\n", logfile_name);
}
static uint8_t gbtracer_h = 0;
static uint8_t gbtracer_l = 0;
static uint8_t gbtracer_a = 0;
static uint8_t gbtracer_b = 0;
static uint8_t gbtracer_c = 0;
static uint8_t gbtracer_d = 0;
static uint8_t gbtracer_e = 0;
static uint8_t gbtracer_f = 0;
static uint16_t gbtracer_sp = 0;
static uint16_t gbtracer_pc = 0;
static uint8_t* gbtracer_memory = NULL;
static size_t gbtracer_memory_size = 0;
#define WRITER(type, name) \
void gbtracer_set_##name(type v) { gbtracer_##name = v; }
WRITER(uint8_t, h);
WRITER(uint8_t, l);
WRITER(uint8_t, a);
WRITER(uint8_t, b);
WRITER(uint8_t, c);
WRITER(uint8_t, d);
WRITER(uint8_t, e);
WRITER(uint8_t, f);
WRITER(uint16_t, sp);
#undef WRITER
void gbtracer_set_memory(uint8_t* memory, size_t size) {
gbtracer_memory = memory;
gbtracer_memory_size = size;
}
static void flush() {
fprintf(logfile_fp, "A: %02X ", gbtracer_a);
fprintf(logfile_fp, "F: %02X ", gbtracer_f);
fprintf(logfile_fp, "B: %02X ", gbtracer_b);
fprintf(logfile_fp, "C: %02X ", gbtracer_c);
fprintf(logfile_fp, "D: %02X ", gbtracer_d);
fprintf(logfile_fp, "E: %02X ", gbtracer_e);
fprintf(logfile_fp, "H: %02X ", gbtracer_h);
fprintf(logfile_fp, "L: %02X ", gbtracer_l);
fprintf(logfile_fp, "SP: %04X ", gbtracer_sp);
uint16_t pc = gbtracer_pc;
fprintf(logfile_fp, "PC: 00:%04X ", pc);
fprintf(logfile_fp, "(");
for (int i = 0; i < 4; i++) {
fprintf(logfile_fp, "%02X%s", gbtracer_memory[pc + i], i < 3 ? " " : "");
}
fprintf(logfile_fp, ")");
fprintf(logfile_fp, "\n");
}
void gbtracer_set_pc(uint16_t pc) {
gbtracer_pc = pc;
flush();
}
void gbtracer_sleep(int64_t) {
// Don't sleep in trace mode
}
int main(int argc, char** argv) {
if (argc < 2) {
printf("Usage: %s <program.so> [args...]\n", argv[0]);
return 1;
}
char* program = argv[1];
int new_argc = argc - 1;
char** new_argv = argv + 1;
void* handle = dlopen(program, RTLD_NOW);
if (!handle) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
return 1;
}
int (*entry)(int, char**) = dlsym(handle, "main");
if (!entry) {
fprintf(stderr, "dlsym failed: %s\n", dlerror());
return 1;
}
int result = entry(new_argc, new_argv);
int dlclose_result = dlclose(handle);
if (dlclose_result != 0) {
fprintf(stderr, "dlclose failed: %s\n", dlerror());
return 1;
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment