This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[Patch, AArch64] Update crt0.S to be ILP32-friendly
- From: Yufeng Zhang <Yufeng dot Zhang at arm dot com>
- To: newlib at sourceware dot org
- Cc: Marcus Shawcroft <Marcus dot Shawcroft at arm dot com>
- Date: Mon, 24 Jun 2013 11:34:53 +0100
- Subject: [Patch, AArch64] Update crt0.S to be ILP32-friendly
Hi,
This patch makes a number of changes to the crt0.S file in order to
support the ILP32 ABI.
Because the Angel APIs are kept the same between LP64 and ILP32, some
changes are needed to make sure the heap info can be obtained properly
from the HeapInfo Angel call.
The patch also fixes the argv handling where the pointers pushed to the
stack shall be 4-byte size when __ILP32__ is defined.
The gcc patches for ILP32 (including the one that defines __ILP32__)
will be sent shortly, but this patch can be committed independently.
OK for the trunk?
Thanks,
Yufeng
libgloss/
* aarch64/crt0.S (GEN_DWORD): New macro definition.
(PTR_REG): Ditto.
(PTR_SIZE): Ditto.
(PTR_LOG_SIZE): Ditto.
(start): Use GEN_DWORD to replace the .dword of HeapBase,
__bss_start__, __bss_end__, FUNCTION(_fini), env and
CommandLine; when __ILP32__ is defined, set the stack base to
the top end of the 32-bit address space if the returned value
from the Angel API call is larger than or equal to 4 GiB.
Also carry out sanity check on the heap base; abort if the
base is larger than or equal to 4 GiB. Use other new
macros in the instructions that processes the argv arrays.
(StackBase): New lable; replace __stack_base__.
(__stack_base__): Set with StackBase or StackBase + 4.
diff --git a/libgloss/aarch64/crt0.S b/libgloss/aarch64/crt0.S
index 601bb2b..1a5cabb 100644
--- a/libgloss/aarch64/crt0.S
+++ b/libgloss/aarch64/crt0.S
@@ -41,6 +41,36 @@
#define _fini __libc_fini_array
#endif
+/* In ELF64, the large addressing model is used and R_AARCH64_ABS64
+ reloc is generated to relocate a 64-bit address. Since 64-bit
+ relocation is not available in ELF32, in order to have
+ a single code path for both ELF64 and ELF32 classes, we synthesize
+ a 64-bit relocation by using R_AARCH64_P32_ABS32 on one of the two
+ .word directives, depending on the endianness. */
+
+.macro GEN_DWORD name
+#if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ .word \name
+ .word 0
+#elif defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ .word 0
+ .word \name
+#else
+ .dword \name
+#endif
+.endm
+
+/* Help tackle the pointer size difference between ELF64 and ELF32. */
+#ifdef __ILP32__
+#define PTR_REG(n) w##n
+#define PTR_SIZE 4
+#define PTR_LOG_SIZE 2
+#else
+#define PTR_REG(n) x##n
+#define PTR_SIZE 8
+#define PTR_LOG_SIZE 3
+#endif
+
.text
.macro FUNC_START name
.global \name
@@ -71,10 +101,33 @@
command line options to the AEM in order to define the values
exposed here in the HeapInfo Angel call. */
ldr x0, .LC0 /* point at returned values */
- ldr x0, [x0, #8] /* get heap_limit */
+ ldr x1, [x0, #8] /* get heap_limit */
+#ifdef __ILP32__
+ /* Sanity check on the heap base. */
+ ldr x0, [x0] /* get heap_base */
+ tst x0, #0xffffffff00000000
+ beq 1f
+ /* Exit with 1 if the heap base is not within the 32-bit address
+ space. */
+ mov x0, ADP_Stopped_ApplicationExit & 0xff
+ movk x0, ADP_Stopped_ApplicationExit >> 16, lsl #16
+ adrp x1, HeapBase /* Reuse to construct the parameter block. */
+ add x1, x1, #:lo12:HeapBase
+ str x0, [x1]
+ mov x0, 1
+ str x0, [x1, #8]
+ mov w0, #AngelSVC_Reason_ReportException
+ AngelSVCAsm AngelSVC
+1:
+ /* For the sake of safety, set the stack base to the top end of
+ the 32-bit address space if the returned value from the
+ Angel API call is larger than or equal to 4 GiB. */
+ tst x1, #0xffffffff00000000
+ csinv w1, w1, wzr, eq
+#endif
/* Ensure quad-word stack alignment. */
- and x0, x0, #~15
+ and x0, x1, #~15
mov sp, x0
/* Setup an initial dummy frame with saved fp=0 and saved lr=0 */
@@ -114,7 +167,7 @@
ldr x2, .Lenvp /* envp */
/* Put NULL at end of argv array. */
- str x0, [x1, #-8]!
+ str PTR_REG (0), [x1, #-PTR_SIZE]!
/* Skip leading blanks. */
.Lnext: ldrb w3, [x8], #1
@@ -133,7 +186,7 @@
cinc x8, x8, eq
/* Push arg pointer to argv, and bump argc. */
- str x8, [x1, #-8]!
+ str PTR_REG (8), [x1, #-PTR_SIZE]!
add x0, x0, #1
/* Find end of arg string. */
@@ -149,14 +202,14 @@
/* Reverse argv array. */
.Lendstr:
- add x3, x1, #0 /* sp = &argv[0] */
- add x4, x1, w0, uxtw #3 /* ep = &argv[argc] */
+ add x3, x1, #0 /* sp = &argv[0] */
+ add x4, x1, w0, uxtw #PTR_LOG_SIZE /* ep = &argv[argc] */
cmp x4, x3
b.lo 2f
-1: ldr x5, [x4, #-8] /* x5 = ep[-1] */
- ldr x6, [x3] /* x6 = *sp */
- str x6, [x4, #-8]! /* *--ep = x6 */
- str x5, [x3], #8 /* *sp++ = x5 */
+1: ldr PTR_REG (5), [x4, #-PTR_SIZE] /* PTR_REG (5) = ep[-1] */
+ ldr PTR_REG (6), [x3] /* PTR_REG (6) = *sp */
+ str PTR_REG (6), [x4, #-PTR_SIZE]! /* *--ep = PTR_REG (6) */
+ str PTR_REG (5), [x3], #PTR_SIZE /* *sp++ = PTR_REG (5) */
cmp x4, x3
b.hi 1b
2:
@@ -177,27 +230,32 @@ FUNCTION (_cpu_init_hook):
.align 3
.LC0:
- .dword HeapBase
+ GEN_DWORD HeapBase
.LC1:
- .dword __bss_start__
+ GEN_DWORD __bss_start__
.LC2:
- .dword __bss_end__
+ GEN_DWORD __bss_end__
.Lfini:
- .dword FUNCTION(_fini)
+ GEN_DWORD FUNCTION(_fini)
.Lenvp:
- .dword env
+ GEN_DWORD env
.Lcmdline:
- .dword CommandLine
+ GEN_DWORD CommandLine
.dword 255
/* Workspace for Angel calls. */
.data
.align 3
/* Data returned by monitor SVC. */
+#if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ .set __stack_base__, StackBase + 4
+#else
+ .set __stack_base__, StackBase
+#endif
.global __stack_base__
HeapBase: .dword 0
HeapLimit: .dword 0
-__stack_base__: .dword 0
+StackBase: .dword 0
StackLimit: .dword 0
env: .dword 0 /* Dummy environment array */
CommandLine: .space 256,0 /* Maximum length of 255 chars handled. */