// Diagnostic for the gnoExecProbe exec-into failure: distinguishes a PATH/
// access() resolution miss from a K_execve transfer-of-control failure.
// Runs in the SAME harness as gnoExecProbe (GNO_PROG2=gnoExeced deployed to
// /bin).  Each marker isolates one step so we can see exactly where exec dies.
//
// Bank-2 absolute uint16 markers (DBR-independent):
//   0x025000  C0DE  reached end (fallback; set only if every exec returned)
//   0x025010  E0EC  gnoExeced ran -> some exec transferred control (success)
//   0x025020  F00D  access("/bin/gnoexeced", F_OK) == 0 (our libc finds it)
//                   else EE00|errno  (access failed -> which errno)
//   0x025022  EE00|errno after execv("/bin/gnoexeced") RETURNED (explicit path,
//                   bypasses PATH; only set if the exec failed to transfer)
//   0x025024  EE00|errno after execvp("gnoexeced") RETURNED (PATH-resolved;
//                   only set if that exec failed too)
#include <stdint.h>

extern int access(const char *path, int mode);
extern int execv(const char *path, char *const *argv);
extern int execvp(const char *file, char *const *argv);
extern int errno;

#define M(a)  (*(volatile uint16_t *)(a))
#define BAD   0xDEAD
#define F_OK  0


int main(void) {
    char *argv[2];
    int   r;

    M(0x025000UL) = 0x0000;
    M(0x025010UL) = BAD;
    M(0x025020UL) = BAD;
    M(0x025022UL) = BAD;
    M(0x025024UL) = BAD;

    argv[0] = "gnoexeced";
    argv[1] = 0;

    // Step 1: does our own access() see the file gsh clearly found at /bin?
    errno = 0;
    r     = access("/bin/gnoexeced", F_OK);
    if (r == 0) {
        M(0x025020UL) = 0xF00D;
    } else {
        M(0x025020UL) = 0xEE00 | (uint16_t)(errno & 0xFF);
    }

    // Step 2: explicit-path execv (bypasses $PATH entirely).  On success this
    // never returns -- gnoExeced sets 0x025010 + 0x025000 in the same image.
    errno = 0;
    execv("/bin/gnoexeced", argv);
    M(0x025022UL) = 0xEE00 | (uint16_t)(errno & 0xFF);   // only if it returned

    // Step 3: PATH-resolved execvp, as gnoExecProbe does.
    errno = 0;
    execvp("gnoexeced", argv);
    M(0x025024UL) = 0xEE00 | (uint16_t)(errno & 0xFF);   // only if it returned

    // Reached only if BOTH execs failed to transfer control.
    M(0x025000UL) = 0xC0DE;
    for (volatile unsigned long j = 0; j < 300000UL; j++) {
    }
    return 0;
}
