Files
SashaGoncharov19 51d085e865 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.
2026-10-23 15:27:58 +04:00

94 lines
4.0 KiB
C

// 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},
};