Merge pull request #9468 from mazen320/feat/libc-num-get-w-vtable

feat(libc): export the wide num_get facet vtable as data
This commit is contained in:
Adrià authored and GitHub committed 2026-10-26 13:21:19 +01:00
commit 2db37cf1de
3 files changed
+13

No files matched your search

+1
View File
@@ -386,6 +386,7 @@ std::uint64_t _ZNSt8numpunctIcE2idE_nid_postfix = 0;
std::uint64_t _ZNSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix = 0;
std::uintptr_t _ZTVSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE_nid_postfix[13] {};
std::uintptr_t _ZTVSt8time_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix[13] {};
std::uintptr_t _ZTVSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix[17] {};
std::streamoff _ZSt7_BADOFF_nid_postfix = -1;
std::fpos_t _ZSt4_Fpz_nid_postfix {};
+11
View File
@@ -24,6 +24,7 @@ extern std::uintptr_t _ZTVSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIw
extern std::uintptr_t _ZTVSt7collateIcE_nid_postfix[9];
extern std::uintptr_t _ZTVSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE_nid_postfix[13];
extern std::uintptr_t _ZTVSt8time_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix[13];
extern std::uintptr_t _ZTVSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix[17];
}
@@ -336,6 +337,15 @@ static void CheckFacetGetcat() {
Require(_ZNSt8numpunctIcE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(&punct, &locale) == 4);
}
static void CheckNumGetWideVtableObject() {
for (std::uintptr_t& slot : _ZTVSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix) {
Require(slot == 0);
slot = 0x1111;
Require(slot == 0x1111);
slot = 0;
}
}
static void CheckTimeGetVtableObject() {
for (std::uintptr_t& slot : _ZTVSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE_nid_postfix) {
Require(slot == 0);
@@ -379,6 +389,7 @@ int main() {
CheckCollateVtableObject();
CheckTimeGetVtableObject();
CheckTimeGetWideVtableObject();
CheckNumGetWideVtableObject();
_Locksyslock_nid_postfix();
_Locksyslock_nid_postfix();
_Unlocksyslock_nid_postfix();
+1
View File
@@ -182,6 +182,7 @@
- [num_put<wchar_t> vtable](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, NID `59oywaaZbJk`) is fourteen zeroed `uintptr_t` slots matching `st_size` 112 on the title `libc.prx` from PPSA16833 (offset-to-top, typeinfo, two destructors, `_Incref`/`_Decref`, and eight `do_put` virtuals). Facet calls through the object fault until those methods are wired.
- [time_get<char> vtable](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, NID `o4kt51-uO48`) is thirteen zeroed `uintptr_t` slots matching `st_size` 104 on console `libSceLibcInternal.sprx` (offset-to-top, typeinfo, two destructors, `_Incref`/`_Decref`, and seven `do_*` virtuals). Facet calls through the object fault until those methods are wired.
- [time_get<wchar_t> vtable](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, NID `sEca1nUOueA`) is thirteen zeroed `uintptr_t` slots matching `st_size` 104 on console `libSceLibcInternal.sprx` (offset-to-top, typeinfo, two destructors, `_Incref`/`_Decref`, and seven `do_*` virtuals). Facet calls through the object fault until those methods are wired.
- [num_get<wchar_t> vtable](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, NID `Y9C9GeKyZ3A`) is seventeen zeroed `uintptr_t` slots matching `st_size` 136 on console `libSceLibcInternal.sprx` (offset-to-top, typeinfo, two destructors, `_Incref`/`_Decref`, and eleven `do_get` virtuals). Facet calls through the object fault until those methods are wired.
- [ios_base standard streams](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc) `_Addstd` queues the stream in the standard stream table of Dinkumware [ios.cpp](https://github.com/ganboing/crt.vc12/blob/master/src/ios.cpp) (`stdstr`, `stdopens`, `_Addstd`, `_Ios_base_dtor`): it takes the first of slots 1 to 7 that is free or already holds the stream, and slot 8 (`NSTDSTR`) when none is, so slot 8 is shared by every stream past the first seven and registration never fails. It stores the 1-based slot index in the guest `IosBase::standardStream` (Dinkumware's `_Stdstr`, where 0 means not a standard stream) and counts the stream objects registered per slot; registering the same stream again reuses its slot and raises its count. Measured on a PS5 (firmware 13.60) from a homebrew payload calling the system `libSceLibcInternal` export: in a process whose own standard streams already hold slots 1 to 7, twelve distinct streams and a repeated one all get 8, written as a 64-bit value at offset 0x8 with no other byte of the object touched; the assignment of slots 1 to 7 to fresh streams is not observable there and follows VC12. The counts are `int`, not VC12's `char`, and the registration and the destructor lock the table where VC12 locks only `_Addstd`; a slot index past the table throws in the destructor instead of indexing out of bounds. The destructor decrements its slot's count and suppresses the rest of the destruction while the count stays positive, as `_Ios_base_dtor` does, and the slots of destroyed streams keep their pointer and stay reserved for that stream, as `stdstr` does. The streams themselves are destroyed by the title's own code as it registers them through `__cxa_atexit`; when the last reference closes, the unsupported stream storage and callback cleanup is still the throw it was and the locale is released as for a non-standard stream.
- [std::_Pad, _Thrd_join, _Thrd_detach, _Thrd_id](../../../core/libs/prx/libc/src/Threads.cpp) (libc) follow Dinkumware V6.00 `thr/xthread` and `thr/threadcall.cpp` ([crt.vc12 `f1d47126`](https://github.com/ganboing/crt.vc12/tree/f1d47126/src/thr)), otherwise without console verification. `_Thrd_id` returns `scePthreadSelf()` unchanged, as measured on a PS5 (firmware 13.40) in two threads (#4164, #8711); `_Launch` omits `_Cnd_do_broadcast_at_thread_exit`; the two-argument form starts with default attributes and the three-argument form forwards the caller's attribute pointer, as PPSA02530's `libc.prx` does at `0x18090`. The 32-byte pad layout is assumed from VC12, unverified. Failing primitives or thread start throw the guest `std::system_error`; null arguments throw. `_Thrd_join` returns `_Thrd_error` (4) on `pthread_join` failure and truncates the exit code to `int`; `_Thrd_detach` returns `_Thrd_error` (4) on `pthread_detach` failure and throws when none is registered
- [siginterrupt](../../../core/libs/prx/libc/src/Process.cpp) (libc) runs FreeBSD 11.4's `siginterrupt.c` sequence through the `sigaction` and the `_sigintr` set that libkernel registers at load: it reads the signal's disposition, sets or clears the signal's bit and `SA_RESTART`, and installs the disposition again. The set is written outside libkernel's registration lock, as FreeBSD's libc writes it without one; a call before libkernel has registered throws.