#include #include #include #include #include #include #include #include "include/memory.h" #define RAM_H (1ul<<32) #define PROT_RW (PROT_READ | PROT_WRITE) __attribute__((hot)) static int gpa_offset(const gpa_ctx* ctx, uintptr_t offs, uintptr_t* out) { if (offs < ctx->low) { *out = offs; return 0; } if (offs >= RAM_H) { const uint64_t x = ctx->low + (offs - RAM_H); if (x < ctx->fsize) { *out = x; return 0; } else { /* Out of bounds */ } } else { /* Not RAM */ } return -1; } static void clean_ctx(gpa_ctx* ctx) { memset(ctx, 0, sizeof(gpa_ctx)); ctx->fd = -1; } static int out_of_bounds(gpa_ctx* ctx, uintptr_t* offs, const size_t nmemb) { return gpa_offset(ctx, *offs, offs) || *offs + nmemb > ctx->fsize; } __attribute__((hot)) int gpa_read(gpa_ctx* ctx, uintptr_t offs, void* buf, const size_t nmemb) { if (out_of_bounds(ctx, &offs, nmemb)) { return -1; } memcpy(buf, ctx->pa + offs, nmemb); return 0; } int gpa_write(gpa_ctx* ctx, uintptr_t offs, const void* src, const size_t nmemb) { if (out_of_bounds(ctx, &offs, nmemb)) { return -1; } memcpy(ctx->pa + offs, src, nmemb); return 0; } /* Zero-copy host pointer to [offs, offs+nmemb) GPA, or NULL if that range is not * fully backed by the mapped image. Same split + bounds check as gpa_read. */ void* gpa_ptr(gpa_ctx* ctx, uintptr_t offs, const size_t nmemb) { if (out_of_bounds(ctx, &offs, nmemb)) { return NULL; } return (uint8_t*)ctx->pa + offs; } __attribute__((cold)) int gpa_open(gpa_ctx* ctx, const char* path, uintptr_t low) { struct stat st; if ((ctx->fd = open(path, O_RDWR)) < 0) { goto ret_; } if (fstat(ctx->fd, &st)) { goto close_; } if ((ctx->pa = mmap(NULL, st.st_size, PROT_RW, MAP_SHARED, ctx->fd, 0)) == MAP_FAILED) { close_: close(ctx->fd); ret_: clean_ctx(ctx); return -1; } ctx->fsize = st.st_size; ctx->low = low; return 0; } __attribute__((cold)) void gpa_close(gpa_ctx* ctx) { if (ctx->pa) { munmap(ctx->pa, ctx->fsize); } if (ctx->fd >= 0) { close(ctx->fd); } clean_ctx(ctx); }