Skip to content

feat(libc): implement getprogname - #2218

Closed
MichalSy wants to merge 1 commit into
boykopovar:mainfrom
MichalSy:codex/guest-program-name
Closed

MichalSy wants to merge 1 commit into
boykopovar:mainfrom
MichalSy:codex/guest-program-name

Conversation

@MichalSy

@MichalSy MichalSy commented Oct 9, 2026

Copy link
Copy Markdown

What

Guest modules importing getprogname currently fail to resolve it, although libkernel already exports the guest __progname data. Add the missing libc-internal export and return that existing pointer, matching FreeBSD stable/11 getprogname. This is the getprogname portion of the fork's existing compatibility changes, isolated onto current upstream main.

The same implementation runs on Windows and Linux. It introduces no second name store or host process-name lookup. The regression checks the initial guest name, pointer replacement, changes through the returned storage, an empty name, and guest errno preservation.

Duplicate review covered all 510 open PRs targeting main at preparation time, including their fetched heads, changed files, added exports and relevant diffs. No competing getprogname implementation was found. The broad clang-format PR 1128 does not add this function; merging its current head into this branch produces a textual conflict in libc-internal Export.cpp, among its many existing conflicts with current main. Rebase and preserve both changes if that formatting work lands. This branch has no dependency on descriptor-isolation PR 2170.

Tested

Based on upstream main at d70b89989473ba1f6ae13e44e079e67f1f8a44b0.

  • Windows: WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON; complete all + libs build passed. guest_program_name and adjacent guest_thread_atexit passed (2/2). Test-registration check passed.
  • Linux: Ubuntu 26.04 under WSL, xPack GCC 15.2.0, Release; libc, libkernel, libc-internal and the three selected test targets built. guest_program_name, guest_thread_atexit and guest_force_tls_destructor passed (3/3).
  • No full CTest run and no commercial title testing. Linux graphics libraries were not rebuilt for this libc-internal export.

Checklist

  • Based on current main; no other open PR implements the same function
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; no silent stubs added
  • No notes, investigation files or images added to the repository
  • New third-party code is a submodule built from source (none added)
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is shown stopping at getprogname on main; #1595 and #1869 were closed for the same reason. Reopen with the title ID and the log line when one does.

@Amoenus

Amoenus commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

PPSA99902: independently validated, observed caller and controlled startup comparison

Replayed this PR's head 0cd6b6c7212727b04174525fc1710f6178cf94c4 onto freshly fetched main bf6e25a1ddc009eb232fdfdb3e6ff58b962df006, local commit d7b10e200b2d710a0b4536973f4111ef45656ebf. Windows 11 Enterprise 26200, WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON.

  • Full libs build passed. guest_program_name, guest_thread_atexit and guest_errors each passed 5/5.
  • The program-name test caught three separate deliberately broken implementations: return constant "eboot.bin", cache the original pointer, and return null. Source was restored, full libraries rebuilt, and all three tests passed 5/5 again.
  • Conventions and test-registration checks passed. No Linux, console or full-suite result is claimed.

The returned pointer matches the existing guest name store, as FreeBSD stable/11 getprogname does. This proposal avoids adding a second constant name store; the behavioral test observes pointer replacement and changes to its storage, empty-name readback and errno preservation.

Real title caller. Sonic Unleashed Recompiled, PPSA99902, 01.003.000, unwrapped original executable SHA256 c34f5b0848ef49e96a855076d8254254047e966e4fe56589d0e504fe13828479. With the earlier local diagnostic stack and strict unused-import filtering, the title actually executes, then crashes in strcmp("Project-A.exe", nullptr).

Tracing the original ELF established this data flow:

0x310803e: name getter used when MESA_DRICONF_EXECUTABLE_OVERRIDE is absent
0x2d1e1fb: check MESA_PROCESS_NAME
0x2d1e206: call import slot 0x4ba4a58 when that name is absent
slot relocation: 7Psx1DlAyE4#C#D (getprogname; name hashes back to NID)
0x2d1e236: cache null when that import returns null
0x31080bd: save returned name in frame[-0xe0]
0x3108845: load that value as strcmp's second argument
0x310884f: call strcmp; first argument is "Project-A.exe"

The title's converted guest libc exports 7Psx1DlAyE4 at RVA 0x10050, with 66 0f ef c0 31 c0 c3 (zero return). An isolated call of that verified export returned null. PE/ELF address mapping was checked at the getter call, argument store, comparison call and string bytes. This connects the previously audited fallback to an actual executed fault; the issue is the returned null, not evidence that strcmp should accept null input.

Controlled comparison. Integrated the exact proposal into the existing diagnostic stack, local commit f61e0d7768005504fc70ea385534182a2061ebfb. Full libraries built; program-name, thread-exit, error, utime, pthread-attribute and signal tests each passed 5/5. For the game experiment, preserved the earlier immutable 120-PRX profile and replaced only libSceLibcInternal.prx with the rebuilt library. Executable, guest libc and other runtime libraries were identical, verified by manifests and per-run hashes.

Runtime Runs Result
Earlier profile, no native getprogname 5 earlier + 1 after the comparison 0xC0000005, same null read through strcmp; no Vulkan device ready
Same profile with this native implementation 5 Past the null read; RTX 5080 Vulkan device ready and swapchain created; next stop AGC driver: graphics program does not belong to a registered shader, 0xC0000409

Corrected runs took 7.086, 6.512, 6.600, 6.591 and 6.591 seconds. The restored-library control reproduced the original crash in 5.677 seconds. No rendering, physical audio output or gameplay is verified. This is conditional evidence from a stack of local fixes/placeholders using unused-filter=2 and a relinker built at 57f96fd2; it is not a result from this proposal alone or unchanged main. The original dump, baseline libraries and guest libc are preserved.

The maintainer's unchanged-main first-stop condition remains unmet: the title stops at dup before this call on the pinned baseline. This is validation evidence, not a request to reopen or a new PR. The next graphics stop is covered by existing work in #1732, whose raw-program policy remains under review. AI-assisted investigation: Codex. All additional diagnostic work remains local; no branch push.

Current-main confirmation: refreshed the local diagnostic stack onto main bf6e25a1ddc009eb232fdfdb3e6ff58b962df006 (local commit 1c2b72a0941314b063e0993f4c74b05dc67d72df) and rebuilt full libraries plus the relinker. All 30 TLS coverage groups and five relevant library tests passed 5/5 each; conventions and test registration passed. Reconverted the original title in both filter modes in an isolated output directory. Five strict-filter startup runs again reached the RTX 5080 Vulkan device/swapchain and the same shader-registration refusal; the default-filter stop remains missing pathconf (oc98+zOImus). The new strict executable and guest libc are bit-for-bit identical to their earlier-main conversion, so the recent TLS change does not change these particular artifacts. Baseline runtime-library and original-source hashes verified after all runs. No rendering/gameplay or standalone-current-main compatibility claim; other local prerequisites remain in this stack.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants