# ps5-native-app-boilerplate - Host regression tests for the executable writer. # Copyright (C) 2026 BlackBearReloaded # SPDX-License-Identifier: GPL-3.0-or-later # # Links two tiny PIEs with the host Clang/lld and converts them with # `ps5-native-tool link`: one whose RELRO region begins with .data.rel.ro and # one without any relocated read-only data, where lld drops that section and # RELRO begins at the GOT. Both must convert, and every mapped load segment # must keep its 16 KiB file/address congruence. Skips without the toolchain. import shutil import struct import subprocess import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] NATIVE = ROOT / "tooling" / "native" PT_LOAD = 1 PT_GNU_RELRO = 0x6474E552 PT_SCE_PROCPARAM = 0x61000001 STUB_SOURCE = "int sceKernelUsleep(unsigned int microseconds) { (void)microseconds; return 0; }\n" PLAIN_SOURCE = """ int sceKernelUsleep(unsigned int microseconds); void _start(void); void _start(void) { (void)sceKernelUsleep(1); } """ RELOCATED_SOURCE = """ int sceKernelUsleep(unsigned int microseconds); void _start(void); static int first(void) { return 1; } static int second(void) { return 2; } /* A const table of pointers is relocated read-only data: lld places it in * .data.rel.ro and that section begins the RELRO region. */ int (*const table[])(void) = {first, second, first, second}; void _start(void) { (void)sceKernelUsleep((unsigned int)table[1]()); } """ def find_tool(*names): for name in names: found = shutil.which(name) if found: return found return None def program_headers(data): phoff = struct.unpack_from("