Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/internal/upstream/pr13-posix-cache-suffix.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion runtime/include/overlay_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion runtime/include/overlay_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
32 changes: 24 additions & 8 deletions runtime/src/overlay_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 7 additions & 2 deletions runtime/src/overlay_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions runtime/tests/run_overlay_posix_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand Down
18 changes: 9 additions & 9 deletions runtime/tests/test_overlay_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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);
Expand Down
13 changes: 9 additions & 4 deletions tools/compile_overlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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')
Expand All @@ -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


Expand Down Expand Up @@ -2075,7 +2080,7 @@ def _do_capture(cap, region_coverage_cache, interior_frag_jobs):
_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:
Expand Down Expand Up @@ -2269,7 +2274,7 @@ def _do_capture(cap, region_coverage_cache, interior_frag_jobs):
# 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}')
Expand Down