Repository navigation
feat: find a lifted program's guest images, load its modules and switch its fibers - #14
Open
oberonlift wants to merge 6 commits into
Open
oberonlift wants to merge 6 commits into
oberonlift wants to merge 6 commits into
Conversation
This was referenced Nov 1, 2026
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 1, 2026 19:35
dd078f7 to
25277c9
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 1, 2026 19:35
3a49e0b to
466231b
Compare
This was referenced Nov 1, 2026
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 1, 2026 22:07
466231b to
90d3f01
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
2 times, most recently
from
November 2, 2026 17:02
61186a9 to
319ad33
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 2, 2026 17:02
90d3f01 to
006f153
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 2, 2026 18:30
319ad33 to
65a7b9f
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
2 times, most recently
from
November 2, 2026 22:07
3e0a605 to
9d12953
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 2, 2026 22:07
65a7b9f to
8337a07
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 3, 2026 16:34
9d12953 to
99d78d6
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 3, 2026 16:34
8337a07 to
6623bb0
Compare
12 tasks done
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 3, 2026 17:20
99d78d6 to
299adba
Compare
Owner
Author
Review findings (unverified)Code review of
|
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 4, 2026 15:40
6623bb0 to
b6bc70b
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 4, 2026 15:40
299adba to
48f4a7b
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 4, 2026 16:20
b6bc70b to
c1e6f6a
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 4, 2026 16:20
48f4a7b to
3733dc8
Compare
12 tasks done
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 4, 2026 17:17
3733dc8 to
3d98f91
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
2 times, most recently
from
November 4, 2026 20:18
2a44260 to
c0cdf08
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
3 times, most recently
from
November 5, 2026 15:34
edd1439 to
5f9283d
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 5, 2026 19:28
5f9283d to
be43071
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
2 times, most recently
from
November 6, 2026 00:18
44fc211 to
bafaa1c
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
2 times, most recently
from
November 6, 2026 15:35
45266c2 to
cf0715b
Compare
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 6, 2026 15:35
bafaa1c to
744c658
Compare
A lifted program carries every guest module it was built with, so dlopen resolves the path as the native loader would and takes the lifted image whose path ends with it, or with it and .guest.prx appended, and runs the module's lifecycle table through guest calls. Symbols come from that image's export table; dlopen(NULL) and the default scope search every image. A name that is not lifted still goes to the native loader. The lifecycle state machine is shared between the native and lifted paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mAddr A lifted build's guest images are not host shared objects, so the dladdr1 that sceKernelGetModuleInfoFromAddr asked first never found them, and sceKernelGetModuleInfoForUnwind, which asks it for a guest image's unwind tables, threw when a title's unwinder looked up its own code. Lifted builds now search the lifted program's images directly, as their dl_iterate_phdr already does, key the module id by the image's base and treat no lifted image as a system one. The debt notes record the module calls that still reach images through host link maps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A lifted guest's executable and modules are part of the lifted program: ps5lift's runtime maps them, and the host's dynamic loader never sees them. Module queries still asked dladdr1 and link_map about guest addresses, which cannot succeed, so sceKernelGetModuleList and module info by handle aborted, and thread_atexit could not reference an image. In lifted builds an image is found through dl_iterate_phdr, which walks the runtime's images, and identified by the address of its first loadable segment, the key sceKernelGetModuleInfoFromAddr already used. A module dlopen loads from the lifted program records that identity, so its module ID matches its load handle. Lifted images are never system images and are never unloaded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A lifted build gives every fiber its own host stack, switches host stacks with an aarch64 version of the switch, and saves and restores the guest registers around each switch through GuestCpu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In a lifted build the frames on a fiber's host stack keep the guest state of the thread that started the fiber. Resumed on another thread, the fiber ran on the first thread's state while that thread ran on it too: a fiber that the second thread handed 5 read 7, the value it was last given on the first thread, and the program went on. A fiber now records the thread that starts it, and resuming a suspended fiber on any other thread throws until each fiber has a guest state of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With fibers switched for a lifted guest every library builds on aarch64, so the workflow builds the libs target, and the 2,187 tests whose programs link AnyPS5's libraries and pass on lavapipe in well under the 30 s limit on the runner join lifted_tests.txt, which now names 2,288. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oberonlift
force-pushed
the
lifted-libkernel
branch
from
November 6, 2026 17:39
744c658 to
2190ab5
Compare
oberonlift
force-pushed
the
lifted-modules-fibers
branch
from
November 6, 2026 17:39
cf0715b to
1acbba4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Open on AnyPS5 as boykopovar#15804; this copy follows it.
ps5lift is a static recompiler for PS5 executables: it lifts a game's x86-64 code to LLVM IR and compiles it ahead of time to aarch64, which runs on Linux against AnyPS5's own libraries with no interpreter or JIT. It runs AnyPS5's PS5-style test programs and a homebrew media player to its home screen; commercial games are not playable yet. Branch
ps5lift-previewmerges all of its PRs (how to try it); native Apple Silicon support is coming along fast. It is a separate approach from the ARM64 compiler in boykopovar#5021; boykopovar#1835 has an introduction.This is 8 of 8 PRs that let AnyPS5's libraries run a lifted program; the lifter itself follows them.
x86-64: behaviour unchanged. The native module lifecycle runs through the state machine it now shares with lifted modules.
What
ps5lift's runtime maps a lifted program's executable and modules; the host's dynamic loader never sees them.
dlopenresolves the path as the native loader would and takes the lifted image whose path ends with it, or with it and.guest.prxappended, so a system library path still reaches AnyPS5's library when the title ships a module of the same name. It runs the module's lifecycle table through guest calls. Symbols come from that image's export table, anddlopen(NULL), whose handle is the executable's module ID, and the default scope search every image. A name that is not lifted still goes to the native loader; the lifecycle state machine is shared between the two paths.sceKernelGetModuleInfoFromAddr,sceKernelGetModuleInfoForUnwind,sceKernelGetModuleList, module info by handle,thread_atexit) find an image throughdl_iterate_phdrand identify it by the address of its first loadable segment, so a module's ID matches its load handle. Lifted images are never system images and are never unloaded.GuestCpu. Resuming a suspended fiber on a thread other than the one that started it throws, until each fiber has a guest state of its own.ps5lift/tests/lifted_tests.txtnames the 2,288 tests that pass with this PR, up from 101.boykopovar#5021 also changes some of the same files:
DynamicLoader.cpp,ModuleInfo.cpp,Rtld.cpp.Tested
Compiled for x86-64 Linux before and after this PR (GCC 13, same flags): 147 of the 148 objects it reaches are byte-identical;
DynamicLoader.cppdiffers by the lifecycle it now shares with lifted modules.On a DGX Spark (aarch64 Linux, NVIDIA GB10, LLVM 18), with all eight PRs and ps5lift on top: every library builds for a lifted program, 2,288 of AnyPS5's own tests pass in that build on lavapipe, and ps5lift's 69 tests pass, among them its libc, exceptions, kernel, fiber and module-loading fixtures and upstream's libc test programs.
The conventions check passes on this branch.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code