Browse Source

Based on start.S from debian's glibc, this gets arm working
properly with the new ABI

Eric Andersen 19 years ago
parent
commit
299d67551e
1 changed files with 69 additions and 138 deletions
  1. 69 138
      libc/sysdeps/linux/arm/crt1.S

+ 69 - 138
libc/sysdeps/linux/arm/crt1.S

@@ -1,148 +1,80 @@
-/* When we enter this piece of code, the program stack looks like this:
-        argc            argument counter (integer)
-        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
-
-   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
-
-   When we are done here, we want
-	a1=argc
-	a2=argv[0]
-	a3=argv[argc+1]
-
-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
+/* Startup code for ARM & ELF
+   Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This is the canonical entry point, usually the first thing in the text
+   segment.
+
+	Note that the code in the .init section has already been run.
+	This includes _init and _libc_init
+
+
+	At this entry point, most registers' values are unspecified, except:
+
+   a1		Contains a function pointer to be registered with `atexit'.
+		This is how the dynamic linker arranges to have DT_FINI
+		functions called for shared libraries that have been loaded
+		before this code runs.
+
+   sp		The stack contains the arguments and environment:
+		0(sp)			argc
+		4(sp)			argv[0]
+		...
+		(4*argc)(sp)		NULL
+		(4*(argc+1))(sp)	envp[0]
+		...
+					NULL
 */
 
-#include <features.h>
+	.text
+	.globl _start
+	.type _start,#function
+_start:
+	/* Fetch address of fini */
+	ldr ip, =_fini
 
-.text
-	.global	    _start
-	.type	    _start,%function
-	.type	    _init,%function
-	.type	    _fini,%function
-	.type	    main,%function
-	.type	    __uClibc_main,%function
+	/* Clear the frame pointer since this is the outermost frame.  */
+	mov fp, #0
 
+	/* Pop argc off the stack and save a pointer to argv */
+	ldr a2, [sp], #4
+	mov a3, sp
 
-.text
-_start:
-	/* Save a copy of rtld_fini before r0 gets nuked */
-	mov     r5, r0
-
-	/* clear the frame pointer */
-	mov     fp, #0
-
-
-	/* Load register r0 with main */
-#ifdef __PIC__
-	adr r8, .L_main
-	ldr r0, .L_main
-	add r0, r0, r8
-#else
-	ldr r0, =main
-#endif
-
-
-#ifdef __ARCH_HAS_MMU__
-
-	/* Load register r1 from the stack to its final resting place */
-	ldr     r1, [sp], #4
-
-	/* Copy argv pointer into r2 -- which its final resting place */
-	mov     r2, sp
-#else
-	/*
-	 * uClinux stacks look a little different from normal
-	 * MMU-full Linux stacks (for no good reason)
-	 */
-	/* pull argc and argv off the stack */
-	ldr r1,[sp, #0]
-	ldr r2,[sp, #4]
-#endif
-
-	/* Store _init and _fini to r3 and r4 */
-#ifdef __PIC__
-	adr r8, .L_init
-	ldr r3, .L_init
-	add r3, r3, r8
-
-	ldr r4, .L_init + 4
-	add r4, r4, r8
-#else
-	ldr r3, =_init
-	ldr r4, =_fini
-#endif
-
-	/* Store _fini(r4), rtld_fini(r5), and stack_end(r2) on the stack */
-	str r2, [sp, #-4]!
-	str r5, [sp, #-4]!
-	str r4, [sp, #-4]!
-
-
-	/* We need to call __uClibc_main which should not return.
-	   __uClibc_main (int (*main) (int, char **, char **), int argc,
-			      char **argv, void (*init) (void), void (*fini) (void),
-			      void (*rtld_fini) (void), void *stack_end)
-	*/
-	bl __uClibc_main
+	/* Push stack limit */
+	str a3, [sp, #-4]!
 
-	/* Crash if somehow `exit' returns anyways.  */
-	bl abort
+	/* Push rtld_fini */
+	str a1, [sp, #-4]!
 
-#ifdef __PIC__
-.L_init:
-	.word _init
-	.word _fini
-.L_main:
-	.word main
-#endif
+	/* Set up the other arguments in registers */
+	ldr a1, =main
+	ldr a4, =_init
 
-/* We need this stuff to make gdb behave itself, otherwise
-   gdb will choke with SIGILL when trying to debug apps.
-*/
-	.section ".note.ABI-tag", "a"
-	.align 4
-	.long 1f - 0f
-	.long 3f - 2f
-	.long  1
-0:	.asciz "GNU"
-1:	.align 4
-2:	.long 0
-	.long 2,0,0
-3:	.align 4
+	/* Push fini */
+	str ip, [sp, #-4]!
+
+	/* __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
 
 /* Define a symbol for the first piece of initialized data.  */
 	.data
@@ -151,4 +83,3 @@ __data_start:
 	.long 0
 	.weak data_start
 	data_start = __data_start
-