I came across this surprising tidbit while translating jonesforth.s from x86 ASM to C with GCC extensions. depends_on_optimization.c is a "simple" C program which depends on whether it's compiled with (any -O
) or without (-O0
) optimizations. It's entirely possible that the program invokes Undefined Behavior as it's using _start(void)
instead of int main(int argc, char *argv[])
then poking around the C stack to find argc
. That's an artefact of translating ASM to C.
#include <stdlib.h>
#include <unistd.h>
#define NEXT goto **ip++
#ifdef __OPTIMIZE__
#define OFFSET 3
#else
#define OFFSET 0
#endif
void _start()
{
intptr_t *stack[1024];
register intptr_t **sp = stack + (sizeof stack / sizeof *stack), *p;
register void **ip;
goto _start;
ADD:
p = *sp++;
sp[0] += (intptr_t)p;
NEXT;
LIT:
*--sp = (intptr_t *)*ip++;
NEXT;
S0:
*--sp = (intptr_t *)(stack + (sizeof stack / sizeof *stack));
NEXT;
EXIT:
p = *sp++;
exit(*p);
static void *code[] = {&&S0, &&LIT, (void *)OFFSET, &&ADD, &&EXIT};
_start:
ip = code;
NEXT;
}
What compiler flag should I use to make GCC produce the same stack layout regardless of optimization level? I tried various combinations of -fno-stack-check
, -fno-stack-protector
, and -fno-stack-clash-protection
to no avail.