mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-24 00:02:45 +02:00
* fix(linux): thread a va_list* through _Printf (x86-64 SysV ABI) On the x86-64 System V ABI `va_list` is an array type, so a by-value `va_list` parameter decays to a pointer. `_Printf()` was passing `&args` (the address of that local pointer, not the argument list) to `_Putfld()`, which does `va_arg(*args, ...)` — so `_Putfld` walked garbage and segfaulted. Latent at `-Og`, fatal at `-O2` (PR #9), which is why the Linux release build crashed at boot: bossInitMainthreadData (boss.c:247, the D121 per-level -m token sprintf) -> sprintf("-level_%c%c %s", ...) -> _Putfld -> SIGSEGV @ xprintf.c Same UB class as D187. Windows x64's `va_list` is a scalar (`char*`), so `&args` happened to work there — the Windows build is unaffected. Fix: under `#ifdef PORT`, `_Printf` takes `va_list *` and passes it straight to `_Putfld` (which already expects `va_list *`); `src/sprintf.c` (the only PC caller — `rmon.c` is excluded from the build) passes `&args` of a real `va_list` object. N64 build untouched (`#ifdef PORT`, and it byte-matches the ROM). Verified: - Windows: build links, `-level_09` framediff 3/3 within golden threshold. - Linux -O2: boot crash gone, now advances past bossInitMainthreadData into stage load (uncovers a separate pre-existing stan.c stack overflow during BUNKER1 prop setup — tracked separately). * docs: D188 (xprintf va_list ABI) + D189 (stan.c stack-smash) findings + porting-notes D7
31 lines
654 B
C
31 lines
654 B
C
#include <stdarg.h>
|
|
#include <ultra64.h>
|
|
/*#include <stddef.h>*/
|
|
|
|
|
|
|
|
char *proutSprintf(char *dst, const char *src, size_t count) {
|
|
return (char *) memcpy((u8 *) dst, (u8 *) src, count) + count;
|
|
}
|
|
|
|
int sprintf(char *dst, const char *fmt, ...) {
|
|
s32 written;
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
#ifdef PORT
|
|
/* xprintf.c's _Printf takes a va_list* under PORT — see the comment there
|
|
* (x86-64 SysV va_list-is-an-array ABI). */
|
|
written = _Printf(proutSprintf, dst, fmt, &args);
|
|
#else
|
|
written = _Printf(proutSprintf, dst, fmt, args);
|
|
#endif
|
|
if (written >= 0) {
|
|
dst[written] = 0;
|
|
}
|
|
return written-1;
|
|
}
|
|
|
|
|
|
|
|
|