65816-llvm-mos/demos/gnoErrnoProbe.c
2026-07-07 18:33:48 -05:00

93 lines
2.7 KiB
C

// errno-space consistency probe for GNO/ME. The composite happy-path test
// proves the subsystems compose; this one hunts the KNOWN latent hazard: the
// fd layer maps GS/OS errors to POSIX errno via _mapErr, but the stat/exec/
// access wrappers stash the RAW kernel errno. A real program that branches on
// `errno == ENOENT` breaks wherever the raw value leaks through. We trigger the
// SAME logical error (a missing file) through four wrappers and record the raw
// errno each sets, so the divergence (if any) is visible against ENOENT.
//
// Bank-2 absolute uint16 markers (DBR-independent):
// 0x025000 C0DE reached end
// 0x025030 ENOENT (from errno.h) -- the value a POSIX app expects
// 0x025032 errno after open("nosuch", O_RDONLY) [fd layer, _mapErr]
// 0x025034 errno after stat("nosuch") [stat wrapper, raw kernel]
// 0x025036 errno after unlink("nosuch") [fd layer, _mapErr]
// 0x025038 errno after access("nosuch", F_OK) [access over stat]
// 0x02503A 0001 if all four calls actually FAILED (rc==-1), else which passed
// 0x02503C 0001 if every failing errno == ENOENT (POSIX-consistent), else DEAD
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define M(a) (*(volatile uint16_t *)(a))
#define OK 0x0001
#define BAD 0xDEAD
static const char kMissing[] = "nosuchfile.xyz";
int main(void) {
struct stat sb;
uint16_t failed;
uint16_t consistent;
int eOpen;
int eStat;
int eUnlink;
int eAccess;
int rc;
int fd;
M(0x025000UL) = 0x0000;
M(0x025030UL) = (uint16_t)ENOENT; // what a POSIX app checks against
failed = OK;
errno = 0;
fd = open(kMissing, O_RDONLY);
eOpen = errno;
if (fd != -1) {
failed = BAD; // unexpectedly succeeded
close(fd);
}
M(0x025032UL) = (uint16_t)eOpen;
errno = 0;
rc = stat(kMissing, &sb);
eStat = errno;
if (rc != -1) {
failed = BAD;
}
M(0x025034UL) = (uint16_t)eStat;
errno = 0;
rc = unlink(kMissing);
eUnlink = errno;
if (rc != -1) {
failed = BAD;
}
M(0x025036UL) = (uint16_t)eUnlink;
errno = 0;
rc = access(kMissing, F_OK);
eAccess = errno;
if (rc != -1) {
failed = BAD;
}
M(0x025038UL) = (uint16_t)eAccess;
M(0x02503AUL) = failed;
consistent = OK;
if (eOpen != ENOENT || eStat != ENOENT || eUnlink != ENOENT || eAccess != ENOENT) {
consistent = BAD;
}
M(0x02503CUL) = consistent;
M(0x025000UL) = 0xC0DE;
for (volatile unsigned long j = 0; j < 300000UL; j++) {
}
return 0;
}