Native iPhone port of Factorio 2.0.77
Run the original macOS ARM64 game code on iOS: - tools/retarget.py: header-only Mach-O retargeting to an iOS dylib - platform/native: UIKit host and macOS API shims (AppKit for SDL's Cocoa backend, CoreGraphics displays, CoreAudio device, Metal device properties, Wuffs PNG decoding, Steam and peripheral stubs) - touch, overlay, iOS keyboard and hardware keyboard input - tools/build_native.py: build, sign, install, data copy, launch - docs: build guide, controls, architecture Also includes the earlier static-translation research (ARM64 -> WASM -> native) under docs/research, runtime/, tests/ and tools/. No game files are included; the build reads them from a local install.
This commit is contained in:
commit
51d085e865
89 files changed
+7999
No files matched your search
@@ -0,0 +1,93 @@
|
||||
// Crash diagnostics: interposes sigaction so Factorio's own crash handler runs after ours.
|
||||
// Ours logs the faulting PC, LR, fault address and the frame-pointer chain as image+offset,
|
||||
// which tools/symbolize_native.py resolves against the original factorio.dSYM on the Mac.
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include "fx.h"
|
||||
|
||||
static struct sigaction fx_previous[NSIG];
|
||||
static int fx_reporting;
|
||||
|
||||
static void fx_describe(const char *label, uintptr_t address) {
|
||||
Dl_info info;
|
||||
if (address && dladdr((void *)address, &info) && info.dli_fname) {
|
||||
const char *base = strrchr(info.dli_fname, '/');
|
||||
fx_log("[fx-crash] %s %#lx %s+%#lx %s", label, (unsigned long)address, base ? base + 1 : info.dli_fname,
|
||||
(unsigned long)(address - (uintptr_t)info.dli_fbase), info.dli_sname ? info.dli_sname : "");
|
||||
} else {
|
||||
fx_log("[fx-crash] %s %#lx", label, (unsigned long)address);
|
||||
}
|
||||
}
|
||||
|
||||
static void fx_crash_handler(int sig, siginfo_t *si, void *context) {
|
||||
if (!fx_reporting++) {
|
||||
ucontext_t *uc = context;
|
||||
struct __darwin_arm_thread_state64 *ts = &uc->uc_mcontext->__ss;
|
||||
uintptr_t pc = (uintptr_t)__darwin_arm_thread_state64_get_pc(*ts);
|
||||
uintptr_t lr = (uintptr_t)__darwin_arm_thread_state64_get_lr(*ts);
|
||||
uintptr_t fp = (uintptr_t)__darwin_arm_thread_state64_get_fp(*ts);
|
||||
uintptr_t sp = (uintptr_t)__darwin_arm_thread_state64_get_sp(*ts);
|
||||
fx_log("[fx-crash] signal %d code %d fault address %p thread %p%s", sig, si->si_code, si->si_addr,
|
||||
(void *)pthread_self(), pthread_main_np() ? " (main)" : "");
|
||||
fx_describe("pc", pc);
|
||||
fx_describe("lr", lr);
|
||||
for (int r = 0; r < 29; r++) fx_log("[fx-crash] x%d = %#llx", r, ts->__x[r]);
|
||||
fx_log("[fx-crash] sp = %#lx fp = %#lx", (unsigned long)sp, (unsigned long)fp);
|
||||
// Frame-pointer walk, bounded to plausible stack addresses above sp.
|
||||
for (int depth = 0; depth < 64 && fp && (fp & 7) == 0 && fp >= sp && fp - sp < (512u << 20); depth++) {
|
||||
uintptr_t next = ((uintptr_t *)fp)[0], ret = ((uintptr_t *)fp)[1];
|
||||
char label[16];
|
||||
snprintf(label, sizeof label, "#%d", depth);
|
||||
fx_describe(label, ret);
|
||||
if (next <= fp) break;
|
||||
fp = next;
|
||||
}
|
||||
}
|
||||
struct sigaction *prev = &fx_previous[sig];
|
||||
if (prev->sa_flags & SA_SIGINFO) {
|
||||
if (prev->sa_sigaction) { prev->sa_sigaction(sig, si, context); return; }
|
||||
} else if (prev->sa_handler != SIG_DFL && prev->sa_handler != SIG_IGN) {
|
||||
prev->sa_handler(sig);
|
||||
return;
|
||||
}
|
||||
signal(sig, SIG_DFL);
|
||||
raise(sig);
|
||||
}
|
||||
|
||||
static int fx_is_fatal(int sig) { return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGFPE || sig == SIGTRAP || sig == SIGABRT; }
|
||||
|
||||
static int fx_sigaction(int sig, const struct sigaction *act, struct sigaction *old) {
|
||||
if (sig <= 0 || sig >= NSIG || !fx_is_fatal(sig) || !act) return sigaction(sig, act, old);
|
||||
if (old) *old = fx_previous[sig];
|
||||
fx_previous[sig] = *act;
|
||||
struct sigaction ours = *act;
|
||||
ours.sa_sigaction = fx_crash_handler;
|
||||
ours.sa_flags |= SA_SIGINFO;
|
||||
return sigaction(sig, &ours, NULL);
|
||||
}
|
||||
|
||||
static void (*fx_signal(int sig, void (*handler)(int)))(int) {
|
||||
if (sig <= 0 || sig >= NSIG || !fx_is_fatal(sig)) return signal(sig, handler);
|
||||
struct sigaction act = {0}, old;
|
||||
act.sa_handler = handler;
|
||||
fx_sigaction(sig, &act, &old);
|
||||
return old.sa_handler;
|
||||
}
|
||||
|
||||
FX_EXPORT void fx_install_crash_reporter(void) {
|
||||
for (int sig = 1; sig < NSIG; sig++) {
|
||||
if (!fx_is_fatal(sig)) continue;
|
||||
struct sigaction act = {0};
|
||||
act.sa_handler = SIG_DFL;
|
||||
fx_sigaction(sig, &act, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((used, section("__DATA,__interpose"))) static const struct { const void *replacement, *original; }
|
||||
fx_interpose[] = {
|
||||
{(const void *)fx_sigaction, (const void *)sigaction},
|
||||
{(const void *)fx_signal, (const void *)signal},
|
||||
};
|
||||
Reference in new issue
Block a user