summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/sysdeps/linux/arm/crt1.S82
1 files changed, 70 insertions, 12 deletions
diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S
index 8ae897c06..86d6036d8 100644
--- a/libc/sysdeps/linux/arm/crt1.S
+++ b/libc/sysdeps/linux/arm/crt1.S
@@ -40,16 +40,48 @@
...
NULL
*/
+/*
+ For uClinux it looks like this:
+
+ argc argument counter (integer)
+ argv char *argv[]
+ envp char *envp[]
+ argv[0] program name (pointer)
+ argv[1...N] program args (pointers)
+ argv[argc-1] end of args (integer)
+ NULL
+ env[0...N] environment variables (pointers)
+ NULL
+
+ARM register quick reference:
+
+ Name Number ARM Procedure Calling Standard Role
+
+ a1 r0 argument 1 / integer result / scratch register / argc
+ a2 r1 argument 2 / scratch register / argv
+ a3 r2 argument 3 / scratch register / envp
+ a4 r3 argument 4 / scratch register
+ v1 r4 register variable
+ v2 r5 register variable
+ v3 r6 register variable
+ v4 r7 register variable
+ v5 r8 register variable
+ sb/v6 r9 static base / register variable
+ sl/v7 r10 stack limit / stack chunk handle / reg. variable
+ fp r11 frame pointer
+ ip r12 scratch register / new-sb in inter-link-unit calls
+ sp r13 lower end of current stack frame
+ lr r14 link address / scratch register
+ pc r15 program counter
+*/
.text
.globl _start
.type _start,#function
_start:
- /* Fetch address of fini */
- ldr ip, =_fini
-
- /* Clear the frame pointer since this is the outermost frame. */
+ /* Clear the frame pointer and link register since this is the outermost frame. */
mov fp, #0
+ mov lr, #0
/* Pop argc off the stack and save a pointer to argv */
ldr a2, [sp], #4
@@ -61,20 +93,46 @@ _start:
/* Push rtld_fini */
str a1, [sp, #-4]!
- /* Set up the other arguments in registers */
- ldr a1, =main
- ldr a4, =_init
+#ifdef L_Scrt1
+ ldr sl, .L_GOT
+.L_GOT_OFF:
+ add sl, pc, sl
+
+ ldr ip, .L_GOT+4 /* _fini */
+ ldr a1, [sl, ip]
+ str a1, [sp, #-4]! /* Push _fini */
+ ldr ip, .L_GOT+8 /* _init */
+ ldr a4, [sl, ip]
+
+ ldr ip, .L_GOT+12 /* main */
+ ldr a1, [sl, ip]
+
+ /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+ /* Let the libc call main and exit with its return code. */
+ b __uClibc_main(PLT)
+#else
+ /* Fetch address of fini */
+ ldr ip, =_fini
/* Push fini */
str ip, [sp, #-4]!
- /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+ /* Set up the other arguments in registers */
+ ldr a1, =main
+ ldr a4, =_init
+ /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
/* Let the libc call main and exit with its return code. */
- bl __uClibc_main
-
- /* should never get here....*/
- bl abort
+ b __uClibc_main
+#endif
+
+#ifdef L_Scrt1
+.L_GOT:
+ .word _GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+8)
+ .word _fini(GOT)
+ .word _init(GOT)
+ .word main(GOT)
+#endif
/* Define a symbol for the first piece of initialized data. */
.data