Skip to content

feat(libc): implement std::_Throw(const std::bad_array_new_length&) - #10927

Merged
adriadam10 merged 3 commits into
boykopovar:mainfrom
edubox:feat/libc-throw-bad-array-new-length
Oct 29, 2026
Merged

adriadam10 merged 3 commits into
boykopovar:mainfrom
edubox:feat/libc-throw-bad-array-new-length

Conversation

@edubox

@edubox edubox commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What

Implement _ZSt6_ThrowRKSt20bad_array_new_length (1cKlQv7Kvmg), imported by Star Wars Racer (PPSA28416) from libc.

The libc.prx bundled with PRAGMATA PPSA02530 exports it as a 52-byte function at 0xcb2d0 (static disassembly): it ignores its argument, allocates the 8-byte exception object, installs the static _ZTVSt20bad_array_new_length, and calls __cxa_throw. The implementation reuses LibcException::ThrowPlain with that vtable, the same path as __cxa_throw_bad_array_new_length; the argument is deliberately unused, as on the console. A guest test checks the type record, base (std::bad_alloc), vtable and that the call throws, and the debt entry records the console evidence.

Overlap: #9416 adds a void* placeholder for _ZSt6_ThrowRKSt20bad_array_new_length to libc/Export.cpp that throws std::runtime_error; I asked its author to drop it (#9416 (comment)). This PR is the real implementation and does not build on #9416, but the two exports cannot both land. #9416 also already conflicts with current main on the ErrorCode layout (pre-existing, not caused by this PR). The other docs/dev/debt/libc.md and CMakeLists.txt overlaps are unrelated entries.

Tested

Linux, CachyOS 7.3.0, GCC 16.2.1, main b2c7a38840 + this PR:

  • guest_throw_bad_array_new_length passes.
  • guest_bad_optional_access passes.
  • python3 tools/check_conventions.py --base origin/main passes.

The console evidence is static disassembly of the retail libc.prx, not a live console measurement; the title itself was not run.

Checklist

  • Based on current main; no other open PR implements it
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: PPSA28416
  • GPUs tested: n/a
  • AI-assisted: yes

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 25, 2026
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Progress report (3a2b919 → f94297b)

📈 System libraries: 45.91% (+0.0037%, +1 implemented functions)

✅ 1 implemented
Library Name
libc _ZSt6_ThrowRKSt20bad_array_new_length_nid_postfix

Changed libraries (implemented exports)

Library Before After Change
libc 1443/1461 (98.77%) 1444/1462 (98.77%) +0.0008 pp

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 9340 docs/dev/debt/libc.md L197-198

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 5303 docs/dev/debt/libc.md
PR 6085 core/libs/prx/libc/CMakeLists.txt
PR 7081 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 7386 docs/dev/debt/libc.md
PR 7447 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 7715 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 8150 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 9371 docs/dev/debt/libc.md
PR 9447 docs/dev/debt/libc.md
PR 9526 docs/dev/debt/libc.md
PR 10226 docs/dev/debt/libc.md
PR 10229 docs/dev/debt/libc.md
PR 10324 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libc/include/Api.hpp
docs/dev/debt/libc.md
PR 10405 docs/dev/debt/libc.md
PR 10620 docs/dev/debt/libc.md
PR 11332 docs/dev/debt/libc.md
PR 11468 core/libs/prx/libc/CMakeLists.txt
PR 11625 core/libs/prx/libc/CMakeLists.txt
docs/dev/debt/libc.md
PR 12057 docs/dev/debt/libc.md
PR 12560 docs/dev/debt/libc.md
PR 12597 docs/dev/debt/libc.md
PR 12627 docs/dev/debt/libc.md
PR 12688 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libc/include/Api.hpp
docs/dev/debt/libc.md
PR 12700 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libc/include/Api.hpp
docs/dev/debt/libc.md
PR 12965 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libc/include/Api.hpp
docs/dev/debt/libc.md

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 1a6d689 to 5710c87 Compare October 25, 2026 10:57
@edubox

edubox commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Overlap note: pr_overlap flags #9416 as adding the same export. It is a void* placeholder in Export.cpp that throws std::runtime_error, not an implementation; I asked its author to drop it here: #9416 (comment). This PR does not depend on #9416's code, but the two definitions cannot both land. #9416 is also already CONFLICTING with current main on the ErrorCode layout.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 5710c87e1aad77032f6d0e0484494220a8ddfb3a. The export body reuses the existing ThrowPlain path with _ZTVSt20bad_array_new_length, and the type record correctly derives from bad_alloc; the static console evidence and scope are clearly described. I ran g++ -std=c++20 -Wall -Wextra -Werror -Icore/libs -fsyntax-only core/libs/tests/GuestThrowBadArrayNewLength.cpp, tools/check_conventions.py --base upstream/main --head HEAD, and git diff --check upstream/main...HEAD; all passed. I could not run the linked CTest target in this checkout because the third-party submodules are uninitialized.

