From 1842d9b1a353e9d9b49d73cf770f6a4275cd9ecc Mon Sep 17 00:00:00 2001 From: B-Howell <116104752+B-Howell@users.noreply.github.com> Date: Wed, 4 Nov 2026 08:56:43 -0500 Subject: [PATCH] feat(libSceLibcInternal): implement the num_get and num_get get members Each of the eleven num_get::get and eleven num_get::get overloads returns do_get through the facet's own vtable, as [facet.num.get.members] requires. The do_get slots follow the declaration order of microsoft/STL xlocnum, the order NumPutVtable already uses for num_put. GuestLocale gains an opaque 16-byte InputIterator for istreambuf_iterator and the NumGetVtable layout. Co-Authored-By: Claude Opus 5.5 --- .../prx/libSceLibcInternal/CMakeLists.txt | 13 ++ core/libs/prx/libSceLibcInternal/Err.cpp | 132 ------------- core/libs/prx/libSceLibcInternal/NumGet.cpp | 126 +++++++++++++ core/libs/prx/libc/include/GuestLocale.hpp | 36 ++++ core/libs/tests/GuestLibcInternalNumGet.cpp | 173 ++++++++++++++++++ docs/dev/debt/libSceLibcInternal.md | 23 +-- 6 files changed, 349 insertions(+), 154 deletions(-) create mode 100644 core/libs/prx/libSceLibcInternal/NumGet.cpp create mode 100644 core/libs/tests/GuestLibcInternalNumGet.cpp diff --git a/core/libs/prx/libSceLibcInternal/CMakeLists.txt b/core/libs/prx/libSceLibcInternal/CMakeLists.txt index 774ed8f0634b..c36071565541 100644 --- a/core/libs/prx/libSceLibcInternal/CMakeLists.txt +++ b/core/libs/prx/libSceLibcInternal/CMakeLists.txt @@ -20,6 +20,19 @@ if(BUILD_TESTING) endif() target_sources(libSceLibcInternal PRIVATE InitOnce.cpp) target_sources(libSceLibcInternal PRIVATE Mutex.cpp) +target_sources(libSceLibcInternal PRIVATE NumGet.cpp) +if(BUILD_TESTING) + add_test_executable(guest_libc_internal_num_get_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibcInternalNumGet.cpp) + target_include_directories(guest_libc_internal_num_get_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libc_internal_num_get_tests PRIVATE libSceLibcInternal libkernel libc ${CMAKE_DL_LIBS}) + configure_windows_unwind(guest_libc_internal_num_get_tests) + add_test(NAME guest_libc_internal_num_get COMMAND guest_libc_internal_num_get_tests $) + set_tests_properties(guest_libc_internal_num_get PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_libc_internal_num_get PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() target_sources(libSceLibcInternal PRIVATE AlignedNew.cpp) if(BUILD_TESTING) add_test_executable(guest_libc_internal_aligned_new_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibcInternalAlignedNew.cpp) diff --git a/core/libs/prx/libSceLibcInternal/Err.cpp b/core/libs/prx/libSceLibcInternal/Err.cpp index d89aa3560864..94d928a4fb7a 100644 --- a/core/libs/prx/libSceLibcInternal/Err.cpp +++ b/core/libs/prx/libSceLibcInternal/Err.cpp @@ -477,72 +477,6 @@ int APS5_VABI sceLibcInternalPending3_054_nid_no_patch() { } APS5_EXPORT("81uX7PzrtG8", sceLibcInternalPending3_054_nid_no_patch); -int APS5_VABI sceLibcInternalPending3_055_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("my9ujasm6-0", sceLibcInternalPending3_055_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_056_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("OWO5cpNw3NA", sceLibcInternalPending3_056_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_057_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("mAwXCpkWaYc", sceLibcInternalPending3_057_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_058_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("wUCRGap1j0U", sceLibcInternalPending3_058_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_059_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("6RGkooTERsE", sceLibcInternalPending3_059_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_060_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("N1VqUWz2OEI", sceLibcInternalPending3_060_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_061_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("I2UzwkwwEPs", sceLibcInternalPending3_061_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_062_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("2bfL3yIBi5k", sceLibcInternalPending3_062_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_063_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("gozsp4urvq8", sceLibcInternalPending3_063_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_064_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("4hiQK82QuLc", sceLibcInternalPending3_064_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_065_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("eZfFLyWCkvg", sceLibcInternalPending3_065_nid_no_patch); - int APS5_VABI sceLibcInternalPending3_066_nid_no_patch() { NotImplemented_nid_no_patch(__func__); return 0; @@ -627,72 +561,6 @@ int APS5_VABI sceLibcInternalPending3_079_nid_no_patch() { } APS5_EXPORT("J-0I2PtiZc4", sceLibcInternalPending3_079_nid_no_patch); -int APS5_VABI sceLibcInternalPending3_080_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("zomvAQ5RFdA", sceLibcInternalPending3_080_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_081_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("vW-nnV62ea4", sceLibcInternalPending3_081_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_082_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("+hjXHfvy1Mg", sceLibcInternalPending3_082_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_083_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("xLZr4GJRMLo", sceLibcInternalPending3_083_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_084_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("2mb8FYgER+E", sceLibcInternalPending3_084_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_085_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("Y3hBU5FYmhM", sceLibcInternalPending3_085_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_086_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("-m2YPwVCwJQ", sceLibcInternalPending3_086_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_087_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("94ZLp2+AOq0", sceLibcInternalPending3_087_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_088_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("bZ+lKHGvOr8", sceLibcInternalPending3_088_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_089_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("cG5hQhjFGog", sceLibcInternalPending3_089_nid_no_patch); - -int APS5_VABI sceLibcInternalPending3_090_nid_no_patch() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -APS5_EXPORT("banNSumaAZ0", sceLibcInternalPending3_090_nid_no_patch); - int APS5_VABI sceLibcInternalPending3_091_nid_no_patch() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceLibcInternal/NumGet.cpp b/core/libs/prx/libSceLibcInternal/NumGet.cpp new file mode 100644 index 000000000000..5941f9355093 --- /dev/null +++ b/core/libs/prx/libSceLibcInternal/NumGet.cpp @@ -0,0 +1,126 @@ +#include "prx/libc/include/GuestLocale.hpp" +#include "prx/libc/include/General.hpp" +#include "SceTypes.hpp" +#include + +namespace { + +const GuestLocale::NumGetVtable& NumGet(const GuestLocale::Facet* self) { + return *reinterpret_cast(self->vtable); +} + +} + +extern "C" { + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetBool_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, bool* value) { + return NumGet(self).getBool(self, first, last, stream, state, value); +} +APS5_EXPORT("OWO5cpNw3NA", sceLibcInternalNumGetBool_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetUnsignedShort_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint16_t* value) { + return NumGet(self).getUnsignedShort(self, first, last, stream, state, value); +} +APS5_EXPORT("gozsp4urvq8", sceLibcInternalNumGetUnsignedShort_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetUnsignedInt_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint32_t* value) { + return NumGet(self).getUnsignedInt(self, first, last, stream, state, value); +} +APS5_EXPORT("N1VqUWz2OEI", sceLibcInternalNumGetUnsignedInt_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::int64_t* value) { + return NumGet(self).getLong(self, first, last, stream, state, value); +} +APS5_EXPORT("I2UzwkwwEPs", sceLibcInternalNumGetLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetUnsignedLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint64_t* value) { + return NumGet(self).getUnsignedLong(self, first, last, stream, state, value); +} +APS5_EXPORT("2bfL3yIBi5k", sceLibcInternalNumGetUnsignedLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetLongLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::int64_t* value) { + return NumGet(self).getLongLong(self, first, last, stream, state, value); +} +APS5_EXPORT("4hiQK82QuLc", sceLibcInternalNumGetLongLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetUnsignedLongLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint64_t* value) { + return NumGet(self).getUnsignedLongLong(self, first, last, stream, state, value); +} +APS5_EXPORT("eZfFLyWCkvg", sceLibcInternalNumGetUnsignedLongLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetFloat_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, float* value) { + return NumGet(self).getFloat(self, first, last, stream, state, value); +} +APS5_EXPORT("6RGkooTERsE", sceLibcInternalNumGetFloat_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetDouble_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, double* value) { + return NumGet(self).getDouble(self, first, last, stream, state, value); +} +APS5_EXPORT("mAwXCpkWaYc", sceLibcInternalNumGetDouble_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetLongDouble_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, long double* value) { + return NumGet(self).getLongDouble(self, first, last, stream, state, value); +} +APS5_EXPORT("wUCRGap1j0U", sceLibcInternalNumGetLongDouble_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalNumGetPointer_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, void** value) { + return NumGet(self).getPointer(self, first, last, stream, state, value); +} +APS5_EXPORT("my9ujasm6-0", sceLibcInternalNumGetPointer_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetBool_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, bool* value) { + return NumGet(self).getBool(self, first, last, stream, state, value); +} +APS5_EXPORT("vW-nnV62ea4", sceLibcInternalWideNumGetBool_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetUnsignedShort_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint16_t* value) { + return NumGet(self).getUnsignedShort(self, first, last, stream, state, value); +} +APS5_EXPORT("bZ+lKHGvOr8", sceLibcInternalWideNumGetUnsignedShort_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetUnsignedInt_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint32_t* value) { + return NumGet(self).getUnsignedInt(self, first, last, stream, state, value); +} +APS5_EXPORT("Y3hBU5FYmhM", sceLibcInternalWideNumGetUnsignedInt_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::int64_t* value) { + return NumGet(self).getLong(self, first, last, stream, state, value); +} +APS5_EXPORT("-m2YPwVCwJQ", sceLibcInternalWideNumGetLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetUnsignedLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint64_t* value) { + return NumGet(self).getUnsignedLong(self, first, last, stream, state, value); +} +APS5_EXPORT("94ZLp2+AOq0", sceLibcInternalWideNumGetUnsignedLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetLongLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::int64_t* value) { + return NumGet(self).getLongLong(self, first, last, stream, state, value); +} +APS5_EXPORT("cG5hQhjFGog", sceLibcInternalWideNumGetLongLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetUnsignedLongLong_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, std::uint64_t* value) { + return NumGet(self).getUnsignedLongLong(self, first, last, stream, state, value); +} +APS5_EXPORT("banNSumaAZ0", sceLibcInternalWideNumGetUnsignedLongLong_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetFloat_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, float* value) { + return NumGet(self).getFloat(self, first, last, stream, state, value); +} +APS5_EXPORT("2mb8FYgER+E", sceLibcInternalWideNumGetFloat_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetDouble_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, double* value) { + return NumGet(self).getDouble(self, first, last, stream, state, value); +} +APS5_EXPORT("+hjXHfvy1Mg", sceLibcInternalWideNumGetDouble_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetLongDouble_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, long double* value) { + return NumGet(self).getLongDouble(self, first, last, stream, state, value); +} +APS5_EXPORT("xLZr4GJRMLo", sceLibcInternalWideNumGetLongDouble_nid_no_patch); + +GuestLocale::InputIterator APS5_VABI sceLibcInternalWideNumGetPointer_nid_no_patch(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, void** value) { + return NumGet(self).getPointer(self, first, last, stream, state, value); +} +APS5_EXPORT("zomvAQ5RFdA", sceLibcInternalWideNumGetPointer_nid_no_patch); + +} diff --git a/core/libs/prx/libc/include/GuestLocale.hpp b/core/libs/prx/libc/include/GuestLocale.hpp index 49918225170c..d09b49a1bf3d 100644 --- a/core/libs/prx/libc/include/GuestLocale.hpp +++ b/core/libs/prx/libc/include/GuestLocale.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "general/VabiMacros.hpp" struct GuestTm; @@ -188,6 +189,13 @@ struct OutputIterator { Streambuf* buffer; }; +struct InputIterator { + std::uint64_t words[2]; +}; + +static_assert(sizeof(InputIterator) == 0x10); +static_assert(std::is_trivially_copyable_v); + struct TimePutVtable { FacetVtable facet; OutputIterator (APS5_VABI *put)(const Facet* self, OutputIterator out, IosBase* stream, char fill, const GuestTm* time, char format, char modifier); @@ -205,6 +213,34 @@ struct NumPutVtable { OutputIterator (APS5_VABI *putPointer)(const Facet* self, OutputIterator out, IosBase* stream, char fill, const void* value); }; +struct NumGetVtable { + FacetVtable facet; + InputIterator (APS5_VABI *getBool)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, bool* value); + InputIterator (APS5_VABI *getUnsignedShort)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::uint16_t* value); + InputIterator (APS5_VABI *getUnsignedInt)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::uint32_t* value); + InputIterator (APS5_VABI *getLong)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::int64_t* value); + InputIterator (APS5_VABI *getUnsignedLong)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::uint64_t* value); + InputIterator (APS5_VABI *getLongLong)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::int64_t* value); + InputIterator (APS5_VABI *getUnsignedLongLong)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, std::uint64_t* value); + InputIterator (APS5_VABI *getFloat)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, float* value); + InputIterator (APS5_VABI *getDouble)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, double* value); + InputIterator (APS5_VABI *getLongDouble)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, long double* value); + InputIterator (APS5_VABI *getPointer)(const Facet* self, InputIterator first, InputIterator last, IosBase* stream, std::int32_t* state, void** value); +}; + +static_assert(offsetof(NumGetVtable, getBool) == 0x20); +static_assert(offsetof(NumGetVtable, getUnsignedShort) == 0x28); +static_assert(offsetof(NumGetVtable, getUnsignedInt) == 0x30); +static_assert(offsetof(NumGetVtable, getLong) == 0x38); +static_assert(offsetof(NumGetVtable, getUnsignedLong) == 0x40); +static_assert(offsetof(NumGetVtable, getLongLong) == 0x48); +static_assert(offsetof(NumGetVtable, getUnsignedLongLong) == 0x50); +static_assert(offsetof(NumGetVtable, getFloat) == 0x58); +static_assert(offsetof(NumGetVtable, getDouble) == 0x60); +static_assert(offsetof(NumGetVtable, getLongDouble) == 0x68); +static_assert(offsetof(NumGetVtable, getPointer) == 0x70); +static_assert(sizeof(NumGetVtable) == 0x78); + struct CtypeVtable { FacetVtable facet; const void* caseMethods[4]; diff --git a/core/libs/tests/GuestLibcInternalNumGet.cpp b/core/libs/tests/GuestLibcInternalNumGet.cpp new file mode 100644 index 000000000000..0c2155be3415 --- /dev/null +++ b/core/libs/tests/GuestLibcInternalNumGet.cpp @@ -0,0 +1,173 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/GuestLocale.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace { + +void Require(bool condition, const char* message) { + if (condition) return; + std::fprintf(stderr, "libc internal num_get: %s\n", message); + std::exit(1); +} + +void* APS5_VABI TestAllocate(std::size_t size) { return std::malloc(size); } +void APS5_VABI TestFree(void* pointer) { std::free(pointer); } +void* APS5_VABI TestCalloc(std::size_t count, std::size_t size) { return std::calloc(count, size); } +void* APS5_VABI TestReallocate(void* pointer, std::size_t size) { return std::realloc(pointer, size); } +void* APS5_VABI TestAlign(std::size_t, std::size_t size) { return std::malloc(size); } +void* APS5_VABI TestRealign(void* pointer, std::size_t size, std::size_t) { return std::realloc(pointer, size); } +int APS5_VABI TestPosixAlign(void** pointer, std::size_t, std::size_t size) { + *pointer = std::malloc(size); + return *pointer ? 0 : 12; +} + +#ifdef _WIN32 +HMODULE g_library = nullptr; +#else +void* g_library = nullptr; +#endif + +template +TFunction Export(const char* nid) { + const std::string name = std::string(nid) + "_nid_no_patch_cut"; +#ifdef _WIN32 + auto* address = reinterpret_cast(GetProcAddress(g_library, name.c_str())); +#else + void* address = dlsym(g_library, name.c_str()); +#endif + Require(address != nullptr, "missing export"); + return reinterpret_cast(address); +} + +void APS5_VABI TestFacetNop(GuestLocale::Facet*) {} +GuestLocale::Facet* APS5_VABI TestFacetRelease(GuestLocale::Facet*) { return nullptr; } +const GuestLocale::FacetVtable g_testFacet{TestFacetNop, TestFacetNop, TestFacetNop, TestFacetRelease}; + +constexpr int kDerived = 100; +constexpr std::uint64_t kReturnedLow = 0x5a5a000000000000ull; +constexpr std::uint64_t kReturnedHigh = 0x00000000a5a5a502ull; + +GuestLocale::InputIterator Iterator(std::uint64_t low, std::uint64_t high) { + return GuestLocale::InputIterator{{low, high}}; +} + +bool Same(const GuestLocale::InputIterator& left, const GuestLocale::InputIterator& right) { + return left.words[0] == right.words[0] && left.words[1] == right.words[1]; +} + +struct Call { + int slot; + int calls; + const GuestLocale::Facet* self; + GuestLocale::InputIterator first; + GuestLocale::InputIterator last; + GuestLocale::IosBase* stream; + std::int32_t* state; + void* value; +}; + +Call g_call{}; + +template +GuestLocale::InputIterator APS5_VABI Record(const GuestLocale::Facet* self, GuestLocale::InputIterator first, GuestLocale::InputIterator last, GuestLocale::IosBase* stream, std::int32_t* state, TValue* value) { + g_call = Call{TSlot, g_call.calls + 1, self, first, last, stream, state, value}; + *state |= 2; + return Iterator(kReturnedLow + TSlot, kReturnedHigh); +} + +template +GuestLocale::NumGetVtable RecordingVtable() { + return GuestLocale::NumGetVtable{g_testFacet, + Record, Record, Record, + Record, Record, Record, + Record, Record, Record, + Record, Record}; +} + +const GuestLocale::NumGetVtable g_baseVtable = RecordingVtable<0>(); +const GuestLocale::NumGetVtable g_derivedVtable = RecordingVtable(); + +template +using NumGetExport = GuestLocale::InputIterator (APS5_VABI*)(const GuestLocale::Facet*, GuestLocale::InputIterator, GuestLocale::InputIterator, GuestLocale::IosBase*, std::int32_t*, TValue*); + +template +void CheckGet(const char* nid, int slot) { + const auto get = Export>(nid); + for (const GuestLocale::NumGetVtable* vtable : {&g_baseVtable, &g_derivedVtable}) { + const int expected = slot + (vtable == &g_derivedVtable ? kDerived : 0); + GuestLocale::Facet facet{&vtable->facet, 1, 0}; + GuestLocale::IosBase stream{}; + std::int32_t state = 4; + TValue value{}; + const GuestLocale::InputIterator first = Iterator(0x1111222233334444ull + expected, 0x0000000000004101ull); + const GuestLocale::InputIterator last = Iterator(0x5555666677778888ull, 0x0000000000000001ull + expected); + const int calls = g_call.calls; + const GuestLocale::InputIterator result = get(&facet, first, last, &stream, &state, &value); + Require(g_call.calls == calls + 1, "get calls do_get exactly once"); + Require(g_call.slot == expected, "get calls the do_get slot of its value type in the facet's own vtable"); + Require(g_call.self == &facet && g_call.stream == &stream && g_call.state == &state && g_call.value == &value, "get passes the facet, stream, state and value"); + Require(Same(g_call.first, first) && Same(g_call.last, last), "get passes both iterators unchanged"); + Require(Same(result, Iterator(kReturnedLow + expected, kReturnedHigh)), "get returns the iterator do_get returns"); + Require(state == 6, "get leaves the state to do_get"); + } +} + + +} + +int main(int argc, char** argv) { +#ifdef _WIN32 + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); +#endif + Require(argc == 2, "expected the libSceLibcInternal path"); +#ifdef _WIN32 + g_library = LoadLibraryA(argv[1]); +#else + g_library = dlopen(argv[1], RTLD_NOW | RTLD_LOCAL); +#endif + Require(g_library != nullptr, "load libSceLibcInternal"); + const std::array api{ + reinterpret_cast(&TestAllocate), reinterpret_cast(&TestFree), + reinterpret_cast(&TestCalloc), reinterpret_cast(&TestReallocate), + reinterpret_cast(&TestAlign), reinterpret_cast(&TestRealign), + reinterpret_cast(&TestPosixAlign), nullptr, nullptr, nullptr}; + ApplicationHeapRegister_nid_no_patch(api.data()); + + CheckGet("OWO5cpNw3NA", 0); + CheckGet("gozsp4urvq8", 1); + CheckGet("N1VqUWz2OEI", 2); + CheckGet("I2UzwkwwEPs", 3); + CheckGet("2bfL3yIBi5k", 4); + CheckGet("4hiQK82QuLc", 5); + CheckGet("eZfFLyWCkvg", 6); + CheckGet("6RGkooTERsE", 7); + CheckGet("mAwXCpkWaYc", 8); + CheckGet("wUCRGap1j0U", 9); + CheckGet("my9ujasm6-0", 10); + CheckGet("vW-nnV62ea4", 0); + CheckGet("bZ+lKHGvOr8", 1); + CheckGet("Y3hBU5FYmhM", 2); + CheckGet("-m2YPwVCwJQ", 3); + CheckGet("94ZLp2+AOq0", 4); + CheckGet("cG5hQhjFGog", 5); + CheckGet("banNSumaAZ0", 6); + CheckGet("2mb8FYgER+E", 7); + CheckGet("+hjXHfvy1Mg", 8); + CheckGet("xLZr4GJRMLo", 9); + CheckGet("zomvAQ5RFdA", 10); + + std::puts("libc internal num_get checks passed"); + return 0; +} diff --git a/docs/dev/debt/libSceLibcInternal.md b/docs/dev/debt/libSceLibcInternal.md index 0dea6b261391..552e2b17fb8c 100644 --- a/docs/dev/debt/libSceLibcInternal.md +++ b/docs/dev/debt/libSceLibcInternal.md @@ -336,6 +336,7 @@ The named entries below use provider-specific NID aliases to avoid interposing h - [fstatvfs](../../../core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp) (libSceLibcInternal) converts `_fstatfs` to the 88-byte `struct statvfs` as FreeBSD 9.2's `sfs2svfs` does (`f_bsize` from the transfer size, `f_frsize` from the block size, `f_favail` equal to `f_ffree`, `f_fsid` 0, `ST_RDONLY` and `ST_NOSUID` only). Differences: `f_namemax` is the `statfs` value, not `fpathconf(_PC_NAME_MAX)`; negative `f_bavail` and `f_ffree` wrap to unsigned without `EOVERFLOW`, as the same-width copy in FreeBSD does; inode counts are 0 on Windows, inherited from `_fstatfs`; a null output returns `EFAULT` after the descriptor is validated, where FreeBSD would fault. Layout and conversion are unverified against the PS5 library (PS5MC imports `fstatvfs` but was not run) - [posix_spawn and posix_spawnp](../../../core/libs/prx/libSceLibcInternal/Spawn.cpp) (libSceLibcInternal) have unverified console sandbox and error equivalence. POSIX errors missing from the shared translator fall back to `EIO`. Only converted programs under `/app0/` run (`/app0/eboot.bin` uses the running image). Windows open/duplication actions redirect only descriptors 0 to 2; nonzero attribute flags throw. POSIX hosts implement only `POSIX_SPAWN_RESETIDS` and `POSIX_SPAWN_SETPGROUP`; other flags throw. Guest IDs are host IDs, a null `argv` returns `EFAULT`, and null or uninitialized objects throw where FreeBSD dereferences them. A null `envp` inherits the parent environment. `posix_spawnp` follows FreeBSD 11 `_execvpe` path search; PPSA99305 reaches it while SDL searches for `zenity` - [getopt, getopt_long](../../../core/libs/prx/libSceLibcInternal/Getopt.cpp) (libSceLibcInternal) follow FreeBSD 11 [getopt.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdlib/getopt.c) and [getopt_long.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdlib/getopt_long.c) with `GNU_COMPATIBLE`: `getopt` does not permute, `getopt_long` permutes unless `POSIXLY_CORRECT` is set in the guest environment or the option string starts with `+`, and the exported `opterr`, `optind`, `optopt`, `optreset` and `optarg` start at 1, 1, 0, 0 and null. Warnings go to the guest's current `stderr` prefixed with `__progname`, where FreeBSD's `warnx` keeps the `stderr` of its first call. A null `getopt` option string, a null argument vector or argument, a negative `optind` and an `optind` moved inside a pending permutation throw where FreeBSD faults. `getopt_long_only` is not exported. That the console's `libSceLibcInternal` uses this FreeBSD code is unverified +- [num_get and num_get get](../../../core/libs/prx/libSceLibcInternal/NumGet.cpp) (libSceLibcInternal): the `do_get` slot order is inferred, not read from the console's `libSceLibcInternal.sprx`, and no title was seen calling these 22 exports. The slots follow the declaration order of [microsoft/STL xlocnum](https://github.com/microsoft/STL/blob/219514876ea86491de191ceaa88632616bbc0f19/stl/inc/xlocnum#L365-L636) (bool, unsigned short, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, void*), the order `NumPutVtable` uses for `num_put`, not that of the standard synopsis. Each `get` returns `do_get` through the facet's vtable and passes the `istreambuf_iterator` arguments as an opaque 16-byte value. No libc or libSceLibcInternal `num_get` facet implements `do_get`, so these reach only a facet the title provides - [_ZNSt4_PadD1Ev](../../../core/libs/prx/libSceLibcInternal/Pad.cpp) (libSceLibcInternal, NID `XyJPhPqpzMw`) is the complete-object destructor of `_Pad`, which has no virtual bases, so the [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#definitions) makes it do the same work as the base-object `D2` destructor; it runs the `libc` export of that `D2` name, which unlocks and destroys the pad's mutex and condition and throws from a thread that does not hold the mutex. The console's `libSceLibcInternal.sprx` was not read and no title was seen calling it - [posix_spawnattr_getflags, getpgroup, getschedparam, getschedpolicy, getsigdefault, getsigmask, setpgroup, setschedparam, setschedpolicy and setsigmask](../../../core/libs/prx/libSceLibcInternal/Spawn.cpp) (libSceLibcInternal) read and write the 0x30-byte attribute object at the offsets of the console's `libSceLibcInternal.sprx` (SDK 4.5x build of `J03950001`, 0x8D860 to 0x8D910: flags at 0, process group at 4, scheduling parameter at 8, policy at 0xC, default and masked signal sets at 0x10 and 0x20), which never fail there and return 0; the layout matched on a PS5 (firmware 13.60). Uninitialized attributes and null pointers, which the console dereferences, throw as the existing setters do - [Optional PID outputs in posix_spawn and posix_spawnp](../../../core/libs/prx/libSceLibcInternal/Spawn.cpp) (libSceLibcInternal) are unverified on the console; null PID outputs follow [FreeBSD 11.4](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/gen/posix_spawn.c#L279-L287), creating a child that can still be reaped with `waitpid` @@ -434,17 +435,6 @@ The named entries below use provider-specific NID aliases to avoid interposing h - [_ZNKSt7collateIwE7compareEPKwS2_S2_S2_](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `n-3HFZvDwBw` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7collateIwE7do_hashEPKwS2_](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `cWaCDW+Dc9U` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7collateIwE9transformEPKwS2_](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `81uX7PzrtG8` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERPv](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `my9ujasm6-0` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERb](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `OWO5cpNw3NA` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERd](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `mAwXCpkWaYc` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERe](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `wUCRGap1j0U` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERf](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `6RGkooTERsE` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERj](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `N1VqUWz2OEI` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERl](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `I2UzwkwwEPs` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERm](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `2bfL3yIBi5k` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERt](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `gozsp4urvq8` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERx](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `4hiQK82QuLc` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERy](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `eZfFLyWCkvg` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERPv](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `VKdXFE7ualw` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERb](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `SmtBNDda5qU` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERd](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `bNQpG-eKogg` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. @@ -459,17 +449,6 @@ The named entries below use provider-specific NID aliases to avoid interposing h - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8_GetffldEPcRS3_S6_RSt8ios_basePi](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `4+y8-2NsDw0` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE8_GetifldEPcRS3_S6_NSt5_IosbIiE9_FmtflagsERKSt6locale](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `G9LB1YD5-xc` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE9_GetffldxEPcRS3_S6_RSt8ios_basePi](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `J-0I2PtiZc4` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERPv](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `zomvAQ5RFdA` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERb](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `vW-nnV62ea4` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERd](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `+hjXHfvy1Mg` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERe](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `xLZr4GJRMLo` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERf](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `2mb8FYgER+E` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERj](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `Y3hBU5FYmhM` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERl](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `-m2YPwVCwJQ` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERm](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `94ZLp2+AOq0` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERt](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `bZ+lKHGvOr8` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERx](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `cG5hQhjFGog` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. -- [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERy](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `banNSumaAZ0` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERPv](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `BNZq-mRvDS8` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERb](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `wEU8oFtBXT8` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only. - [_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE6do_getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateERd](../../../core/libs/prx/libSceLibcInternal/Err.cpp) (libSceLibcInternal) - NID `t39dKpPEuVA` from the PS5 3.20 export inventory; prototype and behavior are unverified. Declaration is for import resolution only.