Skip to content

Ruffle, VLC and XPSemu read their GOT at a fixed 0x400000 base from app0/imports.txt and fault once all imports load #4013

Closed

Description

@babyhuey

Three catalog titles ship app0/imports.txt and contain the same start-up code: Ruffle (PPSA68091), VLC (PPSA85300) and XPSemu (PPSA97358). Each line of the file is <offset> <name>, an import's GOT slot as an offset from the start of the image. For example, the first line of Ruffle's is 00000000024d5370 _init_env.

The title reads the file with fscanf(file, "%lx %127s", &offset, name) and then reads the slot at offset + 0x400000. So it assumes the executable (ET_SCE_DYNEXEC, first PT_LOAD at vaddr 0) is loaded at 0x400000. In Ruffle, at vaddr 0x1d4b:

1d36: call  [fscanf]                 ; rdi=FILE*, rsi="%lx %127s", rdx=&offset, rcx=name
1d42: cmp   eax, 2
1d4b: mov   rax, [rbp-0x30]          ; offset
1d4f: cmp   QWORD PTR [rax+0x400000], 0

The relinked image is mapped elsewhere, so the first read (0x24d5370 + 0x400000) faults.

On main 0a8b1d3, Ruffle reaches this point after #3725 (sinhf), #3580 (pause) and #3494 (pthread_attr_getscope) are merged. With those, every import loads and it logs can't write /data/ruffle/ruffle.log, then:

  • Linux: SIGSEGV at app.elf vaddr 0x1d4f, rax = 0x24d5370 (gdb).
  • Windows 11 (MinGW GCC 15.2): FATAL: unhandled exception 0xc0000005 ... app.exe+0x11d4f, read of 0x00000000028d5370.

