summaryrefslogtreecommitdiffstats
path: root/lib/csu/i386-elf/crt1.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/csu/i386-elf/crt1.c')
-rw-r--r--lib/csu/i386-elf/crt1.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/lib/csu/i386-elf/crt1.c b/lib/csu/i386-elf/crt1.c
index a9caf9e..43adc10 100644
--- a/lib/csu/i386-elf/crt1.c
+++ b/lib/csu/i386-elf/crt1.c
@@ -100,7 +100,40 @@ _start(char *ap, ...)
monstartup(&eprol, &etext);
#endif
_init();
+#ifndef __GNUC__
exit( main(argc, argv, env) );
+#else
+ /*
+ * Some versions of gcc-2 expect the stack frame to be aligned as
+ * follows after it is set up in main():
+ *
+ * +--------------+ <--- aligned by PREFERRED_STACK_BOUNDARY
+ * +%ebp (if any) +
+ * +--------------+
+ * |return address|
+ * +--------------+
+ * | arguments |
+ * | : |
+ * | : |
+ * +--------------+
+ *
+ * We implement the above to fix just the usual case in FreeBSD-4.
+ * Alignment for main() is too compiler-dependent to handle correctly
+ * in all cases here (or in the kernel). E.g., a different alignment
+ * is required for at least gcc-2.95.4 even for the small variation
+ * of compiling main() with -fomit-frame-pointer.
+ */
+ __asm__("
+ andl $~0xf, %%esp # align stack to 16-byte boundary
+ subl $12+12, %%esp # space for args and padding
+ movl %0, 0(%%esp)
+ movl %1, 4(%%esp)
+ movl %2, 8(%%esp)
+ call main
+ movl %%eax, 0(%%esp)
+ call exit
+ " : : "r" (argc), "r" (argv), "r" (env) : "ax", "cx", "dx", "memory");
+#endif
}
#ifdef GCRT
OpenPOWER on IntegriCloud