* Stack pointer is 0 in a bare metal AArch64 program @ 2020-05-11 2:31 Simon Marchi 2020-05-11 4:04 ` Orlando Arias 0 siblings, 1 reply; 5+ messages in thread From: Simon Marchi @ 2020-05-11 2:31 UTC (permalink / raw) To: newlib Hi, Following this thread: https://sourceware.org/pipermail/gdb/2020-May/048516.html I've been trying to build a bare metal AArch64 program and run it in the binutils-gdb simulator. The program is just an empty main function, and it is compiled with: $ aarch64-none-elf-gcc test.c -specs=nosys.specs -g3 -O0 When I try to run it, I get: $ ./sim/aarch64/run --trace=on --trace-disasm=on ./sim/aarch64/a.out memory: ERROR: executable is too big: ffffffffffffffff insn: pc = 400168 instr = 58000281 disasm: ldr x1, 0x00000000004001b8 memory: read of 0 (8 bytes) from 4001b8 insn: pc = 40016c instr = 927cec20 disasm: and x0, x1, #0xfffffffffffffff0 insn: pc = 400170 instr = 9100001f disasm: mov sp, x0 insn: pc = 400174 instr = d280001d disasm: mov x29, #0x0 // #0 insn: pc = 400178 instr = a9bf77fd disasm: stp x29, x29, [sp, #-16]! memory: write of 0 (8 bytes) to fffffffffffffff0 core: 8 byte write to unmapped address 0xfffffff0 at 0x0 program stopped with signal 11 (Segmentation fault). I understand that these instructions try to set up the stack pointer, reading its initial value from 0x4001b8. This value happens to be 0, not a good value for a stack pointer. I'm guessing that these instructions come from crt0.S, from newlib/libgloss: https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=libgloss/aarch64/crt0.S;h=f831be12e6a17e67908dba3e6ffbe5de4e3b58a0;hb=HEAD#l141 With the steps I've done, is it expected that the stack pointer is 0? Is there something I'm missing to make it have some value that makes more sense? Simon ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Stack pointer is 0 in a bare metal AArch64 program 2020-05-11 2:31 Stack pointer is 0 in a bare metal AArch64 program Simon Marchi @ 2020-05-11 4:04 ` Orlando Arias 2020-05-11 12:40 ` Joel Sherrill 0 siblings, 1 reply; 5+ messages in thread From: Orlando Arias @ 2020-05-11 4:04 UTC (permalink / raw) To: newlib [-- Attachment #1.1: Type: text/plain, Size: 1519 bytes --] Greetings, On 5/10/20 10:31 PM, Simon Marchi via Newlib wrote: > $ ./sim/aarch64/run --trace=on --trace-disasm=on ./sim/aarch64/a.out > memory: ERROR: executable is too big: ffffffffffffffff > insn: pc = 400168 instr = 58000281 > disasm: ldr x1, 0x00000000004001b8 > memory: read of 0 (8 bytes) from 4001b8 > insn: pc = 40016c instr = 927cec20 > disasm: and x0, x1, #0xfffffffffffffff0 > insn: pc = 400170 instr = 9100001f > disasm: mov sp, x0 > insn: pc = 400174 instr = d280001d > disasm: mov x29, #0x0 // #0 > insn: pc = 400178 instr = a9bf77fd > disasm: stp x29, x29, [sp, #-16]! Within libgloss for Aarch64, the stack is initialized using a weak symbol with the value of 0: .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 .Lstack: GEN_DWORD __stack .weak __stack If the linker script you are utilizing does not define __stack, then the weak symbol is used. As an aside, this behavior in libgloss has always annoyed me. When working with Cortex-M cores [both ARMv7-M and ARMv8-M], msp is initialized using the value stored in address 0 of the memory map by the hardware. Yes, the application is free to change it afterwards, but it just seems redundant to me. Cheers, Orlando. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Stack pointer is 0 in a bare metal AArch64 program 2020-05-11 4:04 ` Orlando Arias @ 2020-05-11 12:40 ` Joel Sherrill 2020-05-11 12:49 ` Christophe Lyon 2020-05-11 16:00 ` Orlando Arias 0 siblings, 2 replies; 5+ messages in thread From: Joel Sherrill @ 2020-05-11 12:40 UTC (permalink / raw) To: Orlando Arias; +Cc: Newlib On Sun, May 10, 2020 at 11:04 PM Orlando Arias via Newlib < newlib@sourceware.org> wrote: > Greetings, > > On 5/10/20 10:31 PM, Simon Marchi via Newlib wrote: > > $ ./sim/aarch64/run --trace=on --trace-disasm=on ./sim/aarch64/a.out > > memory: ERROR: executable is too big: ffffffffffffffff > > insn: pc = 400168 instr = 58000281 > > disasm: ldr x1, 0x00000000004001b8 > > memory: read of 0 (8 bytes) from 4001b8 > > insn: pc = 40016c instr = 927cec20 > > disasm: and x0, x1, #0xfffffffffffffff0 > > insn: pc = 400170 instr = 9100001f > > disasm: mov sp, x0 > > insn: pc = 400174 instr = d280001d > > disasm: mov x29, #0x0 // #0 > > insn: pc = 400178 instr = a9bf77fd > > disasm: stp x29, x29, [sp, #-16]! > > Within libgloss for Aarch64, the stack is initialized using a weak > symbol with the value of 0: > > .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 > > .Lstack: > GEN_DWORD __stack > .weak __stack > > > If the linker script you are utilizing does not define __stack, then the > weak symbol is used. > > As an aside, this behavior in libgloss has always annoyed me. When > working with Cortex-M cores [both ARMv7-M and ARMv8-M], msp is > initialized using the value stored in address 0 of the memory map by the > hardware. Yes, the application is free to change it afterwards, but it > just seems redundant to me. > Then why isn't a linker script provided which provides this? This behavior is in sharp contrast with other CPU-elf targets with libgloss support. They can produce executables out of the box with no requirements like this. --joel RTEMS > > Cheers, > Orlando. > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Stack pointer is 0 in a bare metal AArch64 program 2020-05-11 12:40 ` Joel Sherrill @ 2020-05-11 12:49 ` Christophe Lyon 2020-05-11 16:00 ` Orlando Arias 1 sibling, 0 replies; 5+ messages in thread From: Christophe Lyon @ 2020-05-11 12:49 UTC (permalink / raw) To: joel; +Cc: Orlando Arias, Newlib Hi, On Mon, 11 May 2020 at 14:47, Joel Sherrill <joel@rtems.org> wrote: > > On Sun, May 10, 2020 at 11:04 PM Orlando Arias via Newlib < > newlib@sourceware.org> wrote: > > > Greetings, > > > > On 5/10/20 10:31 PM, Simon Marchi via Newlib wrote: > > > $ ./sim/aarch64/run --trace=on --trace-disasm=on ./sim/aarch64/a.out > > > memory: ERROR: executable is too big: ffffffffffffffff > > > insn: pc = 400168 instr = 58000281 > > > disasm: ldr x1, 0x00000000004001b8 > > > memory: read of 0 (8 bytes) from 4001b8 > > > insn: pc = 40016c instr = 927cec20 > > > disasm: and x0, x1, #0xfffffffffffffff0 > > > insn: pc = 400170 instr = 9100001f > > > disasm: mov sp, x0 > > > insn: pc = 400174 instr = d280001d > > > disasm: mov x29, #0x0 // #0 > > > insn: pc = 400178 instr = a9bf77fd > > > disasm: stp x29, x29, [sp, #-16]! > > > > Within libgloss for Aarch64, the stack is initialized using a weak > > symbol with the value of 0: > > > > .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 > > > > .Lstack: > > GEN_DWORD __stack > > .weak __stack > > > > > > If the linker script you are utilizing does not define __stack, then the > > weak symbol is used. > > > > As an aside, this behavior in libgloss has always annoyed me. When > > working with Cortex-M cores [both ARMv7-M and ARMv8-M], msp is > > initialized using the value stored in address 0 of the memory map by the > > hardware. Yes, the application is free to change it afterwards, but it > > just seems redundant to me. > > > > Then why isn't a linker script provided which provides this? This behavior > is in sharp contrast with other CPU-elf targets with libgloss support. They > can produce executables out of the box with no requirements like this. > I think this is also related to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66203 > --joel > RTEMS > > > > > > > Cheers, > > Orlando. > > > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Stack pointer is 0 in a bare metal AArch64 program 2020-05-11 12:40 ` Joel Sherrill 2020-05-11 12:49 ` Christophe Lyon @ 2020-05-11 16:00 ` Orlando Arias 1 sibling, 0 replies; 5+ messages in thread From: Orlando Arias @ 2020-05-11 16:00 UTC (permalink / raw) To: joel; +Cc: Newlib [-- Attachment #1.1: Type: text/plain, Size: 3521 bytes --] Greetings, On 5/11/20 8:40 AM, Joel Sherrill wrote: > Then why isn't a linker script provided which provides this? This behavior > is in sharp contrast with other CPU-elf targets with libgloss support. They > can produce executables out of the box with no requirements like this. I am afraid I do not have a good answer for this. A cursory look indicates that the default linker script for Aarch64 is being provided by ld from binutils [or whatever other linker is being used], and not newlib. The linker script in question may not fit the requirements of the simulator, or vice versa. I believe a more proper question would be ``why does the default linker script not create a binary that is readily runnable in the simulator?'' but I can not say whether this is proper, and I do not have an answer either. For actual hardware platforms, the norm is to provide your own linker script. This is because the linker script helps tailor the binary to the memory map of the device. For example, in the M profile for both ARMv{6,7} and ARMv8, the SRAM region starts at address 0x20000000 and can for up to 512 MiB [excluding any bit banding regions that may be present]. However, an MCU using these architectures will have various amounts of memory. The linker script then sets the stack pointer by providing a symbol that gets populated at address 0 of the vector table. In my linker script for an STM32F407, I have: OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(__reset) /* the hardware does not care about this */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM (rxw) : ORIGIN = 0x20000000, LENGTH = 128K } SECTIONS { .vector_table : { KEEP(*(.vector_table)) } > FLASH /* [snip] */ __ram_end = ORIGIN(RAM) + LENGTH(RAM); /* initial msp value */ } Then, in my initialization code: .syntax unified .thumb .section .vector_table, "aw" .globl __vector_table __vector_table: .word __ram_end /* initial stack pointer */ .word __reset /* reset vector/entry point */ .word __vector_2 /* non-maskable interrupt */ /* rest of the vector table */ .section .text .global __reset .type __reset, %function __reset: /* initialize .data region */ ldr r0, =__data_start ldr r1, =__data_end ldr r2, =__data_init /* more initialization code */ When the CPU boots, it reads the vector table, initializes msp [main stack pointer] using the value in entry 0, then initializes pc using the value in entry 1. It then goes into thread mode and starts executing the __reset vector. Yes, this completely bypasses libgloss, but I don't really use most of newlib's or libgloss's facilities on my projects, only the sporadic call to some basic C function. I believe the simulator instead uses whatever the ELF says the entry point is and initializes pc using that value. Technically speaking, on actual freestanding hardware we use whatever CMSIS package the vendor gives us. The CMSIS package provides both vector table initialization, and memory region initialization, completely bypassing the C runtime code in libgloss. CMSIS can go to do other things, like enabling the FPU, and setting up the PLL for the CPU to achieve a desired frequency. For the most part, CMSIS-Core is standard across vendors, with only minor variations in the vector table creation, peripheral/clock initialization code, and linker scripts. Cheers, Orlando. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-05-11 16:00 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-05-11 2:31 Stack pointer is 0 in a bare metal AArch64 program Simon Marchi 2020-05-11 4:04 ` Orlando Arias 2020-05-11 12:40 ` Joel Sherrill 2020-05-11 12:49 ` Christophe Lyon 2020-05-11 16:00 ` Orlando Arias
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).