VLC and XPSemu have the same %lx %127s scan and an imports.txt starting with _init_env. Both still stop on imports on main (VLC: getlogin_r, #3606; XPSemu: execv, #3544), so they would reach the same fault after those.

Possible directions: load the main executable at 0x400000 when that range is free, or reserve 0x400000 + image size and mirror the image's GOT there. I have not checked which fits the loader better.

Activity

  1. babyhuey commented on Oct 12, 2026

    @babyhuey
    ContributorAuthor

    Update: this is now Ruffle's stop on plain main. With #3725, #3580 and #3494 merged, main 8fa5cc4 (Linux, catalog run without extra PRs) loads every import, logs jailbreak ok: already root ... (can't write /data/ruffle/ruffle.log) and exits with SIGSEGV. gdb shows the same read as above:

    rip 0x555555555d4f  (app.elf + 0x1d4f)
    rax 0x24d5370
    => cmpq $0x0,0x400000(%rax)
    

    app.elf's first segment is mapped at 0x555555554000, so 0x24d5370 + 0x400000 is unmapped.

  2. Recapi commented on Oct 12, 2026

    @Recapi
    Contributor

    I'm taking the Linux side of this: a relinker option that places the executable's lowest load page at a requested address on Linux (--linux-fixed-base 0x400000), the counterpart of #4140's --windows-fixed-base. Guest modules keep their normal placement. I'll post it here with Ruffle (PPSA68091) before and after, so nobody duplicates it.

  3. Recapi commented on Oct 12, 2026

    @Recapi
    Contributor

    Linux side is #4593: --linux-fixed-base 0x400000 writes the executable as ET_EXEC with every address rebased. With it, Ruffle (PPSA68091) gets past the 0x400000(%rax) read on Linux and renders, then stops at an unrelated AGC limit (CB_COLOR_CONTROL 0x00cc0050, mode FMASK decompress). It also fixes libkernel's default-scope dlsym, which missed symbols of a non-PIE main program.

  4. Recapi commented on Oct 12, 2026

    @Recapi
    Contributor

    With #4593, Ruffle's game library UI runs on Linux. It initializes the display, input and audio, and presented 2,400 frames in 60 s until the timeout. Opening Favorites starts the Flash player, which stops at an AGC limit: CB_COLOR_CONTROL 0x00cc0050, mode FMASK decompress. Details are in the PR.

  5. Recapi commented on Oct 12, 2026

    @Recapi
    Contributor

    Ruffle's next stop after #4593, the player's first FMASK decompress over a 4x MSAA target with DCC, is tracked in #4685, with the register state and a quality=Low workaround.

  6. dantdmdarealguy commented on Oct 14, 2026

    @dantdmdarealguy
    Contributor

    Windows side, confirmed on main 30f961266: Ruffle (PPSA68091, catalog release) runs when it's relinked with #4140's --windows-fixed-base 0x400000.

    Windows 11 Pro, i9-14900K, RTX 5080 (driver 32.0.16.1714), WinLibs GCC 15.2.0, Release. eboot.bin and sce_module/libc.prx were unwrapped, and eboot.bin and imports.txt were kept in app0. Each run lasted 60 s.

    • relinker --windows --registry eboot.elf app.exe: exits 0xC0000005 after 3.8 s, at rip = app.exe+0x11d4f, reading 0x28d5370. That is the fault in this issue.
    • The same command plus --windows-fixed-base 0x400000: runs the full 60 s to the library screen ("No games yet") at about 62 FPS, and exits 0 on WM_CLOSE.

    Ruffle with --windows-fixed-base 0x400000, 57 s

    So no Windows code change is needed, only the option. The Linux side is #4593.

  7. adriadam10 commented on Oct 14, 2026

    @adriadam10
    Collaborator

    #4593 adds --linux-fixed-base (Linux side, covered by linux_fixed_base); Ruffle and XPSemu get past the GOT read on Linux, the titles' later stops are tracked elsewhere, so this issue stays open.

  8. babyhuey commented on Oct 22, 2026

    @babyhuey
    ContributorAuthor

    Linux update: since #8973 made 0x400000 the default Linux base, all three titles get past the GOT read with a plain relink, with no --linux-fixed-base. On main d6eafa54 in my catalog sweep (headless, SDL offscreen driver):

    Title main 94fbb8cea (PIE base) main d6eafa54
    Ruffle (PPSA68091) SIGSEGV at 0.2 s DisplayWindow Vulkan check, like the other headless UI titles
    VLC (PPSA85300) SIGSEGV at 0.1 s same
    XPSemu (PPSA97358) SIGSEGV runs about 3 s into its GPU work (compute dispatches), its later stop in #5437

    On Windows the default from #4237 is 0x140000000, and VLC still needed --windows-fixed-base 0x400000 in my last Windows runs. Should this stay open for the Windows default, or is --windows-fixed-base the intended answer there?

    AI-assisted: yes

  9. babyhuey commented on Oct 22, 2026

    @babyhuey
    ContributorAuthor

    The Windows half, on main 7e2ba73e4 (Windows 11, RTX 3080, WinLibs GCC 15.2, Release, 60 s each). The relink is the harness's default command, with and without --windows-fixed-base 0x400000:

    Title Default relink (ImageBase 0x140000000) --windows-fixed-base 0x400000
    Ruffle (PPSA68091) 0xC0000005 at 2.6 s, rip app.exe+0x11d4f still running, 98.85 FPS
    VLC (PPSA85300) 0xC0000005 at 2.1 s, rip app.exe+0x107004 still running, 119.88 FPS
    XPSemu (PPSA97358) 0xC0000005 at 2.1 s, rip app.exe+0xc88d9f still running, 109.78 FPS

    So on Windows these titles still need the option, as USAGE.md says. The default comes from WindowsPeFormat.hpp (ImageBase = 0x140000000), which #8973 didn't touch. Would 0x400000 work as the Windows default too, the way #8973 did it for Linux, or does something on Windows rule that address out?

    AI-assisted: yes

  10. LeandroLP23 commented on Oct 26, 2026

    @LeandroLP23
    Contributor

    The Windows half now works with a plain relink too, since #9332 made 0x400000 the Windows default (merged 10-24), matching what babyhuey saw on Linux after #8973.

    Windows 11 10.0.26300, AMD Radeon 860M, WinLibs GCC 15.2.0 r7, Release, main 9656d366be. tools/title_run.py (#7264), with the three titles' fixed_base entries removed from its titles.json, so the relinker ran with --registry and no --windows-fixed-base; 40 s each:

    Title ImageBase of the output Result
    Ruffle (PPSA68091) 0x3f0000, no DYNAMIC_BASE rendering, 94.7 fps
    VLC (PPSA85300) 0x3f0000, no DYNAMIC_BASE rendering, 35.4 fps
    XPSemu (PPSA97358) 0x3f0000, no DYNAMIC_BASE rendering, 22.7 fps

    The 0x10000 below 0x400000 is the PE header, so the guest image's vaddr 0 is at 0x400000, the base the titles' imports.txt reads assume (the old fault was at app.exe+0x11d4f for vaddr 0x1d4f). No 0xC0000005 or FATAL in any log. With both Linux (#8973) and Windows (#9332) defaulting to 0x400000, this issue looks resolved; the titles' later stops, if any, are tracked separately.

    AI-assisted: yes (Claude Code)

  11. oneandonlydean commented on Oct 27, 2026

    @oneandonlydean
    Collaborator

    Fixed on both hosts by the 0x400000 default: Linux in #8973 (44661db), Windows in #9332 (c4446bb). babyhuey confirmed the Linux half and LeandroLP23 the Windows half on current main with a plain relink and no fixed-base option. Closing as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions