Files
spoopyghosty0--frameport/native/a32translator/tests/programs/jitguest.c
T
UnicronNLandClaude Opus 5.5 4f042f7225 native/a32translator: AArch32 -> AArch64 user-mode translator (a32run)
Interpreter + JIT for ARM, Thumb-2, VFPv4 and NEON, ARM EABI syscall
translation, signals, threads and self-modifying code. Runs static bionic
programs on the Frame. Tests: A64 encoders vs llvm-mc, a differential
instruction fuzzer and program tests against qemu-arm. Not shipped; the
README lists the steps towards running 32-bit-only APKs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:41:43 +02:00

53 lines
1.9 KiB
C

/* JIT-in-the-guest: generates ARM and Thumb code at run time, runs it, rewrites it (cache maintenance via
* __builtin___clear_cache = the cacheflush syscall), runs it again. Also a signal interrupting a tight loop. */
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/time.h>
static volatile sig_atomic_t stop;
static void on_alarm(int s) { (void)s; stop = 1; }
typedef int (*fn_t)(int);
int main(void)
{
uint32_t *code = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
int total = 0;
for (int k = 0; k < 50; k++) {
/* ARM: add r0, r0, #k ; bx lr */
code[0] = 0xe2800000u | (uint32_t)k;
code[1] = 0xe12fff1eu;
__builtin___clear_cache((char *)code, (char *)(code + 2));
total += ((fn_t)code)(1000);
}
printf("arm %d\n", total);
/* the same buffer as Thumb code: movs r1, #k ; adds r0, r0, r1 ; bx lr */
uint16_t *t = (uint16_t *)(code + 16);
total = 0;
for (int k = 0; k < 50; k++) {
t[0] = (uint16_t)(0x2100 | k);
t[1] = 0x1840;
t[2] = 0x4770;
__builtin___clear_cache((char *)t, (char *)(t + 3));
total += ((fn_t)((uintptr_t)t | 1))(7);
}
printf("thumb %d\n", total);
/* rewrite through mprotect (RW, write, RX) like JIT engines with W^X */
mprotect(code, 4096, PROT_READ | PROT_WRITE);
code[0] = 0xe3a00063u; /* mov r0, #99 */
code[1] = 0xe12fff1eu;
mprotect(code, 4096, PROT_READ | PROT_EXEC);
printf("mprotect %d\n", ((fn_t)code)(0));
/* a signal must stop a loop that never makes a syscall */
signal(SIGALRM, on_alarm);
struct itimerval it = {{0, 0}, {0, 50000}};
setitimer(ITIMER_REAL, &it, NULL);
unsigned long spins = 0;
while (!stop) spins++;
printf("loop stopped %d\n", spins > 0);
return 0;
}