Repository navigation
feat(libc): provide the runtime scripting allocator hooks - #5092
Conversation
Progress report (8dc92ae → aea1dd6)➖ System libraries: 88.7% (+0.0%, +2 implemented functions) ✅ 2 implemented
|
|
Ready to merge from my side, but the PR description fails the conventions check:
Please fill those template lines in (only you can answer AI-assisted); it merges once they pass. |
|
Tested on Linux x86-64 (Release build, CTest), with a4e1104 merged into main 9d0a41d:
AI-assisted: yes (Claude Code) |
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
Use the registered application allocator and the source-backed alignment/size signature. Add callback ownership and failure checks; record unmeasured console behavior.
a4e1104 to
aea1dd6
Compare
|
Rebased onto main Fresh macOS 27.0.1 arm64 / AppleClang 21 / C++20 checks: the actual production The aborting stand-ins below deliberately exclude default guest-heap/process-parameter execution: this is not a full libc or patched-export lookup test. The rebased head still needs the linked Manually inspected the bot-listed shared hunks: the debt changes are other entries; #4927 changes Reproduce the focused custom-allocator checkSave the following as clang++ -std=c++20 -Wall -Wextra -Werror -Icore/libs core/libs/prx/libc/src/ApplicationHeap.cpp /path/to/allocator_harness.cpp -o /tmp/allocator-check
/tmp/allocator-check
clang++ -std=c++20 -Wall -Wextra -Werror -fsanitize=address,undefined -fno-omit-frame-pointer -Icore/libs core/libs/prx/libc/src/ApplicationHeap.cpp /path/to/allocator_harness.cpp -o /tmp/allocator-sanitized
/tmp/allocator-sanitized#include "prx/libc/include/ApplicationHeap.hpp"
#include "prx/libc/include/GuestHeap.hpp"
#include <array>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <new>
#include <stdexcept>
extern "C" void* scriptingGetMem_nid_postfix(std::size_t, std::size_t);
extern "C" void scriptingFreeMem_nid_postfix(void*);
extern "C" const void* ApplicationProcessParameters_nid_no_patch() { std::abort(); }
namespace GuestHeap {
extern "C" void* GuestHeapAllocate_nid_postfix(std::size_t) { std::abort(); }
extern "C" void GuestHeapFree_nid_postfix(void*) { std::abort(); }
extern "C" void* GuestHeapReallocate_nid_postfix(void*, std::size_t) { std::abort(); }
extern "C" void* GuestHeapAlign_nid_postfix(std::size_t, std::size_t) { std::abort(); }
extern "C" void* GuestHeapRealign_nid_postfix(void*, std::size_t, std::size_t) { std::abort(); }
extern "C" std::size_t GuestHeapUsableSize_nid_postfix(const void*) { std::abort(); }
}
namespace {
alignas(4096) std::array<unsigned char,8192> storage{};
std::size_t seenAlignment=0, seenSize=0;
unsigned calls=0, frees=0;
int failure=0;
void require(bool value) { if (!value) throw std::runtime_error("allocator assertion failed"); }
void* align(std::size_t alignment, std::size_t size) {
++calls; seenAlignment=alignment; seenSize=size;
if(failure==1) return nullptr;
if(failure==2) throw std::bad_alloc();
if(failure==3) throw std::runtime_error("callback failure");
if(failure==4) return storage.data()+1;
return storage.data();
}
void* allocate(std::size_t bytes) { return align(16,bytes); }
void release(void* pointer) { require(pointer==storage.data()); ++frees; }
void* zeroAllocate(std::size_t count,std::size_t bytes) { return allocate(count*bytes); }
void* resize(void*,std::size_t bytes) { return allocate(bytes); }
void* realign(void*,std::size_t bytes,std::size_t alignment) { return align(alignment,bytes); }
int posix(void** pointer,std::size_t alignment,std::size_t bytes) { *pointer=align(alignment,bytes);return 0; }
}
int main() {
scriptingFreeMem_nid_postfix(nullptr);
const std::array<void*,10> api{reinterpret_cast<void*>(&allocate),reinterpret_cast<void*>(&release),reinterpret_cast<void*>(&zeroAllocate),reinterpret_cast<void*>(&resize),reinterpret_cast<void*>(&align),reinterpret_cast<void*>(&realign),reinterpret_cast<void*>(&posix)};
ApplicationHeapRegister_nid_no_patch(api.data());
for(const std::size_t alignment: {0,1,3,15,16,32,64,256}) {
auto* pointer=static_cast<unsigned char*>(scriptingGetMem_nid_postfix(alignment,37));
require(pointer==storage.data() && seenAlignment==(alignment<16?16:alignment) && seenSize==37);
std::memset(pointer,0xa5,37); scriptingFreeMem_nid_postfix(pointer);
}
require(frees==8);
auto before=calls;
for(const std::size_t alignment: {24,48,1280}) require(scriptingGetMem_nid_postfix(alignment,37)==nullptr);
require(calls==before);
scriptingFreeMem_nid_postfix(nullptr);require(frees==8);
for(failure=1;failure<=2;++failure) require(scriptingGetMem_nid_postfix(16,37)==nullptr);
for(failure=3;failure<=4;++failure) {
bool threw=false; try { scriptingGetMem_nid_postfix(16,37); } catch(const std::runtime_error&) { threw=true; }
require(threw);
}
std::cout << "8 normalization/alignment cases, 3 invalid alignments, matching/null release, null/bad_alloc failure and 2 propagated errors pass\n";
}AI-assisted: yes (OpenAI Codex). |
|
Checked on the current head: build + ctest of core/libs (105/105, incl. the eight |
|
Tested on Linux x86-64 (Release build, CTest), with aea1dd6 merged into main 44df216. This replaces my earlier result at a4e1104:
AI-assisted: yes (Claude Code) |
|
Heads-up @MrMha: since this merged, Metal Gear Solid Master Collection (PPSA18194) aborts 0 s in on AI-assisted: yes |
What
Add the runtime allocator hooks requested in #694:
scriptingGetMem(alignment, size)calls the application allocator's aligned allocation, andscriptingFreeMem(pointer)frees through that same allocator. Alignments below 16 normalize to 16; larger non-powers of two return null. Null free is a no-op; allocation failure represented bystd::bad_allocreturns null; other allocator errors propagate.The signatures and source-based alignment contract remain documented in libc technical debt. NIDs:
scriptingGetMem→ayuoL6Vjz2k;scriptingFreeMem→yV45DG6ei28. This supplies the hooks, but does not claim complete resolution of the title's process-scope lookup path.Reapplied on main
2e5dd5aa144af1bf90a214a6341bf3e1b4e6d47a. Retained the newly mergedfdopendebt entry and added the scripting entry beside it; production and test changes apply cleanly.Tested
Fresh local checks on macOS 27.0.1 arm64, AppleClang 21, C++20,
-Wall -Wextra -Werror:ApplicationHeap.cppwith a controlled registered allocator. Native and ASan/UBSan executions pass eight normalization/alignment cases, writable storage, matching/null free, three invalid alignments without callback invocation, null/bad_alloc allocation failures, and propagation of callback/misalignment errors.core/libs/tests/ApplicationHeap.cpppasses-fsyntax-only.ApplicationHeap.cppbecause both scripting hooks are absent.Earlier Linux full linked regression evidence from @coltken95 at old head
a4e1104remains in the discussion; it was not rerun on this new head. Full runtime build/CTest, patched-libc process-scope lookup and title execution remain unverified on this head and need the maintainer-dispatched full build.Manual review of the bot-listed shared hunks found other libc debt entries, #4927's
getcwdassertion, #6217's default-heap statistics wiring and #6044's test relocation/labels. None adds these scripting hooks. If #6044 lands first, preserve the scripting assertions atcore/libs/tests/memory/ApplicationHeap.cpp. These are source comparisons, not combined runtime validation.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)