One test gap: GuestThrowBadArrayNewLength.cpp catches ..., so it passes if the export throws a different exception type (for example, bad_alloc) even though the purpose of this symbol is to throw std::bad_array_new_length. Please assert the caught dynamic type, and fail if a different exception is caught; retaining the RTTI/vtable layout checks is useful but does not verify the type thrown by this entry point.

@edubox

edubox commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Pushed c437e5a8cc for the test gap.

The catch (...) now reads the thrown type with
__cxa_current_exception_type_nid_postfix() and requires its name() to
match the exported _ZTISt20bad_array_new_length_nid_postfix record, so a
different exception such as bad_alloc fails the test instead of passing.

Verification:

  • Positive: guest_throw_bad_array_new_length passes on the new head.
  • Negative control: replacing the call with
    _ZSt11_Xbad_allocv_nid_postfix() (throws bad_alloc) makes the test
    abort; restoring the export call passes again.
  • python3 tools/check_conventions.py --base origin/main: clean.

The RTTI/vtable layout and base-type checks are unchanged. Not run:
Windows/macOS (no host here).

@wachi35676

Copy link
Copy Markdown
Contributor

Windows run of head c437e5a8cc42 merged onto main aeff26bd9. Windows 11 10.0.26300, WinLibs GCC 15.2.0, Release.

  • guest_throw_bad_array_new_length and guest_bad_optional_access pass, 2 runs. The build has 0 warnings.
  • Without the PR's Api.hpp and StandardExceptions.cpp changes, the test doesn't compile. The previously built executable then won't start against the rebuilt libc.prx (0xc0000139, entry point not found). So the test really depends on the new export.
  • feat(libc): implement system_category and future_category error categ… #9416, the other definition of _ZSt6_ThrowRKSt20bad_array_new_length, was closed on 2026-10-25, so that overlap is gone.

AI-assisted: yes (Claude Code); results above were run on this machine.

@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

The test gap from the review is addressed at c437e5a8cc: the catch (...) now reads the thrown type with __cxa_current_exception_type_nid_postfix() and requires the exported _ZTISt20bad_array_new_length_nid_postfix name, so a different exception such as bad_alloc fails the test. The Windows run on this head also passes. Could you re-review the exact head?

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from c437e5a to 8a22e09 Compare October 26, 2026 05:57
@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main 14c99b52ac to clear the conflict with the new CMake test blocks; the change itself is unchanged. guest_throw_bad_array_new_length and guest_bad_optional_access pass on the rebased head, and conventions are clean. Could you re-review the exact head?

@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 26, 2026
@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 8a22e09 to 93c5eba Compare October 26, 2026 12:23
@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main 2db37cf1de. The only conflict was in core/libs/prx/libc/CMakeLists.txt: this PR adds its test block where main now adds the Windows exception_personality block. Both blocks are retained, and the change itself is unchanged.

guest_throw_bad_array_new_length and guest_bad_optional_access pass on the rebased head 93c5eba5d6, and check_conventions.py and git diff --check are clean. Could you re-review the exact head?

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (518d36eaec); head is now 9cc1507f5f. The test asserts the caught dynamic type via __cxa_current_exception_type (it must be St20bad_array_new_length, not bad_alloc); rebuilt and ran guest_throw_bad_array_new_length on the rebased head: passes. check_conventions.py --base origin/main: all checks passed.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch 2 times, most recently from 9cc1507 to 96e0a37 Compare October 26, 2026 17:55
@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (88795ed448); head is now 96e0a37b0a. The change itself is unchanged. Rebuilt and ran guest_throw_bad_array_new_length and guest_bad_optional_access on the rebased head: both pass. check_conventions.py --base origin/main and git diff --check are clean. Could you re-check the exact head?

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 96e0a37 to ab17f79 Compare October 26, 2026 21:39
@edubox

edubox commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Rebased again onto current main (85071975fb); head is now ab17f79043. No code changes. guest_throw_bad_array_new_length and guest_bad_optional_access pass; conventions/diff-check clean. Could you re-check the exact head?

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from ab17f79 to b329765 Compare October 26, 2026 22:03
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (0cd07dc4ab); head is now b14481c247. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (d7fd416992); head is now 031c83f7d4. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from b14481c to 031c83f Compare October 28, 2026 08:04
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (cc672fdfc6); head is now e1b5aa8051. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 031c83f to e1b5aa8 Compare October 28, 2026 09:04
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (3a40945e62); head is now 88df37c6f0. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from e1b5aa8 to 88df37c Compare October 28, 2026 10:03
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (2227f13661); head is now bce1351872. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 88df37c to bce1351 Compare October 28, 2026 12:03
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (d4cb89300f); head is now 7daa9d7a77. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from bce1351 to 7daa9d7 Compare October 28, 2026 14:03
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (17f8dfad51); head is now d0ffc18304. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (7fea87746b); head is now 91a46e583c. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from d0ffc18 to 91a46e5 Compare October 28, 2026 17:03
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (319621ba2e); head is now f14c754f20. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 91a46e5 to f14c754 Compare October 28, 2026 19:02
@edubox

