overlay: use platform-native shared-library suffixes

Adapted from NyperYuhgard's PR #13 POSIX overlay work.

Co-authored-by: NyperYuhgard <93950153+NyperYuhgard@users.noreply.github.com>
This commit is contained in:
Matthew Stanley
2026-07-14 10:08:39 -07:00
parent e5b5e309b5
commit e247155cd6
8 changed files with 65 additions and 30 deletions
@@ -0,0 +1,9 @@
# PR #13 POSIX cache-suffix provenance
Parked from NyperYuhgard's PSXrecomp PR #13, commit
[`a39ab37dbc32f4889bf80331208b7510f497fc4f`](https://github.com/mstan/psxrecomp/commit/a39ab37dbc32f4889bf80331208b7510f497fc4f).
Native overlay artifacts use `.dll` on Windows and `.so` on POSIX hosts. The
compiler, cache parser, manifest lookup, ABI cleanup, and cached-CRC lookup share
that convention. POSIX loading/scanning itself is excluded because current master
already has the newer implementation merged through PR #18.
+1 -1
View File
@@ -49,7 +49,7 @@ int overlay_loader_dispatch(CPUState *cpu, uint32_t addr);
* (loaded DLLs stay loaded); emu thread only. */
void overlay_loader_rescan(void);
/* True if the cache holds a DLL named <region_start8>_<crc8>.dll. */
/* True if the cache holds <region_start8>_<crc8>.{dll,so}. */
int overlay_loader_has_cached_crc(uint32_t region_start, uint32_t crc);
/* Returns number of functions currently registered in the dynamic table. */
+1 -1
View File
@@ -7,7 +7,7 @@
extern "C" {
#endif
/* Parsed <addr8>_<crc8>.dll cache filename. The parser is shared by the
/* Parsed <addr8>_<crc8>.{dll,so} cache filename. The parser is shared by the
* Windows and POSIX directory walkers so both platforms reject partial hex
* fields and lookalike suffixes identically. */
typedef struct PsxOverlayCacheFile {
+24 -8
View File
@@ -22,6 +22,14 @@
# include <unistd.h>
#endif
#ifdef _WIN32
# define OVERLAY_SHARED_EXT ".dll"
# define OVERLAY_SHARED_EXT_LEN 4
#else
# define OVERLAY_SHARED_EXT ".so"
# define OVERLAY_SHARED_EXT_LEN 3
#endif
/* ============================================================================
* Inc3 — Per-entry validity + multi-candidate dispatch (design doc §8)
*
@@ -953,8 +961,11 @@ static void rebuild_lazy_manifest_index(void) {
char path[800];
snprintf(path, sizeof(path), "%s", s_cache_idx[ci].path);
size_t n = strlen(path);
if (n < 4 || strcmp(path + n - 4, ".dll") != 0) continue;
snprintf(path + n - 4, sizeof(path) - (n - 4), ".ranges");
if (n < OVERLAY_SHARED_EXT_LEN ||
strcmp(path + n - OVERLAY_SHARED_EXT_LEN, OVERLAY_SHARED_EXT) != 0)
continue;
snprintf(path + n - OVERLAY_SHARED_EXT_LEN,
sizeof(path) - (n - OVERLAY_SHARED_EXT_LEN), ".ranges");
int man_n = 0;
ManFn *man = parse_manifest(path, &man_n);
if (!man) continue;
@@ -1195,9 +1206,10 @@ static void remove_posix_dll_and_manifest(const char *dll_path) {
remove(dll_path);
char ranges[800];
int n = snprintf(ranges, sizeof(ranges), "%s", dll_path);
if (n >= 4 && (size_t)n + 4 < sizeof(ranges) &&
strcmp(ranges + n - 4, ".dll") == 0) {
memcpy(ranges + n - 4, ".ranges", 8);
if (n >= OVERLAY_SHARED_EXT_LEN &&
(size_t)n + 7 - OVERLAY_SHARED_EXT_LEN < sizeof(ranges) &&
strcmp(ranges + n - OVERLAY_SHARED_EXT_LEN, OVERLAY_SHARED_EXT) == 0) {
memcpy(ranges + n - OVERLAY_SHARED_EXT_LEN, ".ranges", 8);
remove(ranges);
}
#else
@@ -1565,7 +1577,9 @@ int overlay_loader_has_cached_crc(uint32_t region_start, uint32_t crc) {
if (s_cache_idx[i].region_start != region_start) continue;
const char *fn = strrchr(s_cache_idx[i].path, '/');
fn = fn ? fn + 1 : s_cache_idx[i].path;
if (strlen(fn) == 21 && (uint32_t)strtoul(fn + 9, NULL, 16) == crc)
if (strlen(fn) == 17u + OVERLAY_SHARED_EXT_LEN &&
strcmp(fn + 17, OVERLAY_SHARED_EXT) == 0 &&
(uint32_t)strtoul(fn + 9, NULL, 16) == crc)
return 1;
}
return 0;
@@ -2218,8 +2232,10 @@ static int load_one_dll(const char *dll_path) {
char ranges_path[800];
snprintf(ranges_path, sizeof(ranges_path), "%s", dll_path);
size_t plen = strlen(ranges_path);
if (plen >= 4 && strcmp(ranges_path + plen - 4, ".dll") == 0)
snprintf(ranges_path + plen - 4, sizeof(ranges_path) - (plen - 4), ".ranges");
if (plen >= OVERLAY_SHARED_EXT_LEN &&
strcmp(ranges_path + plen - OVERLAY_SHARED_EXT_LEN, OVERLAY_SHARED_EXT) == 0)
snprintf(ranges_path + plen - OVERLAY_SHARED_EXT_LEN,
sizeof(ranges_path) - (plen - OVERLAY_SHARED_EXT_LEN), ".ranges");
int man_n = 0;
ManFn *man = parse_manifest(ranges_path, &man_n);
+7 -2
View File
@@ -24,8 +24,13 @@ static int parse_hex8(const char *text, uint32_t *value) {
int psx_overlay_cache_name_parse(const char *name, uint32_t *region_start,
uint32_t *content_crc) {
uint32_t addr = 0, crc = 0;
if (!name || strlen(name) != 21 || name[8] != '_' ||
strcmp(name + 17, ".dll") != 0 ||
#ifdef _WIN32
static const char extension[] = ".dll";
#else
static const char extension[] = ".so";
#endif
if (!name || strlen(name) != 17 + sizeof(extension) - 1 || name[8] != '_' ||
strcmp(name + 17, extension) != 0 ||
!parse_hex8(name, &addr) || !parse_hex8(name + 9, &crc))
return 0;
if (region_start) *region_start = addr;
+5 -5
View File
@@ -9,14 +9,14 @@ cache="$tmp/cache"
base="$tmp/tags"
expected="cg12_11111111"
other="cg12_22222222"
mkdir -p "$cache/00000000_11111111.dll" "$base/$expected" "$base/$other"
mkdir -p "$cache/00000000_11111111.so" "$base/$expected" "$base/$other"
cc -std=c99 -Wall -Wextra -Werror -fPIC -shared \
"$root/runtime/tests/overlay_posix_fixture.c" \
-o "$cache/80010000_DEADBEEF.dll"
: > "$cache/00000000_00000000.dll"
: > "$cache/80010000_DEADBEG0.dll"
: > "$base/$other/80020000_12345678.dll"
-o "$cache/80010000_DEADBEEF.so"
: > "$cache/00000000_00000000.so"
: > "$cache/80010000_DEADBEG0.so"
: > "$base/$other/80020000_12345678.so"
cc -std=c99 -Wall -Wextra -Werror \
-I"$root/runtime/include" \
+9 -9
View File
@@ -14,7 +14,7 @@ typedef struct ScanResult {
static int record_cache_file(const PsxOverlayCacheFile *file, void *opaque) {
ScanResult *result = (ScanResult *)opaque;
result->count++;
if (strcmp(file->name, "80010000_DEADBEEF.dll") == 0) {
if (strcmp(file->name, "80010000_DEADBEEF.so") == 0) {
result->addr = file->region_start;
result->crc = file->content_crc;
}
@@ -23,16 +23,16 @@ static int record_cache_file(const PsxOverlayCacheFile *file, void *opaque) {
static void check_name_parser(void) {
uint32_t addr = 1, crc = 1;
assert(psx_overlay_cache_name_parse("00000000_00000000.dll", &addr, &crc));
assert(psx_overlay_cache_name_parse("00000000_00000000.so", &addr, &crc));
assert(addr == 0 && crc == 0);
assert(psx_overlay_cache_name_parse("89abcdef_ABCDEF01.dll", &addr, &crc));
assert(psx_overlay_cache_name_parse("89abcdef_ABCDEF01.so", &addr, &crc));
assert(addr == 0x89ABCDEFu && crc == 0xABCDEF01u);
assert(!psx_overlay_cache_name_parse("G0010000_DEADBEEF.dll", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEG0.dll", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEEF.so", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000-DEADBEEF.dll", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEEF.dll.extra", &addr, &crc));
assert(!psx_overlay_cache_name_parse("G0010000_DEADBEEF.so", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEG0.so", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEEF.dll", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000-DEADBEEF.so", &addr, &crc));
assert(!psx_overlay_cache_name_parse("80010000_DEADBEEF.so.extra", &addr, &crc));
}
int main(int argc, char **argv) {
@@ -55,7 +55,7 @@ int main(int argc, char **argv) {
assert(handle == NULL); /* A directory is not a loadable overlay library. */
char fixture[1024];
snprintf(fixture, sizeof(fixture), "%s/80010000_DEADBEEF.dll", argv[1]);
snprintf(fixture, sizeof(fixture), "%s/80010000_DEADBEEF.so", argv[1]);
handle = psx_overlay_posix_library_open(fixture, error, sizeof(error));
assert(handle != NULL);
typedef int (*AbiFn)(void);
+9 -4
View File
@@ -151,6 +151,11 @@ def is_windows() -> bool:
or platform.system().startswith(('MSYS', 'CYGWIN', 'MINGW')))
def overlay_ext() -> str:
"""Use the host platform's conventional shared-library suffix."""
return '.dll' if is_windows() else '.so'
def cache_arch_abi() -> str:
"""Canonical cache arch-abi tag, IDENTICAL to overlay_loader.c's
PSX_OVERLAY_ARCH_ABI ("<os>-<arch>": win|linux|macos + x64|arm64|x86).
@@ -1686,7 +1691,7 @@ def compile_interior_fragment(interior: int, data: bytes, load_addr: int,
key = binascii.crc32(b''.join(
struct.pack('<II', ev, crc)
for ev, crc, _ in sorted(frag_ids))) & 0xFFFFFFFF
dll_path = os.path.join(cache_dir, f'{phys_addr:08X}_{key:08X}.dll')
dll_path = os.path.join(cache_dir, f'{phys_addr:08X}_{key:08X}{overlay_ext()}')
if os.path.exists(dll_path) and not args.force:
return frag_ids # already built
patched_c = os.path.join(tmp, 'frag_patched.c')
@@ -1708,7 +1713,7 @@ def compile_interior_fragment(interior: int, data: bytes, load_addr: int,
if not compile_dll(patched_c, dll_path, include_dirs,
gcc=args.gcc, flavor=args.flavor):
return None
write_overlay_ranges_from(frag_ids, dll_path[:-4] + '.ranges')
write_overlay_ranges_from(frag_ids, os.path.splitext(dll_path)[0] + '.ranges')
return frag_ids
@@ -2075,7 +2080,7 @@ def main():
_interiors | _disp_roots, _executed))
if not args.static:
dll_path = os.path.join(cache_dir, f'{phys_addr:08X}_{crc32:08X}.dll')
dll_path = os.path.join(cache_dir, f'{phys_addr:08X}_{crc32:08X}{overlay_ext()}')
print(f'Overlay load=0x{load_addr:08X} size={size} crc32=0x{crc32:08X}')
if args.static:
@@ -2269,7 +2274,7 @@ def main():
# Emit the per-entry code-range manifest beside the DLL from
# the same func-id list we keyed the dedup on. The loader keys
# it by the same filename stem with .ranges (replacing .dll).
ranges_out = dll_path[:-4] + '.ranges'
ranges_out = os.path.splitext(dll_path)[0] + '.ranges'
if this_ids:
nfn = write_overlay_ranges_from(this_ids, ranges_out)
print(f' ranges: {nfn} functions -> {ranges_out}')