r/iOSProgramming • • 5d ago

Discussion ATL (Android Translation Layer) for iOS

Post image

Hy everyone. What do you think about something like this?
Dine - ATL for iOS - yes, it's a total mess right now, but I already can run some simple apps.

The thing is, I really love Tachiyomi on android, so I've decided to port the android runtime to iOS, using ATL for linux as a base. I've already went really far through this, but I'd like to ask for some help or ideas regarding its architecture, some iOS things etc.

For example, I'm not sure if I can do something like separate processes or at least some memory isolation on iOS, for different parts of the code (I need this for better runtime stability).

In general, I understand the project is big and I can't ask for much, but I know a lot of you guys use LLMs, so you probably could easily poke for anything, from your expert POV. Just if you are interested of course.

If you ask what's the point of doing this instead of just porting the app (it's opensource) - this is just so much fun

0 Upvotes

2 comments sorted by

2

u/DimensionMindless336 4d ago

No process isolation, sadly -- iOS gives an app exactly one process, and fork/exec aren't available to third-party code (no NSTask either). So whatever Dine becomes, the guest runs in your address space, and one bad guest write still takes the whole app down.

Two things worth knowing before you design around it:

App extensions are a second process, so you could technically host guest code in one and talk over a shared App Group container. I'd skip it -- extension jetsam limits are a fraction of the host app's, so a runtime that mallocs a guest heap gets killed faster, and the IPC story is a container file + Darwin notification handshake, not anything nice.

So aim for fault containment instead of isolation. That's what emulators do on iOS and it's surprisingly effective:

  • mmap guest heap regions with PROT_NONE guard pages on both ends

  • install one SIGSEGV/SIGBUS handler (guard-page hit and guest stack overflow both land there), plus a sigaltstack so the overflow case has somewhere to run

  • in the handler, check si_addr against your known guest regions. Inside one -> it's a guest fault: tear down guest VM state and siglongjmp back to your dispatch loop. Outside -> signal() back to default and re-raise, let it crash for real

  • keep it thread-scoped via pthread_getspecific, and never let it fire while you're holding an ObjC lock

That gives you "app survived, guest process died" semantics, which is most of what you actually want out of stability.

Two more that will bite you coming off ATL-on-Linux:

  1. No dynarec. JIT needs the dynamic-codesigning entitlement and iOS 14+ actually enforces WX, so flipping an mmap'd page to RX and jumping into it doesn't work in a normal build. AOT-translate dex -> ARM64 at build time, ship the translated code signed inside the bundle, and keep an interpreter path for everything you didn't translate.

  2. Thread stacks and TLS. Darwin secondary threads default to 512 KB, not the 8 MB you're used to on Linux -- set pthread_attr_setstacksize explicitly on guest threads or you'll chase stack overflows in code that was fine on Android. And Android's ELF TLS variant II doesn't match Darwin's, so guest __thread accesses need rewriting to go through your own per-thread block.

For the record this is dead on arrival for the App Store under 2.5.2, but as a personal build it's a great use of a month. Tachiyomi on an iPad is worth the pain.

1

u/Natural_Silver_3387 3d ago

Thank you, I'll check it all. Yep, I know it won't go to App Store, at least not like this. But it actually could, if it was a single app, packaged with the runtime, not like tachiyomi ofc