edubox commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (c9207624bc); head is now 490e8139b4. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from f14c754 to 490e813 Compare October 28, 2026 23:03
Follow the console libc.prx (PPSA02530) at 0xcb2d0: ignore the argument and throw the static bad_array_new_length object. Star Wars Racer (PPSA28416) imports it.
@edubox

edubox commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Rebased automatically onto current main (3a2b919816); head is now f94297b8c2. Focused tests pass; check_conventions.py --base origin/main and git diff --check are clean.

@edubox
edubox force-pushed the feat/libc-throw-bad-array-new-length branch from 490e813 to f94297b Compare October 29, 2026 00:03

@XairRrR XairRrR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — approved

The export is correct (NID 1cKlQv7Kvmg matches the name, it throws std::bad_array_new_length through the existing ThrowPlain path), it merges cleanly onto current main, and the new test passes and fails under two negative controls. I have one non-blocking note on the wording of the debt entry.

What I ran

Head f94297b8c2138ef9b963c8e25f9df7f40ab132da merged (--no-ff) onto main d71fe2fa87f8d74b14ad86506b5f0ed916b33a70 in a clean worktree. Arch Linux 7.2.11-zen, GCC 16.2.1, Intel Core i9-14900KF, Release, Ninja, BUILD_TESTING=ON.

git fetch origin main pull/10927/head:refs/review/10927
git checkout --detach origin/main
git merge --no-ff --no-edit refs/review/10927
git diff --check origin/main...refs/review/10927
python3 tools/check_conventions.py --base origin/main
cmake -S . -B build
cmake --build build -j10 --target guest_throw_bad_array_new_length_tests guest_bad_optional_access_tests exception_runtime_tests libs
ctest --test-dir build -j4 --output-on-failure -R "guest_throw_bad_array_new_length|guest_bad_optional_access|exception_runtime"
nm -D build/core/libs/libs/libc.prx | grep 1cKlQv7Kvmg
# NID: SHA-1(name + 518D64A635DED8C1E6B039B1C3E55230), first 8 bytes as LE u64, BE base64, '/' -> '-'

Results

Check Result
Merge onto main Clean (core/libs/prx/libc/CMakeLists.txt auto-merged)
git diff --check Clean
check_conventions.py --base origin/main All conventions checks passed
Build (libs and the three test targets) OK, no warnings in the changed files
guest_throw_bad_array_new_length Passed (0.00 s)
guest_bad_optional_access, exception_runtime Passed
NID of _ZSt6_ThrowRKSt20bad_array_new_length Computes to 1cKlQv7Kvmg, matches the description and debt entry
Export in the built libc.prx 0000000000108020 T 1cKlQv7Kvmg
ctest
1/3 Test #627: guest_bad_optional_access ..........   Passed    0.00 sec
2/3 Test #629: guest_throw_bad_array_new_length ...   Passed    0.00 sec
3/3 Test #633: exception_runtime ..................   Passed    0.00 sec

100% tests passed out of 3

Negative control

  1. I restored core/libs/prx/libc/include/Api.hpp and core/libs/prx/libc/src/exception/StandardExceptions.cpp from main. The test no longer compiles (_ZSt6_ThrowRKSt20bad_array_new_length_nid_postfix not declared). This matches the Windows result reported earlier in the thread.
  2. That only shows that the test needs the symbol, so I also checked the type assertion. I changed the new export's body to throw std::bad_alloc (ThrowPlain(_ZTVSt9bad_alloc_nid_postfix)) and rebuilt. guest_throw_bad_array_new_length then fails (Subprocess aborted). This confirms the fix for the earlier review's catch (...) gap: the test now rejects the base type. With the file restored, the test passes again.

Findings

Blocking

None.

Non-blocking

  • docs/dev/debt/libc.md:194: the entry describes the console function and the implementation but never names a gap. CONTRIBUTING.md asks that an entry "states the gap first (what differs from the console, what is unverified, what throws)". The open point is that the evidence is static disassembly of the libc.prx bundled with PPSA02530, while the importer is PPSA28416, and it was not checked at runtime. Suggested wording: lead with "Unverified at runtime; follows static disassembly of the libc.prx bundled with PPSA02530 …". Alternatively, if maintainers consider the behaviour settled, drop the entry and keep the evidence in the PR body.

Not verified

  • Windows and macOS builds. Windows runs were reported in the thread by two contributors; I did not repeat them.
  • The console disassembly of libc.prx (PPSA02530, 0xcb2d0). I have no copy and took the description's reading as given.
  • Running PPSA28416. Not done, per review policy.

@adriadam10
adriadam10 merged commit 5e216d6 into boykopovar:main Oct 29, 2026
17 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the export against the existing ThrowPlain path and _ZTVSt20bad_array_new_length, and that the test reads the caught dynamic type, so a bad_alloc or any other exception fails it. The debt entry is accurate and carries no title name. Confirmed by @XairRrR (Linux, negative controls), @wachi35676 and @maskym (Windows); merged.

@edubox
edubox deleted the feat/libc-throw-bad-array-new-length branch October 29, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build docs libc unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants