From 02c6971e02b118b1f79e1bfbb887a192fa770e67 Mon Sep 17 00:00:00 2001 From: LeandroLP23 Date: Sat, 31 Oct 2026 18:59:56 +0100 Subject: [PATCH] docs(debt): correct stale and contradictory entries Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libkernel/System/src/Process.cpp | 1 - docs/dev/TechnicalDebt.md | 2 +- docs/dev/debt/libSceAgcDriver.md | 2 +- docs/dev/debt/libSceAudioOut.md | 2 +- docs/dev/debt/libSceCommonDialog.md | 4 ---- docs/dev/debt/libSceHmd2.md | 2 +- docs/dev/debt/libSceLibcInternal.md | 1 - docs/dev/debt/libSceNetCtl.md | 1 + docs/dev/debt/libSceNpCommon.md | 1 - docs/dev/debt/libSceRegMgr.md | 2 +- docs/dev/debt/libSceSsl.md | 2 +- docs/dev/debt/libSceSystemService.md | 5 ++--- docs/dev/debt/libc.md | 5 +---- docs/dev/debt/libkernel.md | 2 +- docs/dev/debt/libkernel_sys.md | 4 ++-- docs/dev/debt/relinker.md | 2 +- 16 files changed, 14 insertions(+), 24 deletions(-) diff --git a/core/libs/prx/libkernel/System/src/Process.cpp b/core/libs/prx/libkernel/System/src/Process.cpp index d5e02ed07e..77fac5fe43 100644 --- a/core/libs/prx/libkernel/System/src/Process.cpp +++ b/core/libs/prx/libkernel/System/src/Process.cpp @@ -577,7 +577,6 @@ bool ExecWindowsImage(const std::filesystem::path& target) { extern "C" { -// unknown data const char* __progname_nid_postfix = "eboot.bin"; static char* emptyEnvironment[1]; char** environ_nid_postfix = emptyEnvironment; diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index ee801b4795..f6ccd77e75 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -12,7 +12,7 @@ Entries about one library or component are in [debt](debt/), one file per librar ### Silent stubs -Throughout the project, every function at every stage either **does exactly what it's supposed to or throws an exception**. Everywhere... except: +Throughout the project, every function at every stage either **does exactly what it's supposed to or throws an exception**. The exceptions are listed under **Silent stubs** in each library's file in [debt](debt/). ### Unknown function info diff --git a/docs/dev/debt/libSceAgcDriver.md b/docs/dev/debt/libSceAgcDriver.md index 8540c1a932..de299059ac 100644 --- a/docs/dev/debt/libSceAgcDriver.md +++ b/docs/dev/debt/libSceAgcDriver.md @@ -132,7 +132,7 @@ - [PS4 (GCN) multisampled color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver, PS4) - a GCN color target with 2, 4 or 8 samples and as many fragments (CB_COLOR_ATTRIB NUM_SAMPLES and NUM_FRAGMENTS) becomes a host-resident multisampled target, as on the AGC path: its samples stay on the host. With FAST_CLEAR or COMPRESSION set, its CMASK (CB_COLOR_CMASK, CMASK_SLICE tile max + 1 times 128 bytes) is taken for fast clears; FMASK contents are not modeled. Fewer fragments than samples (EQAA), more than 8 samples and a single-sample fast clear throw. A CB metadata pass (FMASK decompress or resolve) over a GCN target may cover only its visible rows and columns: the extent the viewport and scissor cover counts when the tile mode pads it to the target's size. None of it is checked on a console. - [PS4 (GCN) array layer banks](../../../core/libs/prx/libSceAgcDriver/Graphics/include/TextureTiling.hpp) (libSceAgcDriver, PS4) - not checked on a console. The bank of each layer of a tiled 2D array is rotated by (banks / 2 - 1) times the layer index outside the PRT modes, XORed in as AMD's address library and shadPS4 (`tiling.comp`, 0614ce324be0) do; fpPS4 (`ps4_tiling.pas`, 04cefd43e6fd) adds it to the bank instead. - [PS4 flips without a resident image](../../../core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp) (libSceAgcDriver, PS4) - a tiled flip with no resident image, such as one before the title draws into the buffer, is decoded on the CPU one texel at a time through `ColorTargetLayout::Offset`, about 116 ms at 1920x1080 ([measured on #9673](https://github.com/boykopovar/AnyPS5/pull/9673)). It then takes the same upload, HDR10 scaler, frame dump and screenshot path as a linear buffer. -- [PS4 render targets and display buffers](../../../core/libs/prx/libSceAgcDriver/Execution/src/DisplayBuffer.cpp) (libSceAgcDriver, PS4) - a tiled PS4 display buffer is read as Display2DThin with rows padded to 128 elements, as shadPS4's `image_info.cpp` does. A PS4 render target spans its surface padded to whole macro tiles (1920x1080 at 32 bits is 1920x1088), the display buffer is its top-left corner, and a texture over that corner with the same pitch, tiling and texel size is a [GPU copy](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) of it. A PS4 `DB_Z_INFO` names a GB_TILE_MODE index; the depth image stays on the GPU and HTILE is kept, as for the PS5. shadPS4 (`image_info.cpp`, 0614ce324be0) rounds the width of a tiled display buffer up to a multiple of 128 itself, whereas `DisplayBufferSize` requires the pitch to be one already. A PS4 depth target spans `DB_DEPTH_SIZE`; a smaller level-0 depth view reads a plane copy of its corner, a stencil one guest memory. +- [PS4 render targets and display buffers](../../../core/libs/prx/libSceAgcDriver/Execution/src/DisplayBuffer.cpp) (libSceAgcDriver, PS4) - a tiled PS4 display buffer is read as Display2DThin with rows padded to 128 elements, as shadPS4's `image_info.cpp` does. This path is not reached yet: [VideoOut](../../../core/libs/prx/libSceVideoOut/src/Buffer.cpp) refuses a PS4 buffer whose tiling is not linear before it gets here. A PS4 render target spans its surface padded to whole macro tiles (1920x1080 at 32 bits is 1920x1088), the display buffer is its top-left corner, and a texture over that corner with the same pitch, tiling and texel size is a [GPU copy](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) of it. A PS4 `DB_Z_INFO` names a GB_TILE_MODE index; the depth image stays on the GPU and HTILE is kept, as for the PS5. shadPS4 (`image_info.cpp`, 0614ce324be0) rounds the width of a tiled display buffer up to a multiple of 128 itself, whereas `DisplayBufferSize` requires the pitch to be one already. A PS4 depth target spans `DB_DEPTH_SIZE`; a smaller level-0 depth view reads a plane copy of its corner, a stencil one guest memory. - [PS4 pattern fill](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/BufferFill.cpp) (libSceAgcDriver, PS4) - the PS4 build of the pattern-fill compute kernel seen in Limbo (CUSA01664), with user data s[4:7] a 32-bit UINT source, s[8:11] the 32-bit UINT destination and s[12:15] a control record of count and index mask, where thread i stores source[i & mask], runs as a GPU fill when the mask is 0, a single repeated dword; other masks run the kernel, since running Limbo's two-dword clears of a 64-bit target as fills made its gameplay advance more slowly per frame. The kernel is recognized by its code, not by an SDK symbol. ### Functional diff --git a/docs/dev/debt/libSceAudioOut.md b/docs/dev/debt/libSceAudioOut.md index 740c6ba732..a59044961c 100644 --- a/docs/dev/debt/libSceAudioOut.md +++ b/docs/dev/debt/libSceAudioOut.md @@ -76,7 +76,7 @@ - [sceAudioOut2Set3DLatency](../../../core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp) (libSceAudioOut) - the two 32-bit arguments and selector validation match the system library: selector 0 accepts outputs 0 through 2; selector 255 accepts outputs 1 and 2. No third latency argument exists. The host has no system 3D rendering stage, so the call still does not apply latency and does not reproduce the system initialization and output-availability checks. - [sceAudioOut2MasteringInit and sceAudioOut2MasteringInitEx](../../../core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp) (libSceAudioOut) - the initialized flag and the flag checks follow the PS5 13.60 module (0x22360): a repeated initialization returns 0, other flags return `0x80268201`, and InitEx also accepts bit 31, which the console passes to the audio server as a mastering mode. Nothing is sent to an audio server. PPSA01289 calls Init twice before Term twice; by the module its second Term gets `0x80268203`, and the title only logs a non-zero result - [sceAudioOut2MasteringGetState and sceAudioOut2MasteringSetParam](../../../core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp) (libSceAudioOut) - the state layout, the states ids 1 (default) and 2 (V2), the descriptor ids `0x01010001`, `0x01020001` and `0x01010003` and the error `0x80268204` follow [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp), not a console measurement. GetState zeroes the states and writes the two descriptors; with no mastering stage the compressor and limiter values stay zero. SetParam accepts any parameter set and records nothing, as KytyPS5 does. The checks before them follow the PS5 13.60 module: both return `0x80268203` before mastering is initialized, GetState returns `0x8026800C` for a null state, SetParam returns `0x80268201` for a null parameter and `0x80268205` for flags above 1. The console's checks of `output` and `user` are not reproduced; both are ignored -- [sceAudioOut2SetSystemDebugState](../../../core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp) (libSceAudioOut) - records the debug state id in the trace and returns 0, as [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp) does; the host has no system mix to apply it to. Id `0x20` with a 4-byte param throws. Not measured on a console +- [sceAudioOut2SetSystemDebugState](../../../core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp) (libSceAudioOut) - accepts only debug state 1 with an 8-byte param: it records the id in the trace and returns 0, as [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp) does, since the host has no system mix to apply it to. Any other id or size returns `0x80268001`, a null param `0x8026800C` and a call before initialization `0x80268006`; id `0x20` with a 4-byte param, and state 1 with a null inner param, throw. Not measured on a console - [sceAudioOut2GetSpeakerArrayCoefficients](../../../core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp) (libSceAudioOut) - validates the handle and the coefficient count like the ambisonics call, then writes the front pair at full gain and silence for every other speaker, ignoring the position, spread, height awareness and downmix spread radius: [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp) and [prosper](https://github.com/mattias800/prosper/blob/main/prosper/src/hle/audio/hle_audio.cpp) both return that pair. The console's VBAP gains over the array's directions are not measured - [sceAudioOutSetMixLevelPadSpk](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - no emulator applies the level: [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/0614ce324be092791b758d79f93d9f1ca5b10a81/src/core/libraries/audio/audioout.cpp#L769-L808) (PS4) checks and stores it, [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6fddd1ab033e7980cd356d14c964905/src/audio/ps4_libsceaudioout.pas#L474-L488) (PS4) ignores it and KytyPS5 (PS5) has no such function anywhere in its repository; it is assumed to be a linear gain on the port's own output, and the -9 dB default (11626) is applied to every pad speaker port, including those of titles that never call the function - [sceAudioOutGetLastOutputTime](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - signature and behaviour taken from the [shadPS4](https://github.com/shadps4-emu/shadPS4) and [fpPS4](https://github.com/red-prig/fpPS4) reimplementations of the PS4 library, not confirmed on a PS5 title: the time is the process time at which `sceAudioOutOutput` or `sceAudioOutOutputs` accepted the port's last block, not the time the block reached the device. [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/0614ce324be092791b758d79f93d9f1ca5b10a81/src/core/libraries/audio/audioout.cpp#L183-L187) (PS4) stamps it after its output thread hands the block on and [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6fddd1ab033e7980cd356d14c964905/src/audio/ps4_libsceaudioout.pas#L695-L804) (PS4) after its blocking device write; AnyPS5 once it has queued the block to a host device or paced a port without one, which can be earlier than both; KytyPS5 (PS5) has no such function diff --git a/docs/dev/debt/libSceCommonDialog.md b/docs/dev/debt/libSceCommonDialog.md index 43d2199a17..65d711c18b 100644 --- a/docs/dev/debt/libSceCommonDialog.md +++ b/docs/dev/debt/libSceCommonDialog.md @@ -19,10 +19,6 @@ | `Unknown` | `txNJzxX6yrA` | | `Unknown` | `yxjgDvqUbGQ` | -### Silent stubs - -- [libSceCommonDialog](../../../core/libs/prx/libSceCommonDialog/Export.cpp) - ### Unknown function info - 14 additional pending imports in [InventoryExports.cpp](../../../core/libs/prx/libSceCommonDialog/InventoryExports.cpp) are listed in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCommonDialog.c). Their signatures and behavior are unverified; each uses the no-parameter unknown-signature convention and throws through `NotImplemented_nid_no_patch`, for import resolution only. diff --git a/docs/dev/debt/libSceHmd2.md b/docs/dev/debt/libSceHmd2.md index 48662531da..f5206bc5a2 100644 --- a/docs/dev/debt/libSceHmd2.md +++ b/docs/dev/debt/libSceHmd2.md @@ -101,7 +101,7 @@ - [Hmd2SlotUpTo2ThenError1003](../../../core/libs/prx/libSceHmd2/Export.cpp) (libSceHmd2) - before `sceHmd2Initialize` the console returns `0x8a721003` for a first argument of 0 to 2 and `0x8a720009` for 3 to 5, 8, 16, 255 and -1; the other arguments are not looked at: `FRoSjceDv10`. Measured from a payload process on firmware 13.60 (probes `hmd2n` and `hmd2x`); the meaning of the arguments and the behaviour after initialization are not measured, and the handler throws once `sceHmd2Initialize` has succeeded - [Hmd2SlotUpTo2CheckSecondThenError002C](../../../core/libs/prx/libSceHmd2/Export.cpp) (libSceHmd2) - before `sceHmd2Initialize` the console returns `0x8a72002c` for a first argument of 0 to 2 and `0x8a720009` for 3 to 5, 8, 16, 255 and -1; a null second argument returns `0x8a720008` even with an invalid first argument: `wQ44gBwBw44`. Measured from a payload process on firmware 13.60 (probes `hmd2n` and `hmd2x`); the meaning of the arguments and the behaviour after initialization are not measured, and the handler throws once `sceHmd2Initialize` has succeeded - [Hmd2IndexZeroCheckSecondThenZero](../../../core/libs/prx/libSceHmd2/Export.cpp) (libSceHmd2) - before `sceHmd2Initialize` the console returns 0 for a first argument of 0 and `0x8a72100f` for 1 to 5, 8, 16, 255 and -1; a null second argument returns `0x8a720008` even with a nonzero first argument. Its third to sixth arguments answered `0x8a72100f` when null with a nonzero first argument, which does not separate them from the first-argument check, so they are not looked at: `wiv8+7ogrq0`. Measured from a payload process on firmware 13.60 (probes `hmd2n` and `hmd2x`); the meaning of the arguments and the behaviour after initialization are not measured, and the handler throws once `sceHmd2Initialize` has succeeded -- [FBUEhH9tQ1A](../../../core/libs/prx/libSceHmd2/Export.cpp) (libSceHmd2) - left unimplemented: before initialization it writes the 32-bit value 9 through its second argument and returns 0 when its first argument points at zeroed memory, but returns `0x8a720001` without writing when that memory holds 0xAA bytes, and its fourth to sixth arguments answer `0x8a720001` when null, so the first argument is an in-out structure whose fields are not known +- [FBUEhH9tQ1A](../../../core/libs/prx/libSceHmd2/InventoryExports.cpp) (libSceHmd2) - left unimplemented: before initialization it writes the 32-bit value 9 through its second argument and returns 0 when its first argument points at zeroed memory, but returns `0x8a720001` without writing when that memory holds 0xAA bytes, and its fourth to sixth arguments answer `0x8a720001` when null, so the first argument is an in-out structure whose fields are not known - [libSceHmd2 gaze exports](../../../core/libs/prx/libSceHmd2/Export.cpp) - gaze argument registers and input/output directions are recovered. Result queries take a 16-byte size/handle parameter. The 24-byte foveated result contains size, status and a three-float direction; its trailing four bytes are untouched. The 56-byte full result still needs its eye-field semantics. Object selection uses a 120-byte parameter and 56-byte result whose fields remain incomplete. Its initialization and memory-query structures are recovered, including the 32-bit object count and memory size, memory pointer and 64-bit alignment. Calibration data descriptors contain a pointer and signed 32-bit size; calibration status contains two 32-bit selectors and three floats. The underlying calibration blob formats remain incomplete. Raw gaze input is mutable. CalibrationPoint is three floats passed by value in two SIMD registers; SetIpdOffset takes a byte and a float. diff --git a/docs/dev/debt/libSceLibcInternal.md b/docs/dev/debt/libSceLibcInternal.md index 8ce9cc93ee..289afaea73 100644 --- a/docs/dev/debt/libSceLibcInternal.md +++ b/docs/dev/debt/libSceLibcInternal.md @@ -543,7 +543,6 @@ The named entries below use provider-specific NID aliases to avoid interposing h - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FDtento`, `_FErfc`, `_FHypot`, `_FLogpoly`, `_FPlsw`, `_FPmsw`, `_FPow`, `_FQuad` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FQuadph`, `_FRint`, `_FSincos`, `_FTan`, `_FTgamma`, `_FXp_addh`, `_FXp_addx`, `_FXp_invx` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FXp_ldexpx`, `_FXp_movx`, `_FXp_mulh`, `_FXp_mulx`, `_FXp_setn`, `_FXp_setw`, `_FXp_sqrtx`, `_FXp_subx`, `_Fac_tidy`, `_Fail_s` -- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Fgpos`, `_Fofind`, `_Fofree`, `_Fopen`, `_Foprep`, `_Frprep`, `_Fspos` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Fwprep`, `_Genld`, `_Gentime`, `_Getcloc`, `_Getctyptab`, `_Getdst`, `_Geterrno`, `_Getfld`, `_Getfloat`, `_Getgloballocale` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Getint`, `_Getpcostate`, `_Getpwcostate`, `_Getpwctrtab`, `_Getpwctytab`, `_Getstr`, `_Gettime`, `_Getzone`, `_Hypot` diff --git a/docs/dev/debt/libSceNetCtl.md b/docs/dev/debt/libSceNetCtl.md index ccfd443ff7..74a4e9b625 100644 --- a/docs/dev/debt/libSceNetCtl.md +++ b/docs/dev/debt/libSceNetCtl.md @@ -2,6 +2,7 @@ ### Unknown function info +- [sceNetCtlGetIfStat](../../../core/libs/prx/libSceNetCtl/Export.cpp) (libSceNetCtl) - the signature and 56-byte layout come from PPSA09030's call site and SharpProspero's `SceNetCtlIfStat`; the device kind is always 0, the byte counters are the host's totals over its up non-loopback hardware interfaces (not "since cleared"), and the not-connected result is assumed to match `sceNetCtlGetState` - [sceNetCtlScanIpcInt](../../../core/libs/prx/libSceNetCtl/Export.cpp) (libSceNetCtl) - argument registers and IPC transfer directions are recovered for the info, connection, scan, NAT, bandwidth and Wi-Fi queries. The connection configuration is 1464 bytes, scan options 88, BSSID output 96, scan info 112, IPv6 info 256, internal NAT info 196, bandwidth info 32, bandwidth-estimation info 28 and Wi-Fi info 48. Their field semantics still require the receiving service; incomplete declarations preserve this gap. Scan queries transfer a six-byte BSSID and use a 64-bit in/out buffer size. - [sceNetCtlGetInfo](../../../core/libs/prx/libSceNetCtl/Export.cpp) (libSceNetCtl) - answers from the host interface with an IPv4 address, preferring the default-route one: its address, netmask, gateway, MTU and first two IPv4 DNS servers. The device is always reported as wired, the link as connected, the IP configuration as DHCP and the HTTP proxy as off, and the Ethernet address is the one from `sceNetGetMacAddress`. A missing gateway or DNS server is `0.0.0.0`; the console value is unknown. The DHCP host name (12), PPPoE user name (13), HTTP proxy server (20) and Wi-Fi BSSID and SSID (5, 6) are empty strings and the other Wi-Fi codes (7-10) and the proxy port (21) are 0, as that configuration sets none of them; this follows [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/main/src/libs/network.cpp) and is not measured on hardware. One title (PPSA02225) calls code 12 at 0x1056f0f, 0xa0387f and 0xa26de5 and code 14 at 0x1056fa1; the meaning of the flag byte it checks is not shown. diff --git a/docs/dev/debt/libSceNpCommon.md b/docs/dev/debt/libSceNpCommon.md index f3888d8733..fb4a8f824a 100644 --- a/docs/dev/debt/libSceNpCommon.md +++ b/docs/dev/debt/libSceNpCommon.md @@ -64,7 +64,6 @@ The following nine state helpers in [PendingExportsRound7.cpp](../../../core/lib - [sce::np::NpCommId and sceNpUtilParseTitleId](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) (libSceNpCommon) - follow `libSceNpCommon.sprx` of firmware 13.60, read from disassembly, not measured on a console, with one change: `sceNpUtilParseTitleId` reads `titleId[9]` only when the string is at least 10 characters long, where the module reads it whatever the length, past the end of a shorter string. The parsed number is `strtol` of the text after the underscore, cut to a byte, as in the module. - [sce::np::NpTitleId Parse and ConstructFromTitleId](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) (libSceNpCommon) - drop the parsed `_NN` suffix and store `_00`, and accept only ASCII letters and digits, as `libSceNpCommon.sprx` of firmware 13.60 does, read from disassembly, not measured on a console. The module classifies characters with the C-locale `_Getpctype` table, so a locale with other letters is not covered. Parse takes exactly 12 characters, ConstructFromTitleId exactly 9, and a rejected title id leaves the object unchanged. - [The sce::np::NpTitleSecret constructor from data](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) (libSceNpCommon) - throws `std::invalid_argument` when the size is not 128, where `libSceNpCommon.sprx` of firmware 13.60 asserts `size == (128)` and panics, read from disassembly, not measured on a console. `SetSecretData` and `Equals` with a size return `0x80559E11` or false instead, and `ParseHex` / `BuildHex` return only the negative results of `sceNpStrnParseHex` / `sceNpStrBuildHex`, as the module does. -- [The sce::np::StreamReader and StreamWriter helpers](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) (libSceNpCommon) - follow `libSceNpCommon.sprx` of firmware 13.60, read from disassembly, not measured on a console: `ReadAll` halts through `sceNpPanic` when the stream reports more bytes than it was asked for; `WriteData` and `WriteFilledData` loop for as long as the stream accepts 0 bytes; `SkipAll` and `SkipData` add the reported count even when the read fails; positive stream and context results count as success and are returned as 0. - [sceNpCreateThread](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) always applies an explicit priority when one is given; the firmware picks between explicit and inherited scheduling from the title's compiled SDK version, which is not available here. - [sceNpCalloutStartOnCtx and sceNpCalloutStartOnCtx64](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) look for the callout in the queue before writing it and return `0x80558006` with the entry and the queue unchanged. Firmware 13.60, read from disassembly and not measured on a console, clears and fills the entry before it takes the lock and checks the queue, so restarting a queued callout returns the same error but drops every callout queued after it. - [sceNpCalloutTermCtx](../../../core/libs/prx/libSceNpCommon/Runtime.cpp) (libSceNpCommon) throws when a callout of the context calls it on that same context, because the worker thread cannot join itself and tearing the context down under it leaves the worker reading freed memory. What the console does is unknown and not measured. Closes when: measured on a PS5. diff --git a/docs/dev/debt/libSceRegMgr.md b/docs/dev/debt/libSceRegMgr.md index 953efe032a..7d0f22dfb0 100644 --- a/docs/dev/debt/libSceRegMgr.md +++ b/docs/dev/debt/libSceRegMgr.md @@ -17,7 +17,7 @@ ### Functional -- [Registry store](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - entries are queried through an in-memory process-local store without persistence. Callable prototypes for `sceRegMgrGetInt`, `sceRegMgrGetStr`, and `sceRegMgrGetBin` derive from [regmgr.h](https://github.com/ps5-payload-dev/regdump/blob/883524cc48c8497267ba7fc94ff0ac58880c4227/regmgr.h#L3713-L3729). Implemented getters return error codes for invalid parameters (`0x80820001`), missing keys (`0x80820002`), buffer sizing (`0x80820004`), and type mismatches (`0x80820006`) as unverified host implementation assumptions, as the cited regmgr.h does not establish error codes or validation behavior. Queries with non-positive keys `0` and `-1` take the missing-key path without key-range validation, pinning the unverified host assumption that non-positive keys are not rejected as invalid parameters. Setters (`sceRegMgrSetInt`, `sceRegMgrSetStr`, `sceRegMgrSetBin`, `sceRegMgrSetbin`), reset (`sceRegMgrResetVal`), and zero-length getter paths remain unimplemented throwing `NotImplemented_nid_no_patch` until callable contracts and error codes are supported by evidence. +- [Registry store](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - entries are queried through an in-memory process-local store without persistence, and nothing fills it yet: the setters throw, so a valid query always takes the missing-key path and the buffer-sizing and type-mismatch returns below cannot be reached. Callable prototypes for `sceRegMgrGetInt`, `sceRegMgrGetStr`, and `sceRegMgrGetBin` derive from [regmgr.h](https://github.com/ps5-payload-dev/regdump/blob/883524cc48c8497267ba7fc94ff0ac58880c4227/regmgr.h#L3713-L3729). Implemented getters return error codes for invalid parameters (`0x80820001`), missing keys (`0x80820002`), buffer sizing (`0x80820004`), and type mismatches (`0x80820006`) as unverified host implementation assumptions, as the cited regmgr.h does not establish error codes or validation behavior. Queries with non-positive keys `0` and `-1` take the missing-key path without key-range validation, pinning the unverified host assumption that non-positive keys are not rejected as invalid parameters. Setters (`sceRegMgrSetInt`, `sceRegMgrSetStr`, `sceRegMgrSetBin`, `sceRegMgrSetbin`), reset (`sceRegMgrResetVal`), and zero-length getter paths remain unimplemented throwing `NotImplemented_nid_no_patch` until callable contracts and error codes are supported by evidence. - [Unverified registry APIs](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - export names and NIDs for initial-value getters, version queries, region queries and conversions, error checks, control/backup routines, and `sceRegMgrNonSys*` variants are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/cf6eede3f6588d779664e01874638f09484324b7/libSceRegMgr.c) and [NID database](https://github.com/zecoxao/sce_symbols/blob/9620e03b2964dbf0cfc1cb143ab24a65125091de/aerolib.csv), but their callable contracts and runtime behavior remain unverified and retain `NotImplemented_nid_no_patch`. ### Unknown function info diff --git a/docs/dev/debt/libSceSsl.md b/docs/dev/debt/libSceSsl.md index d1b3d7a3d3..ca92bae14b 100644 --- a/docs/dev/debt/libSceSsl.md +++ b/docs/dev/debt/libSceSsl.md @@ -17,4 +17,4 @@ - This pending declaration has an unverified signature and behavior; it is a parameterless import-resolution declaration and throws through `NotImplemented_nid_no_patch`: [`sceSslSetServerName`](../../../core/libs/prx/libSceSsl/Export.cpp). ### Functional -- [System roots for HTTP](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - `SslTrustSystemRoots_nid_no_patch` makes one connection also trust the system CA list, read once per process from `//common/cert/CA_LIST.cer`. It is parsed into a separate allocation pool, not charged to the title's `sceSslInit` pool, and linked after the context's own authorities; `sceSslGetCaList` and `sceSslGetCaCerts` do not report it. A missing, empty or certificate-free list throws and names the path instead of trusting nothing. Only the HTTP libraries call it: whether a bare libSceSsl connection on the console trusts the system roots is not measured, so `sceSslCreateConnection` alone keeps trusting only the context's authorities +- [System roots for HTTP](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - `SslTrustSystemRoots_nid_no_patch` makes one connection also trust the system CA list, read once per process from `//common/cert/CA_LIST.cer`. It is parsed into a separate allocation pool, not charged to the title's `sceSslInit` pool, and linked after the context's own authorities; `sceSslGetCaList` and `sceSslGetCaCerts` do not report it. A missing, empty or certificate-free list throws and names the path instead of trusting nothing. Only libSceHttp2 calls it: whether a bare libSceSsl connection on the console trusts the system roots is not measured, so `sceSslCreateConnection` alone keeps trusting only the context's authorities diff --git a/docs/dev/debt/libSceSystemService.md b/docs/dev/debt/libSceSystemService.md index 636f2afbdb..bab47ee119 100644 --- a/docs/dev/debt/libSceSystemService.md +++ b/docs/dev/debt/libSceSystemService.md @@ -44,7 +44,6 @@ ### Silent stubs - [libSceSystemService](../../../core/libs/prx/libSceSystemService/Export.cpp) - `sceSystemServicePowerTick`, `sceSystemServiceReportAbnormalTermination`, `sceSystemServiceDisableMusicPlayer`, `sceSystemServiceReenableMusicPlayer`, `sceSystemServiceDisableMediaPlay` and `sceSystemServiceReenableMediaPlay` return success and do nothing: the host has no auto power-off timer to reset, no system crash reporter to notify, no system music player to pause or resume and no system media playback to disable. PPSA01521 calls `sceSystemServiceDisableMediaPlay` during start-up, and its wrappers for both pass no arguments -- [sceSystemServiceLaunchWebBrowser](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 launches no web browser, so the call fails and nothing is shown. RommPS PPSA76677 then tells the player to scan its QR code instead - [sceSystemServiceShowControllerSettings](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - returns success without showing the controller settings: AnyPS5 has no system UI to open. Cat Quest III (PPSA15065) imports it - [sceSystemServiceShowDisplaySafeAreaSettings](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - returns success without showing the display safe area settings dialog: AnyPS5 has no system UI to open. PPSA03332 imports it, and the no-argument signature is assumed: [Orbital](https://github.com/AlexAltea/orbital/blob/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/tools/ida/db_types.json) has `sceSystemServiceShowControllerSettings` but not this call - [sceSystemServiceOpenChallengeActivity](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - returns success without opening the challenge activity: AnyPS5 has no system UI to open. Cat Quest III (PPSA15065) imports it @@ -65,14 +64,14 @@ - [sceLncUtilGetAppLaunchedUser, sceSystemServiceGetAppLaunchedUser, sceShellCoreUtilGetUserFocus](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - for the running title's app ID they write the initial user, 0x10000000 (`USER_SERVICE_INITIAL_USER_ID`): `sceUserServiceGetInitialUser` reports that user as the one who started the title, and `sceUserServiceGetForegroundUser` reports it as the foreground user. A null user pointer returns 0x80940005 (0x80e30003 from `sceShellCoreUtilGetUserFocus`) before the app ID is looked at, as firmware 13.42's `libSceSystemService.sprx` does ([emulator run](https://github.com/boykopovar/AnyPS5/pull/10801#issuecomment-6403075212)). Another app ID throws, because the console's answer for it is unknown. The user is written as a 32-bit value, as the LncUtil process and status payloads entry says - [sceLncUtilIsAppSuspended, sceSystemServiceIsAppSuspended](../../../core/libs/prx/libSceSystemService/Export.cpp), [sceLncUtilIsSpeculativeLaunch](../../../core/libs/prx/libSceSystemService/PendingExports.cpp) (libSceSystemService) - for the running title's app ID they write false. The title that calls them is running, and AnyPS5 has no shell to suspend it. It was started from the host, not by `sceLncUtilLaunchApp`, so no `LncLaunchParam` asked for a speculative launch. A null output returns 0x80940005 before the app ID is looked at, as firmware 13.42's `libSceSystemService.sprx` does ([emulator run](https://github.com/boykopovar/AnyPS5/pull/10801#issuecomment-6403075212)). Another app ID throws, because the console's answer for it is unknown. Whether the console already reports a title as suspended while it handles its own suspend event is not known - [sceSystemServiceLaunchApp](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 runs one title and cannot start another, so every call throws without reading its arguments. The (title ID, null-terminated argv, launch parameters) signature follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L141-L148), whose `AppLauncher` Prospero Explorer (PPSA99109) and Prospero Multi Tools (PPSA99110) import it through and which passes a 0x20-byte launch context or null; the console's argument checks and errors are unknown -- [sceSystemServiceLaunchWebBrowser](../../../core/libs/prx/libSceSystemService/Export.cpp): the native export takes one URI argument. Null input, the 6015-byte length limit and supported scheme checks are recovered. The host still returns kernel `EOPNOTSUPP` for valid input; a missing browser service's native error is unresolved. +- [sceSystemServiceLaunchWebBrowser](../../../core/libs/prx/libSceSystemService/Export.cpp): the native export takes one URI argument. Null input, the 6015-byte length limit and supported scheme checks are recovered. The host still returns kernel `EOPNOTSUPP` for valid input, so no browser opens (RommPS PPSA76677 then tells the player to scan its QR code instead); a missing browser service's native error is unresolved. - [sceSystemServiceParamGetString](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the system name (parameter 6) is the fixed `PS5`, not the console's name. As in a payload process on a PS5 (firmware 13.60), the name is written NUL-padded to the whole buffer, and a buffer under 65 bytes, a null buffer or any other parameter returns `SYSTEM_SERVICE_ERROR_PARAMETER` without writing. Parameters 0 to 40, 100 to 110, 1000 to 1010, -1 and `INT_MAX` were tried there; the others are assumed to fail the same way. PPSA26344 at `0xA87935` passes parameter 6 with a 65-byte buffer - [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - console language numbers 0 to 29 follow the PS4 SDK enum in [OpenOrbis](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/blob/06fcf7fd108fa080035cdd3259ed22eb07e0508c/include/orbis/_types/sys_service.h#L54-L83) (21 Arabic). 30 (Ukrainian) is not in it and follows PPSA99505 ([Jelly5](https://github.com/02dnot/Jelly5/blob/552b866d89b2a58b27f7f7b0484dc743ce235526/app/src/app/i18n.cpp#L29-L60)) and PPSA99002 ([ProsperoLight](https://github.com/blackbearreloaded/ProsperoLight/blob/b708bbde3457bef1073a9ab6959957cb691e8e2f/include/i18n.hpp#L252-L309)), whose numbers agree with the enum. Not confirmed on a console, and neither title starts on `main` yet. Parameter 400 returns the same number as parameter 1: PPSA01325 asks for 400 first, asks for 1 when that fails, and uses either answer as an index into the same 31 languages; in the PS5 10.01 and 12.60 `libSceSystemService` modules parameter 400 reads the same registry value as parameter 1, without parameter 1's mapping of newer language numbers by SDK version, and returns 0x80a10003 when an imported check that is not identified returns 1; the 4.03 module has no parameter 400. Neither the mapping nor that error is modelled, and the parameter's name is not known. Without `ANYPS5_LANGUAGE` the language is English (United States); the date format and time format stay fixed - [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - `ANYPS5_LANGUAGE=auto` takes the console language from the host locale with the table in [LanguageLocale.hpp](../../../core/libs/prx/libSceSystemService/LanguageLocale.hpp). The table is a host-side convenience: nothing was measured on a console about which language a person of a given host locale would choose, and what a title does with the number is unmeasured too. The language numbers and names are those of the entry above ([OpenOrbis](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/blob/06fcf7fd108fa080035cdd3259ed22eb07e0508c/include/orbis/_types/sys_service.h#L54-L83) for 0 to 29). - [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - `auto` chooses where the console has no exact variant, and none of these choices is measured: a bare `pt` is Portuguese (Brazil) and a bare `es` Spanish (Spain); `en-GB`, `en-IE`, `en-AU` and `en-NZ` are English (United Kingdom) and every other English is English (United States); a bare `zh` is Chinese (Simplified) and `zh-TW`, `zh-HK`, `zh-MO` and the Hant script Traditional; `es-US` and the Latin American countries are Spanish (Latin America); the Portuguese-speaking territories outside Brazil are Portuguese (Portugal). A language the console has no entry for (Baltic and the other Slavic languages, Hebrew, Hindi, Catalan, Basque and Galician) gives English (United States) and is not mapped to a neighbouring language. - [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - `auto` reads the host language through `LC_ALL`, `LC_MESSAGES`, `LANG` and `LANGUAGE` on Linux, `GetUserDefaultLocaleName` on Windows (the user's regional-format locale, not the list of display languages) and `CFLocaleCopyPreferredLanguages` on macOS. Only the Linux source has run, with injected and real environments and no non-English host; the Windows and macOS sources are not built or run. The resolver is inline, so a library that carries its own copy (a separate DLL on Windows) resolves the host again and can print its own fallback line; its answer is the same. - [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - parameters 1 to 5, 100 to 111, 200 to 213, 300 and 400 answer (see the integer system parameters entry); every other parameter, and a null value pointer, returns 0x80A10003 without writing the value. Inside a retail title on a PS5 (firmware 13.40, measured 2026-10-19 through ptrace remote calls in the game process) parameters 0, 6, 7 (game parental level), 8 to 20, 401, 999, 1000 (enter button assignment) and 1001 to 1008 returned 0x80A10003, as did a null value pointer; 1 to 5 and 400 answered, and 100 answered the value 0. A sweep of parameters 0 to 2048 in the same way on 2026-10-23 also found 101 to 111, 200 to 213 and 300 answering, each writing 4 bytes; every other parameter, and a null value pointer for 100 to 111, returned 0x80A10003 and left the value as it was. One title (PPSA13356, call at 0xAF350) asks for parameter 1 and does not read the result. -- [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the time zone (parameter 4) and summer time (parameter 5) follow the host's local time zone at the moment of the call. Titles compute the local time as UTC plus the time zone in minutes plus 60 minutes when summer time is 1 ([Apollo](https://github.com/bucanero/apollo-ps4/blob/252a9d5a187c463994263009851a179f4f910c49/source/exec_cmd.c#L70-L92), [GoldHEN's frame logger](https://github.com/GoldHEN/GoldHEN_Plugins_Repository/blob/6c3a06f53d9caebadfb0aeed9bb94119012010a7/plugin_src/frame_logger/source/main.c#L60-L82), and [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/413d2e3518fb435f40971d238fe0ecae7ee551da/src/SharpProspero/Platform/SystemParameters.cs#L75-L79) calls them the offset from UTC in minutes and whether summer time is in effect), so the time zone is the host's current offset east of UTC less the summer time shift while summer time is in effect: 60 minutes on Linux, and on Windows the C runtime's own summer time bias (`_get_dstbias`), which is also what shifted its local time. For a host zone whose summer time is not one hour, Linux keeps the sum right and the standard offset wrong, and Windows the opposite; how the console reports such a zone is unknown. libkernel's `sceKernelConvertUtcToLocaltime`, `sceKernelConvertLocaltimeToUtc` and `sceKernelGettimezone` still use UTC +- [sceSystemServiceParamGetInt](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the time zone (parameter 4) and summer time (parameter 5) follow the host's local time zone at the moment of the call. Titles compute the local time as UTC plus the time zone in minutes plus 60 minutes when summer time is 1 ([Apollo](https://github.com/bucanero/apollo-ps4/blob/252a9d5a187c463994263009851a179f4f910c49/source/exec_cmd.c#L70-L92), [GoldHEN's frame logger](https://github.com/GoldHEN/GoldHEN_Plugins_Repository/blob/6c3a06f53d9caebadfb0aeed9bb94119012010a7/plugin_src/frame_logger/source/main.c#L60-L82), and [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/413d2e3518fb435f40971d238fe0ecae7ee551da/src/SharpProspero/Platform/SystemParameters.cs#L75-L79) calls them the offset from UTC in minutes and whether summer time is in effect), so the time zone is the host's current offset east of UTC less the summer time shift while summer time is in effect: 60 minutes on Linux, and on Windows the C runtime's own summer time bias (`_get_dstbias`), which is also what shifted its local time. For a host zone whose summer time is not one hour, Linux keeps the sum right and the standard offset wrong, and Windows the opposite; how the console reports such a zone is unknown. - [sceSystemServiceInitializePlayerDialogParam](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - a null param throws: what the console does with it is not measured. The console run in [prosper](https://github.com/mattias800/prosper/blob/40d95db32efe1ad00106a5b9a84e018fffa9ecff/prosper/tests/data/console_oracle/nethttp.golden.tsv#L46) shows only the 0x40 bytes written (size 0x40, user ID -1 at 0xC, zeros), so the field names and the mode and target account fields follow [SharpProspero's struct](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L637-L655), and the `void` return [its declaration](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L419-L426); the console left 0x800693020 in `rax`, not an SCE error code. Closes when: the null case is measured on a PS5 - [sceLncUtilBlockAppSuspend, sceLncUtilUnblockAppSuspend](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 never suspends the title, so a block changes nothing. An unblock with no block left returns `SCE_KERNEL_ERROR_EBUSY` and changes nothing, before it reads the reason, as in [BunnyFl's measurements](https://github.com/boykopovar/AnyPS5/pull/9586#issuecomment-6362292920) of firmware 13.42's library. A null reason still throws `NotImplemented_nid_no_patch` in `sceLncUtilBlockAppSuspend`, where the library reads the reason only for a log line written below SDK 2.50 or with capability bit 62, a path that is not measured, and in an unblock while a block is held, where the library faults after lowering the count - [sceShellCoreUtil and sceLncUtil status queries](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - a null output throws `NotImplemented_nid_no_patch` in `sceShellCoreUtilGetSocialScreenStatus`, where the library writes through it and faults, and in `sceShellCoreUtilIsEyeToEyeDistanceAdjusted`, whose answer comes from a service that is not measured, as does a user ID other than `USER_SERVICE_INITIAL_USER_ID` in both eye-to-eye queries (as in `sceMoveOpen`). The other null outputs follow [BunnyFl's measurements](https://github.com/boykopovar/AnyPS5/pull/9586#issuecomment-6362292920) of firmware 13.42's library: 0x80e30003 from the three `sceShellCoreUtil` `Get*Status` getters and, by forwarding, `sceSystemServiceGetRemoteplayStatus`, and 0x80940005 from `sceLncUtilIsPs2Emu` diff --git a/docs/dev/debt/libc.md b/docs/dev/debt/libc.md index bcdadd868a..d5964dcc63 100644 --- a/docs/dev/debt/libc.md +++ b/docs/dev/debt/libc.md @@ -90,7 +90,7 @@ - [srandomdev](../../../core/libs/prx/libc/src/Random.cpp) (libSceLibcInternal, implemented in libc) is not verified against the console. The firmware 3.20 [export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibcInternal.c) names NID `a2MOZf++Wjg`; it follows FreeBSD 11 [random.c](https://github.com/freebsd/freebsd-src/blob/4ab2e064d7950be84256d671a7ae93f87cc6aa36/lib/libc/stdlib/random.c), filling every active generator word from host OS entropy instead of `KERN_ARND`, then resetting additive feedback positions without warming up. An entropy failure throws rather than leaving `sysctl`'s failure unchecked. Calls share the generator lock. - [stdc_count_ones_uc, us, ui, ul and ull](../../../core/libs/prx/libc/src/IntegerBuiltins.cpp) (libc) have not been measured on a console. Their unsigned 8/16/32/64/64-bit arguments and count result follow PPSA03671 v01.001.005's bundled libc.prx, read from disassembly and run directly on a Windows host; the ul argument remains 64-bit on Windows. - [stdc_leading_ones_uc, us, ui, ul and ull; stdc_trailing_ones_uc, us, ui, ul and ull](../../../core/libs/prx/libc/src/IntegerBuiltins.cpp) (libc) have not been measured on a console. Their unsigned 8/16/32/64/64-bit arguments, all-ones results and leading/trailing one counts follow PPSA03671 v01.001.005's bundled libc.prx, read from disassembly and run directly on a Windows host; ul remains 64-bit on Windows. -- [Integer compiler-rt builtins](../../../core/libs/prx/libc/src/IntegerBuiltins.cpp) (libc) - the console traps in `__divsi3`, `__modsi3` and the 64- and 128-bit divisions on a zero divisor (`div`) and in `__negv*`, `__absv*` and `__mulv*` on overflow (an abort helper, then `ud2`); these throw instead. As in the `libc.prx` bundled with PPSA08427 (disassembly), `__addv*` and `__subv*` wrap without an overflow check, and `__udivsi3`, `__umodsi3` and `__udivmodsi4` divide in software, giving a quotient of 0 and the dividend as remainder for a zero divisor; `__clzdi2` and `__ctzdi2` of 0 return 32 and `__clzti2` and `__ctzti2` of 0 return 64 +- [Integer compiler-rt builtins](../../../core/libs/prx/libc/src/IntegerBuiltins.cpp) (libc) - the console traps in `__divsi3`, `__modsi3` and the 64- and 128-bit divisions on a zero divisor (`div`) and in `__negv*`, `__absv*` and `__mulv*` on overflow (an abort helper, then `ud2`); these throw instead. The 128-bit `__udivti3` (also re-exported by libSceAmpr), `__umodti3` and `__modti3` are in [RuntimeSupport.cpp](../../../core/libs/prx/libc/src/RuntimeSupport.cpp). As in the `libc.prx` bundled with PPSA08427 (disassembly), `__addv*` and `__subv*` wrap without an overflow check, and `__udivsi3`, `__umodsi3` and `__udivmodsi4` divide in software, giving a quotient of 0 and the dividend as remainder for a zero divisor; `__clzdi2` and `__ctzdi2` of 0 return 32 and `__clzti2` and `__ctzti2` of 0 return 64 - [qsort](../../../core/libs/prx/libc/src/FileAndHeap.cpp) (libc) follows the `libc.prx` that titles ship, read from disassembly of the copies of PPSA13934, PPSA07923 and PPSA05916 and checked by running them side by side (460,000 random sorts of 0 to 3,000 elements of 1 to 600 bytes, including forced heap sorts, gave the same comparator calls in the same order and the same result), not measured on a console. It is an introsort in the shape of Dinkumware's `std::sort`: from 33 elements a three-way partition around a median of three, or of nine from 42 elements with a step of `(n - 1) / 8 + 1`, looping on the larger side; a heap sort once a division budget, starting at n and cut to `budget / 2 + budget / 4` at each partition, reaches 0; and an insertion sort below 33 elements, which keeps elements that compare equal in their order. A null array or comparator returns at once, as there. A zero element size with 33 or more elements throws, where the console divides by zero - [qsort_r](../../../core/libs/prx/libc/src/FileAndHeap.cpp) (libc) follows FreeBSD 11 [qsort.c](https://github.com/freebsd/freebsd-src/blob/5ed7eb0d97ba4436218e810f61bd059acba984c2/lib/libc/stdlib/qsort.c): Bentley and McIlroy's quicksort, with insertion sort below 7 elements and after a partition pass that swaps nothing, so elements that compare equal end in FreeBSD's order and the comparator is called in the same sequence; `qsort_r` passes its thunk as the comparator's first argument. That the console's libc uses this FreeBSD code is unverified - [wcsncat_s and wcscat_s](../../../core/libs/prx/libc/src/Strings.cpp) (libc) refuse a copy as overlapping only when the written range `[dest + len1, dest + len1 + len2)` meets the read range `[src, src + len2)`. The rule comes from a static reading of the console's `wcsncat_s` in `libc.prx` (not run on a console); `wcscat_s` gets it through `wcsncat_s`, and its own console code was not read. `strncat_s` uses the same rule, as the PPSA31872 `libc.prx` code does. The narrow `strcat_s` also counts the terminator each range holds, as a payload process measured on a PS5 (firmware 13.60), where `strcat_s(d, 8, d + 1)` on `"ab"` is `EINVAL`, so it refuses some copies whose wide equivalent proceeds; the wide forms were run on a console, but not their overlap, so whether `wcscat_s(d, 8, d + 1)` on `"ab"` succeeds as the rule says is unmeasured. @@ -111,10 +111,7 @@ - [qsort_s](../../../core/libs/prx/libc/src/FileAndHeap.cpp) (libc) passes its context as the comparator's third argument, as FreeBSD 13's [`qsort_s`](https://github.com/freebsd/freebsd-src/blob/release/13.0.0/lib/libc/stdlib/qsort.c#L97-L127) (C11 Annex K) does. It returns `EINVAL` after calling the constraint handler when `n` or `es` exceeds `RSIZE_MAX`, or when `n` is not 0 and `a` or `cmp` is null; FreeBSD 11, which the rest of libc follows, has no `qsort_s`. Its sort is the console's `qsort` (checked in the same way), and a zero element size behaves as in `qsort`. The console's constraint handling is unverified; the Quake homebrew (#6698) imports it from its `libOSMesa.so.8` - [bsearch_s](../../../core/libs/prx/libc/src/BoundsChecking.cpp) (libc) accepts a zero element size: a nonempty search calls the comparator with the base address, while a zero count calls no comparator. Argument validation, callback counts, unchanged errno and lack of a constraint violation for zero stride match CPU-only executions of the converted PPSA03766 and PPSA07923 bundled `libc.prx` modules. Console execution, other SDK versions and the default constraint handler remain unverified. - [ungetwc, fgetwc, fputwc, fputws and fgetws](../../../core/libs/prx/libc/src/StandardStreams.cpp) (libc) - a null stream returns -1 (or null) with errno set to `EINVAL` (22), aligning with wide stream defensive parameter checks. In the `libc.prx` shipped by titles (measured on PPSA07923), the console does not validate the stream pointer and faults with an access violation on `ungetwc`, `fgetwc`, `fputwc`, `fputws` and `fgetws` when passed a null stream. -- [__udivti3](../../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc, re-exported by libSceAmpr) - the hardware traps on a zero divisor; this throws instead -- [__umodti3](../../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc) - the hardware traps on a zero divisor; this throws instead - [std::_Throw_C_error](../../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc) follows disassembly of a bundled PS5 `libc.prx`: maps 1 and 2 to generic error 35 (`resource_unavailable_try_again`), 3 to 16 (`device_or_resource_busy`), 4 to 22 (`invalid_argument`), and 5 to 1 (`operation_not_permitted`), throwing a guest `std::system_error` through the existing C++ error helper. Other values return without throwing. Other SDK versions have not been inspected -- [__modti3](../../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc) - the hardware traps on a zero divisor; this throws instead - [snprintf and vsnprintf](../../../core/libs/prx/libc/src/Formatting.cpp) (libc) accept any size up to `SIZE_MAX`, as a payload process on a PS5 (firmware 13.60) does. A null buffer with a nonzero size throws here, where the console writes through it, and a result longer than `INT_MAX` throws, which was not measured diff --git a/docs/dev/debt/libkernel.md b/docs/dev/debt/libkernel.md index 6aa42b9cdf..912b87287e 100644 --- a/docs/dev/debt/libkernel.md +++ b/docs/dev/debt/libkernel.md @@ -120,7 +120,7 @@ - [cfsetspeed](../../../core/libs/prx/libkernel/File/src/Terminal.cpp) (libkernel, NID `C1MQ6OaXRjo`) - console behavior and module/library versions are unverified. The prototype, uint32 speed and 44-byte termios layout (input speed at 36, output speed at 40) follow the public PS5 payload SDK [termios.h](https://github.com/ps5-payload-dev/sdk/blob/a7685ce8e97ce1f8a4f38253a41d54241c9124f1/include/freebsd/termios.h) and [sys/_termios.h](https://github.com/ps5-payload-dev/sdk/blob/a7685ce8e97ce1f8a4f38253a41d54241c9124f1/include/freebsd/sys/_termios.h). The module association follows its libkernel stub table and the NID rehashes to the aerolib name. Both speed fields accept every uint32 value and no flags or control characters change, as [FreeBSD 11.4 termios.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libc/gen/termios.c) does. No terminal I/O is performed. Null pointers throw where the reference dereferences them. - [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) - console standard-stream behavior is unverified. Regular files, directories and archived files at descriptors 0 to 2 use vnode readiness, including host redirection (`< file`, `> log.txt` or `2> log.txt`): they are readable and writable even at EOF. Other standard descriptors reaching the fallback use the console model: descriptor 0 is never reported readable and descriptors 1 and 2 are writable; reads from descriptor 0 still go to host stdin. `/dev/random` and `/dev/urandom` follow `randomdev_poll` for a seeded device under [`selscan`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1178-L1236), which asks once with the flags of every set the descriptor is in: in the read set they are readable and reported in no other set, and otherwise they are reported in the write and exception sets they were asked in. A regular file, a directory or a file read from app0.zar is always readable and writable and never in the exception set, as `vop_stdpoll` answers, on every host. Guest sockets and libSceNet sockets are polled. A kqueue is readable while one of its events is triggered and is never writable or in the exception set, as FreeBSD 11.4's [`kqueue_poll`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/kern_event.c#L1900-L1924) answers, on every host. Other descriptors are polled through the host on Linux, while on Windows pipes are checked every millisecond with the readiness test `poll` uses and any other descriptor throws. Dungeons (PPSA16064) selects on descriptor 0, and RetroArch (PPSA99169) selects on its web server's wake-up pipe next to its listening socket - [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) - a descriptor the socket poller reports as unknown is polled on the host instead of throwing (on Windows only a pipe, as above); an invalid host descriptor fails with `EBADF`, and mixed host and socket sets are polled in short alternating slices so neither side waits out the full slice alone. A descriptor that stops being a socket, a kqueue or a pipe during the wait fails the call with `EBADF` when it is closed and is selected again with the rest of the timeout when its number was reused, as FreeBSD 11.4's [`kern_select`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1129-L1140) looks every descriptor up again in each pass. A close that has already removed the descriptor from the guest's kqueue, pipe or file tables but not yet closed its host descriptor is seen by that new look-up as a descriptor of unknown kind, which fails with `EBADF` on Windows and is polled through the host on Linux. Wobbly Life (PPSA29413) selects on file descriptors while streaming its bundles -- [__progname](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - unknown data export +- [__progname](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - points to the constant `eboot.bin`, which `getprogname` and `_getprogname` also return; the console's value is not measured - [environ](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - data export pointing to a fixed empty environment so titles that import it load; it is not the environment libc's `getenv` reads, so it lists none of those variables and `setenv`/`putenv` changes do not appear in it - [seteuid, setegid, setuid, setgid, setreuid, setregid, setresuid, setresgid, setgroups, getgroups](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - the guest process is assumed to run as root, with real, effective and saved user and group ids 0. As in FreeBSD's `sys_seteuid`, `sys_setegid`, `sys_setuid`, `sys_setgid`, `sys_setreuid`, `sys_setregid`, `sys_setresuid` and `sys_setresgid`, id 0 (or -1 for an unchanged `setreuid`/`setregid`/`setresuid`/`setresgid` id) is then accepted without a privilege check and changes no credential, so 0 is returned; any other id would change an id, which is not modelled, and throws. `setgroups` keeps the supplementary group list as `kern_setgroups` does (`NGROUPS_MAX` 1023, an empty list leaves the effective group as the only entry, a first entry other than 0 would change the effective group and throws) and `getgroups` reports it. The ids and privileges a title has on a console are unverified - [pthread_getname_np](../../../core/libs/prx/libkernel/Pthread/Posix/Thread.cpp) (libkernel) - a thread that has already been joined returns `ESRCH` (3) and its output buffer is left untouched, as measured on a PS5 (firmware 13.60) by the author of this entry; since [#4481](https://github.com/boykopovar/AnyPS5/pull/4481) the joined thread's object is retained, so the posix wrapper answers `ESRCH` for it instead of reading the retained name. A null name buffer is answered with `EFAULT` before that, an order the console table does not measure. The SCE sibling `scePthreadGetname` has no measured joined-thread behaviour on the console and still reads the retained object's name. After a detached thread is released, it now returns `ESRCH` through the thread registry instead of reading freed storage; that released-handle answer is not measured on the console (see the scePthreadJoin entry) diff --git a/docs/dev/debt/libkernel_sys.md b/docs/dev/debt/libkernel_sys.md index 3240982464..86007d7cc2 100644 --- a/docs/dev/debt/libkernel_sys.md +++ b/docs/dev/debt/libkernel_sys.md @@ -1,12 +1,11 @@ # libkernel_sys technical debt -- [sceKernelGetCpuUsage, sceKernelGetThreadName, sceKernelLwfsAllocateBlock, sceKernelLwfsLseek, sceKernelLwfsSetAttribute, sceKernelLwfsWrite, sceKernelSetCompressionAttribute and sceKernelSetFsstParam](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) - throw through `NotImplemented_nid_no_patch`; behaviour and the PS5 prototypes are unmeasured. The parameter lists come from a single source, the PS4 OpenOrbis `libkernel.h`, with no second reference: `off_t` and `ssize_t` are taken as 64-bit, the `Lwfs*` and `Set*` parameters are unnamed there (the names here are guesses), and the `Proc_Stats` of `sceKernelGetCpuUsage` is declared as `void*` because its layout is unknown. -- [sceKernelGetPhysPageSize](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) returns `PS5_PAGE_SIZE` (16 KiB), the guest page granularity used by libkernel's direct-memory and mapping implementation. The export has no arguments. Console behaviour is unverified ### Silent stubs - [sceKernelCallIndirectBuffer2](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) - always writes a zero result, as `sceAmprAmmSubmitCommandBuffer2` does here; in firmware 13.42 the library passes the result pointer to a kernel ioctl, and what the kernel writes there is not known ### Unknown function info +- [sceKernelGetCpuUsage, sceKernelGetThreadName, sceKernelLwfsAllocateBlock, sceKernelLwfsLseek, sceKernelLwfsSetAttribute, sceKernelLwfsWrite, sceKernelSetCompressionAttribute and sceKernelSetFsstParam](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) - throw through `NotImplemented_nid_no_patch`; behaviour and the PS5 prototypes are unmeasured. The parameter lists come from a single source, the PS4 OpenOrbis `libkernel.h`, with no second reference: `off_t` and `ssize_t` are taken as 64-bit, the `Lwfs*` and `Set*` parameters are unnamed there (the names here are guesses), and the `Proc_Stats` of `sceKernelGetCpuUsage` is declared as `void*` because its layout is unknown. - [Nine unnamed additional exports](../../../core/libs/prx/libkernel_sys/AdditionalExports.cpp) (libkernel_sys, NIDs `pCbBddNl66Y`, `zAloppPJxy0`, `vq2+HyP5U5I`, `z+e0vV-tnH4`, `gJ5gpW45mU0`, `N94a0T4F4+U`, `C49jelxiaVE`, `1WXQlxMpnNA`, `FR0odl35yQY`) - return what firmware 13.42's `system/common/lib/libkernel_sys.sprx` returns, read from disassembly to the return, not measured on a console. The first five are `xor %eax,%eax; ret`, `N94a0T4F4+U` is `mov $0x8002004e,%eax; ret` and `C49jelxiaVE` is `mov $0x20018,%eax; ret`. `1WXQlxMpnNA` stores 1 to a zero-initialised module byte and returns 0, and `FR0odl35yQY` returns that byte zero-extended; no other code in the module touches the byte. None reads an argument, so the declarations are parameterless; the 32-bit loads clear the upper half of `rax`, so they return `std::uint64_t`. Names, intended parameters and callers are unknown. - [libkernel_sys additional exports](../../../core/libs/prx/libkernel_sys/AdditionalExports.cpp) - 309 callable exports have import-resolution declarations only. Parameter lists, return types and behavior remain unverified. Parameterless `int` declarations are placeholders, not verified ABI prototypes; every entry throws through `NotImplemented_nid_no_patch`. Unresolved names use literal NID aliases; no runtime functionality or data objects are fabricated. Existing providers and exports supplied by open pull requests are excluded. Kernel variant imports already resolve through `libkernel`, then `libc`; existing providers remain unchanged. Six native data exports (`errno`, `__stack_chk_guard`, `_sigintr`, `__progname`, `environ`, and NID `AxgW94umKqU`) require separate storage, layout, TLS and ownership validation and are not added as callable aliases or fabricated globals. @@ -331,6 +330,7 @@ - [scePthreadCondattrGetclock](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - a null clock pointer with a valid attribute throws `std::invalid_argument`, where a payload process measured on a device faults. A null or destroyed attribute with a null output returns `SCE_KERNEL_ERROR_EINVAL` (`0x80020016`) because [FreeBSD 11.4 libthr](https://github.com/freebsd/freebsd-src/blob/d106002967/lib/libthr/thread/thr_condattr.c#L82-L90) checks the attribute first; that pair was not measured. Returning `SCE_KERNEL_ERROR_EFAULT` (`0x8002000E`) for an unwritable clock pointer is a host-safety fallback; firmware 13.42 disassembly stores the clock directly, so the console faults. Stale handles are not validated ### Functional +- [sceKernelGetPhysPageSize](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) returns `PS5_PAGE_SIZE` (16 KiB), the guest page granularity used by libkernel's direct-memory and mapping implementation. The export has no arguments. Console behaviour is unverified - [revoke](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) - a character device throws, because device revocation is not modelled. Other paths follow FreeBSD 11 `sys_revoke`: path errors as `stat` reports them, and `EINVAL` for anything that is not a character device. Guest paths have no `/dev`, so `/dev/null` and the like fail with `ENOENT`, not as devices - [sceKernelGetUpdVersion](../../../core/libs/prx/libkernel_sys/Export.Discovery.cpp) (libkernel_sys) - runs the same code as `sysKernelGetUpdVersion` on firmware 13.42 ([disassembly](https://github.com/boykopovar/AnyPS5/pull/10671#issuecomment-6398286973)), so it forwards there: a null output is refused with `SCE_KERNEL_ERROR_EINVAL`, and otherwise the 4 bytes come from `machdep.upd_version`, whose retail value is unmeasured (see libkernel's entry) diff --git a/docs/dev/debt/relinker.md b/docs/dev/debt/relinker.md index f651709df7..bcc6f920eb 100644 --- a/docs/dev/debt/relinker.md +++ b/docs/dev/debt/relinker.md @@ -29,7 +29,7 @@ - An RSP operand that `--frame-red-zone` cannot move in place, an 8-bit displacement the shift takes past 0x7f or one without a displacement, moves to a stub with the instructions after it up to five bytes and is re-encoded there with the moved displacement ([framer](../../../core/relinker/codegen/src/x86/RedZoneFramer.cpp)). The leaf is skipped when that site would take in a branch target, a branch, ret or RIP-relative instruction, or another site, and when the operand is EVEX, whose 8-bit displacement is scaled. A game patch over a framed site or a moved displacement is refused. - In `--frame-red-zone`, function bounds come from the executable's `.eh_frame` FDEs: each function is decoded from its FDE start to its FDE end, or to int3 padding before it, and the relinker stops with an error when the executable has none. Code outside every FDE, such as a function without unwind information, is not framed ([framer](../../../core/relinker/codegen/src/x86/RedZoneFramer.cpp)). - `--to-intel` lowers MCOMMIT to STC plus NOP padding and RDPRU through a runtime-checked stub in the [matcher](../../../core/relinker/codegen/src/x86/Amd64OnlyInstructionMatcher.cpp): AMD APM Vol. 3 defines RDPRU ECX 0 as MPERF and ECX 1 as APERF, neither readable on Intel hosts, so both selectors return the host TSC as a disclosed monotonic-counter approximation (their ratio always reads 1.0) while other selectors yield zero EDX:EAX. STC asserts CF=1 because under x86-TSO prior stores are already ordered and guest memory is host-DRAM-backed, leaving the commit-success case as the only observable one. Non-zero RDPRU selectors, the TSC-for-MPERF/APERF substitution, and any console path reporting MCOMMIT CF=0 are unverified. -- [Unscoped imports on Windows](../../../core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp) - an import without a module that no searched library exports under its name is searched again under the NID of that name, because homebrew built with the [ps5-payload-dev SDK](https://github.com/ps5-payload-dev/sdk) imports by symbol name (Quake, from the websrv homebrew launcher; Mari0, #6239) while the libraries in `libs/` export NIDs. A dependency named with `.sprx`, `.suprx` or `.debug_prx` loads the `.prx` library of the same stem from `libs/`, and a kernel-family import searches the other members and `libc.prx`, undeclared variants optional, as `libSceLibcInternal` already loads `libc.prx`: AnyPS5's `libkernel_web.prx` exports only two functions, where the console's `libkernel_web.sprx` is a libkernel variant. A name that matches a library's export as written still binds to that export first. macOS resolves these imports through the host loader by name and is unchanged. +- [Unscoped imports on Windows](../../../core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp) - an import without a module that no searched library exports under its name is searched again under the NID of that name, because homebrew built with the [ps5-payload-dev SDK](https://github.com/ps5-payload-dev/sdk) imports by symbol name (Quake, from the websrv homebrew launcher; Mari0, #6239) while the libraries in `libs/` export NIDs. A dependency named with `.sprx`, `.suprx` or `.debug_prx` loads the `.prx` library of the same stem from `libs/`, and a kernel-family import searches the other members and `libc.prx`, undeclared variants optional, as `libSceLibcInternal` already loads `libc.prx`: AnyPS5's `libkernel_web.prx` exports only throwing placeholders (see [libkernel_web](libkernel_web.md)), where the console's `libkernel_web.sprx` is a libkernel variant. A name that matches a library's export as written still binds to that export first. macOS resolves these imports through the host loader by name and is unchanged. - [Unscoped imports on Linux](../../../core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp) - in an executable or bundled module that names a dependency with `.sprx`, `.suprx` or `.debug_prx`, as homebrew built with the [ps5-payload-dev SDK](https://github.com/ps5-payload-dev/sdk) does, an import without a module that is named by symbol is bound to the NID of that name only. Unlike Windows, the name as written is not tried first, because the host loader also searches the host C library, which exports `malloc` or `pthread_create` under their names. A name that a bundled module exports still binds to that module, as does a bundled module's import of a name the executable exports, and such a dependency loads the `.prx` library of the same stem. Unqualified imports of other executables and bundled modules are still bound by name. - An `R_X86_64_GLOB_DAT` or `R_X86_64_JUMP_SLOT` relocation with a nonzero addend fails the conversion in the Linux output ([ELF patcher](../../../core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp)), in the Windows and macOS outputs ([relocation builder](../../../core/relinker/elfpatcher/src/windows/WindowsRelocationBuilder.cpp)) and in guest modules ([guest image reader](../../../core/relinker/relinker/src/guest/GuestImageReader.cpp)). What the console's loader does with such an addend is not measured. The x86-64 psABI computes both as S, but loaders differ: FreeBSD rtld uses S for GLOB_DAT and lazy JUMP_SLOT and S+A for eager JUMP_SLOT, and glibc used S+A for eager binding before [f8587a61892c](https://github.com/bminor/glibc/commit/f8587a61892cbafd98ce599131bf4f103466f084) (2.36) and S since. - The length-changing path of the [instruction rewriter](../../../core/relinker/codegen/src/x86/X64InstructionRewriter.cpp) is not used by the [converter](../../../core/relinker/codegen/src/Amd64OnlyConverter.cpp): it does not adjust data-to-code references (relocations, FDEs, jump tables) or segment sizes, so every substitution keeps the instruction length. The rewriter conservatively rejects length-changing edits when a surviving truncated relative branch would move relative to its target (only one of the two lies after the cut) or when its section-relative target falls outside the 16-bit range, because the runtime address base needed to resolve a wrapped destination is unavailable; truncated branches that keep their distance and stay in range are accepted.