diff --git a/docs/internal/upstream/pr13-posix-cache-suffix.md b/docs/internal/upstream/pr13-posix-cache-suffix.md new file mode 100644 index 000000000..b50d307b3 --- /dev/null +++ b/docs/internal/upstream/pr13-posix-cache-suffix.md @@ -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. diff --git a/runtime/include/overlay_loader.h b/runtime/include/overlay_loader.h index b309bb53e..dfe4f69c4 100644 --- a/runtime/include/overlay_loader.h +++ b/runtime/include/overlay_loader.h @@ -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 _.dll. */ +/* True if the cache holds _.{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. */ diff --git a/runtime/include/overlay_posix.h b/runtime/include/overlay_posix.h index 3f3b6473e..39381a4fb 100644 --- a/runtime/include/overlay_posix.h +++ b/runtime/include/overlay_posix.h @@ -7,7 +7,7 @@ extern "C" { #endif -/* Parsed _.dll cache filename. The parser is shared by the +/* Parsed _.{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 { diff --git a/runtime/src/overlay_loader.c b/runtime/src/overlay_loader.c index b6d552aba..857be681f 100644 --- a/runtime/src/overlay_loader.c +++ b/runtime/src/overlay_loader.c @@ -22,6 +22,14 @@ # include #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); diff --git a/runtime/src/overlay_posix.c b/runtime/src/overlay_posix.c index efe6396a5..9862dd173 100644 --- a/runtime/src/overlay_posix.c +++ b/runtime/src/overlay_posix.c @@ -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; diff --git a/runtime/tests/run_overlay_posix_test.sh b/runtime/tests/run_overlay_posix_test.sh index 1a4e7730a..d9a150159 100644 --- a/runtime/tests/run_overlay_posix_test.sh +++ b/runtime/tests/run_overlay_posix_test.sh @@ -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" \ diff --git a/runtime/tests/test_overlay_posix.c b/runtime/tests/test_overlay_posix.c index dde630081..e946b7faf 100644 --- a/runtime/tests/test_overlay_posix.c +++ b/runtime/tests/test_overlay_posix.c @@ -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); diff --git a/tools/compile_overlays.py b/tools/compile_overlays.py index 30ed9c307..54330a2fd 100644 --- a/tools/compile_overlays.py +++ b/tools/compile_overlays.py @@ -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 ("-": 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(' {ranges_out}')