linker script 连接脚本
[root@centos7 aarch64-bare-metal-qemu]# gcc -c test64.c -o test64.o [root@centos7 aarch64-bare-metal-qemu]# as -c startup64.s -o startup64.o [root@centos7 aarch64-bare-metal-qemu]# ld -Ttest64.ld test64.o startup64.o -o test64.elf [root@centos7
[root@centos7 aarch64-bare-metal-qemu]# qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -kernel test64.elf
Hello world!
[root@centos7 aarch64-bare-metal-qemu]# objdump -s -d test64.o > test64.txt [root@centos7 aarch64-bare-metal-qemu]# objdump -s -d startup64.o > startup64.txt [root@centos7 aarch64-bare-metal-qemu]# objdump -s -d test64.elf > test64.elf.txt [root@centos7 aarch64-bare-metal-qemu]# cat test64.txt test64.o: file format elf64-littleaarch64 Contents of section .text: 0000 ff4300d1 e00700f9 08000014 0020a1d2 .C........... .. 0010 e10740f9 21004039 010000b9 e00740f9 ..@.!.@9......@. 0020 00040091 e00700f9 e00740f9 00004039 ..........@...@9 0030 1f001f6b c1feff54 ff430091 c0035fd6 ...k...T.C...._. 0040 fd7bbfa9 fd030091 00000090 00000091 .{.............. 0050 00000094 fd7bc1a8 c0035fd6 .....{...._. Contents of section .rodata: 0000 00000009 00000000 48656c6c 6f20776f ........Hello wo 0010 726c6421 0a00 rld!.. Contents of section .comment: 0000 00474343 3a202847 4e552920 342e382e .GCC: (GNU) 4.8. 0010 35203230 31353036 32332028 52656420 5 20150623 (Red 0020 48617420 342e382e 352d3434 2900 Hat 4.8.5-44). Contents of section .eh_frame: 0000 10000000 00000000 017a5200 04781e01 .........zR..x.. 0010 1b0c1f00 14000000 18000000 00000000 ................ 0020 40000000 00410e10 4e0e0000 20000000 @....A..N... ... 0030 30000000 00000000 1c000000 00410e10 0............A.. 0040 9d029e01 410d1d44 dedd0c1f 00000000 ....A..D........ Disassembly of section .text: 0000000000000000: 0: d10043ff sub sp, sp, #0x10 4: f90007e0 str x0, [sp,#8] 8: 14000008 b 28 0x28> c: d2a12000 mov x0, #0x9000000 // #150994944 10: f94007e1 ldr x1, [sp,#8] 14: 39400021 ldrb w1, [x1] 18: b9000001 str w1, [x0] 1c: f94007e0 ldr x0, [sp,#8] 20: 91000400 add x0, x0, #0x1 24: f90007e0 str x0, [sp,#8] 28: f94007e0 ldr x0, [sp,#8] 2c: 39400000 ldrb w0, [x0] 30: 6b1f001f cmp w0, wzr 34: 54fffec1 b.ne c 0xc> 38: 910043ff add sp, sp, #0x10 3c: d65f03c0 ret 0000000000000040 : 40: a9bf7bfd stp x29, x30, [sp,#-16]! 44: 910003fd mov x29, sp 48: 90000000 adrp x0, 0 4c: 91000000 add x0, x0, #0x0 50: 94000000 bl 0 54: a8c17bfd ldp x29, x30, [sp],#16 58: d65f03c0 ret [root@centos7 aarch64-bare-metal-qemu]# cat startup64.txt startup64.o: file format elf64-littleaarch64 Contents of section .text: 0000 9e000058 df030091 00000094 00000014 ...X............ 0010 00000000 00000000 ........ Disassembly of section .text: 0000000000000000 <_Reset>: 0: 5800009e ldr x30, 10 <_Reset+0x10> 4: 910003df mov sp, x30 8: 94000000 bl 0 c: 14000000 b c <_Reset+0xc> ... [root@centos7 aarch64-bare-metal-qemu]# cat test64.elf.txt test64.elf: file format elf64-littleaarch64 Contents of section .startup: 40000000 9e000058 df030091 14000094 00000014 ...X............ 40000010 e8100040 00000000 ...@.... Contents of section .text: 40000018 ff4300d1 e00700f9 08000014 0020a1d2 .C........... .. 40000028 e10740f9 21004039 010000b9 e00740f9 ..@.!.@9......@. 40000038 00040091 e00700f9 e00740f9 00004039 ..........@...@9 40000048 1f001f6b c1feff54 ff430091 c0035fd6 ...k...T.C...._. 40000058 fd7bbfa9 fd030091 00000090 00000291 .{.............. 40000068 ecffff97 fd7bc1a8 c0035fd6 .....{...._. Contents of section .rodata: 40000078 00000009 00000000 48656c6c 6f20776f ........Hello wo 40000088 726c6421 0a00 rld!.. Contents of section .eh_frame: 40000090 14000000 00000000 017a5200 04781e01 .........zR..x.. 400000a0 1b0c1f00 00000000 14000000 1c000000 ................ 400000b0 68ffffff 40000000 00410e10 4e0e0000 h...@....A..N... 400000c0 24000000 34000000 90ffffff 1c000000 $...4........... 400000d0 00410e10 9d029e01 410d1d44 dedd0c1f .A......A..D.... 400000e0 00000000 00000000 ........ Contents of section .comment: 0000 4743433a 2028474e 55292034 2e382e35 GCC: (GNU) 4.8.5 0010 20323031 35303632 33202852 65642048 20150623 (Red H 0020 61742034 2e382e35 2d343429 00 at 4.8.5-44). Disassembly of section .startup: 0000000040000000 <_Reset>: 40000000: 5800009e ldr x30, 40000010 <_Reset+0x10> 40000004: 910003df mov sp, x30 40000008: 94000014 bl 40000058 4000000c: 14000000 b 4000000c <_Reset+0xc> 40000010: 400010e8 .word 0x400010e8 40000014: 00000000 .word 0x00000000 Disassembly of section .text: 0000000040000018 : 40000018: d10043ff sub sp, sp, #0x10 4000001c: f90007e0 str x0, [sp,#8] 40000020: 14000008 b 40000040 0x28> 40000024: d2a12000 mov x0, #0x9000000 // #150994944 40000028: f94007e1 ldr x1, [sp,#8] 4000002c: 39400021 ldrb w1, [x1] 40000030: b9000001 str w1, [x0] 40000034: f94007e0 ldr x0, [sp,#8] 40000038: 91000400 add x0, x0, #0x1 4000003c: f90007e0 str x0, [sp,#8] 40000040: f94007e0 ldr x0, [sp,#8] 40000044: 39400000 ldrb w0, [x0] 40000048: 6b1f001f cmp w0, wzr 4000004c: 54fffec1 b.ne 40000024 0xc> 40000050: 910043ff add sp, sp, #0x10 40000054: d65f03c0 ret 0000000040000058 : 40000058: a9bf7bfd stp x29, x30, [sp,#-16]! 4000005c: 910003fd mov x29, sp 40000060: 90000000 adrp x0, 40000000 <_Reset> 40000064: 91020000 add x0, x0, #0x80 40000068: 97ffffec bl 40000018 4000006c: a8c17bfd ldp x29, x30, [sp],#16 40000070: d65f03c0 ret
链接脚本和栈指针
C函数栈指针
链接地址
- The address to load the program to should be changed too. '0x10000' is not valid RAM or ROM address for -M virt. According to virt.c, '0x40000000' is OK to use. So my linker script is modified and named test64.ld
0x40000000
[root@centos7 aarch64-bare-metal-qemu]# cat test64.ld ENTRY(_Reset) SECTIONS { . = 0x40000000; .startup . : { startup64.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; }
Disassembly of section .startup: 0000000040000000 <_Reset>: 40000000: 5800009e ldr x30, 40000010 <_Reset+0x10> 40000004: 910003df mov sp, x30 40000008: 94000014 bl 400000584000000c: 14000000 b 4000000c <_Reset+0xc> 40000010: 400010e8 .word 0x400010e8 40000014: 00000000 .word 0x00000000 Disassembly of section .text: 0000000040000018 : 40000018: d10043ff sub sp, sp, #0x10 4000001c: f90007e0 str x0, [sp,#8] 40000020: 14000008 b 40000040 0x28> 40000024: d2a12000 mov x0, #0x9000000 // #150994944 40000028: f94007e1 ldr x1, [sp,#8] 4000002c: 39400021 ldrb w1, [x1] 40000030: b9000001 str w1, [x0] 40000034: f94007e0 ldr x0, [sp,#8] 40000038: 91000400 add x0, x0, #0x1 4000003c: f90007e0 str x0, [sp,#8] 40000040: f94007e0 ldr x0, [sp,#8] 40000044: 39400000 ldrb w0, [x0] 40000048: 6b1f001f cmp w0, wzr 4000004c: 54fffec1 b.ne 40000024 0xc> 40000050: 910043ff add sp, sp, #0x10 40000054: d65f03c0 ret 0000000040000058 : 40000058: a9bf7bfd stp x29, x30, [sp,#-16]! 4000005c: 910003fd mov x29, sp 40000060: 90000000 adrp x0, 40000000 <_Reset> 40000064: 91020000 add x0, x0, #0x80 40000068: 97ffffec bl 40000018 4000006c: a8c17bfd ldp x29, x30, [sp],#16 40000070: d65f03c0 ret
链接地址0x10000
[root@centos7 aarch64-bare-metal-qemu]# cat test64.ld ENTRY(_Reset) SECTIONS { . = 0x10000; .startup . : { startup64.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; }
[root@centos7 aarch64-bare-metal-qemu]# ld -Ttest64.ld test64.o startup64.o -o test64.elf [root@centos7 aarch64-bare-metal-qemu]# objdump -s -d test64.elf > test64.elf.txt2 [root@centos7 aarch64-bare-metal-qemu]# cat test64.elf.txt2
[root@centos7 aarch64-bare-metal-qemu]# cat test64.elf.txt2 test64.elf: file format elf64-littleaarch64 Contents of section .startup: 10000 9e000058 df030091 14000094 00000014 ...X............ 10010 e8100100 00000000 ........ Contents of section .text: 10018 ff4300d1 e00700f9 08000014 0020a1d2 .C........... .. 10028 e10740f9 21004039 010000b9 e00740f9 ..@.!.@9......@. 10038 00040091 e00700f9 e00740f9 00004039 ..........@...@9 10048 1f001f6b c1feff54 ff430091 c0035fd6 ...k...T.C...._. 10058 fd7bbfa9 fd030091 00000090 00000291 .{.............. 10068 ecffff97 fd7bc1a8 c0035fd6 .....{...._. Contents of section .rodata: 10078 00000009 00000000 48656c6c 6f20776f ........Hello wo 10088 726c6421 0a00 rld!.. Contents of section .eh_frame: 10090 14000000 00000000 017a5200 04781e01 .........zR..x.. 100a0 1b0c1f00 00000000 14000000 1c000000 ................ 100b0 68ffffff 40000000 00410e10 4e0e0000 h...@....A..N... 100c0 24000000 34000000 90ffffff 1c000000 $...4........... 100d0 00410e10 9d029e01 410d1d44 dedd0c1f .A......A..D.... 100e0 00000000 00000000 ........ Contents of section .comment: 0000 4743433a 2028474e 55292034 2e382e35 GCC: (GNU) 4.8.5 0010 20323031 35303632 33202852 65642048 20150623 (Red H 0020 61742034 2e382e35 2d343429 00 at 4.8.5-44). Disassembly of section .startup: 0000000000010000 <_Reset>: 10000: 5800009e ldr x30, 10010 <_Reset+0x10> 10004: 910003df mov sp, x30 10008: 94000014 bl 100581000c: 14000000 b 1000c <_Reset+0xc> 10010: 000110e8 .word 0x000110e8 10014: 00000000 .word 0x00000000 Disassembly of section .text: 0000000000010018 : 10018: d10043ff sub sp, sp, #0x10 1001c: f90007e0 str x0, [sp,#8] 10020: 14000008 b 10040 0x28> 10024: d2a12000 mov x0, #0x9000000 // #150994944 10028: f94007e1 ldr x1, [sp,#8] 1002c: 39400021 ldrb w1, [x1] 10030: b9000001 str w1, [x0] 10034: f94007e0 ldr x0, [sp,#8] 10038: 91000400 add x0, x0, #0x1 1003c: f90007e0 str x0, [sp,#8] 10040: f94007e0 ldr x0, [sp,#8] 10044: 39400000 ldrb w0, [x0] 10048: 6b1f001f cmp w0, wzr 1004c: 54fffec1 b.ne 10024 0xc> 10050: 910043ff add sp, sp, #0x10 10054: d65f03c0 ret 0000000000010058 : 10058: a9bf7bfd stp x29, x30, [sp,#-16]! 1005c: 910003fd mov x29, sp 10060: 90000000 adrp x0, 10000 <_Reset> 10064: 91020000 add x0, x0, #0x80 10068: 97ffffec bl 10018 1006c: a8c17bfd ldp x29, x30, [sp],#16 10070: d65f03c0 ret
没有helloworld 输出
[root@centos7 aarch64-bare-metal-qemu]# qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -kernel test64.elf
Killed
heap
[root@centos7 aarch64-bare-metal-qemu]# cat test64.ld ENTRY(_Reset) SECTIONS { . = 0x40000000; .startup . : { startup64.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); heap_low = .; /* for _sbrk */ . = . + 0x10000; /* 64kB of heap memory */ heap_top = .; /* for _sbrk */ . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; }
[root@centos7 aarch64-bare-metal-qemu]# ld -Ttest64.ld test64.o startup64.o -o test64.elf
[root@centos7 aarch64-bare-metal-qemu]# ld -Ttest64.ld test64.o startup64.o -o test64.elf [root@centos7 aarch64-bare-metal-qemu]# objdump -s -d test64.elf > test64.elf.txt3 [root@centos7 aarch64-bare-metal-qemu]# cat test64.elf.txt3 test64.elf: file format elf64-littleaarch64 Contents of section .startup: 40000000 9e000058 df030091 14000094 00000014 ...X............ 40000010 e8100140 00000000 ...@.... Contents of section .text: 40000018 ff4300d1 e00700f9 08000014 0020a1d2 .C........... .. 40000028 e10740f9 21004039 010000b9 e00740f9 ..@.!.@9......@. 40000038 00040091 e00700f9 e00740f9 00004039 ..........@...@9 40000048 1f001f6b c1feff54 ff430091 c0035fd6 ...k...T.C...._. 40000058 fd7bbfa9 fd030091 00000090 00000291 .{.............. 40000068 ecffff97 fd7bc1a8 c0035fd6 .....{...._. Contents of section .rodata: 40000078 00000009 00000000 48656c6c 6f20776f ........Hello wo 40000088 726c6421 0a00 rld!.. Contents of section .eh_frame: 40000090 14000000 00000000 017a5200 04781e01 .........zR..x.. 400000a0 1b0c1f00 00000000 14000000 1c000000 ................ 400000b0 68ffffff 40000000 00410e10 4e0e0000 h...@....A..N... 400000c0 24000000 34000000 90ffffff 1c000000 $...4........... 400000d0 00410e10 9d029e01 410d1d44 dedd0c1f .A......A..D.... 400000e0 00000000 00000000 ........ Contents of section .comment: 0000 4743433a 2028474e 55292034 2e382e35 GCC: (GNU) 4.8.5 0010 20323031 35303632 33202852 65642048 20150623 (Red H 0020 61742034 2e382e35 2d343429 00 at 4.8.5-44). Disassembly of section .startup: 0000000040000000 <_Reset>: 40000000: 5800009e ldr x30, 40000010 <_Reset+0x10> 40000004: 910003df mov sp, x30 40000008: 94000014 bl 400000584000000c: 14000000 b 4000000c <_Reset+0xc> 40000010: 400110e8 .word 0x400110e8 40000014: 00000000 .word 0x00000000 Disassembly of section .text: 0000000040000018 : 40000018: d10043ff sub sp, sp, #0x10 4000001c: f90007e0 str x0, [sp,#8] 40000020: 14000008 b 40000040 0x28> 40000024: d2a12000 mov x0, #0x9000000 // #150994944 40000028: f94007e1 ldr x1, [sp,#8] 4000002c: 39400021 ldrb w1, [x1] 40000030: b9000001 str w1, [x0] 40000034: f94007e0 ldr x0, [sp,#8] 40000038: 91000400 add x0, x0, #0x1 4000003c: f90007e0 str x0, [sp,#8] 40000040: f94007e0 ldr x0, [sp,#8] 40000044: 39400000 ldrb w0, [x0] 40000048: 6b1f001f cmp w0, wzr 4000004c: 54fffec1 b.ne 40000024 0xc> 40000050: 910043ff add sp, sp, #0x10 40000054: d65f03c0 ret 0000000040000058 : 40000058: a9bf7bfd stp x29, x30, [sp,#-16]! 4000005c: 910003fd mov x29, sp 40000060: 90000000 adrp x0, 40000000 <_Reset> 40000064: 91020000 add x0, x0, #0x80 40000068: 97ffffec bl 40000018 4000006c: a8c17bfd ldp x29, x30, [sp],#16 40000070: d65f03c0 ret
链接脚本定义堆
[root@centos7 aarch64-bare-metal-qemu]# gcc -c test64.c -o test64.o -nostdlib test64.c: In function ‘_sbrk’: test64.c:40:2: warning: passing argument 1 of ‘print_pointer’ makes pointer from integer without a cast [enabled by default] print_pointer(heap_low); ^ test64.c:12:6: note: expected ‘const char *’ but argument is of type ‘char’ void print_pointer(const char *s) { ^ test64.c:41:2: warning: passing argument 1 of ‘print_pointer’ makes pointer from integer without a cast [enabled by default] print_pointer(heap_top); ^ test64.c:12:6: note: expected ‘const char *’ but argument is of type ‘char’ void print_pointer(const char *s) { ^ test64.c:51:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] return (caddr_t) prev_heap_end; ^ [root@centos7 aarch64-bare-metal-qemu]# as -c startup64.s -o startup64.o [root@centos7 aarch64-bare-metal-qemu]# ld -Ttest64.ld test64.o startup64.o -o test64.elf [root@centos7 aarch64-bare-metal-qemu]# qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -kernel test64.elf Hello world! 0000 0000 Killed [root@centos7 aarch64-bare-metal-qemu]# ls ans ans.o ans.s hello hello.o hello.txt libc.s LICENSE Makefile README.md startup64.o startup64.s startup64.txt sys sys.o sys.s test64.c test64.elf test64.elf.txt test64.elf.txt2 test64.elf.txt3 test64.ld test64.o test64.txt [root@centos7 aarch64-bare-metal-qemu]# cat test64.ld ENTRY(_Reset) SECTIONS { . = 0x40000000; .startup . : { startup64.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); heap_low = .; /* for _sbrk */ . = . + 0x10000; /* 64kB of heap memory */ heap_top = .; /* for _sbrk */ . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; }
volatile unsigned int * const UART0DR = (unsigned int *) 0x09000000; typedef unsigned int caddr_t; caddr_t _sbrk(int incr) ; void print_uart0(const char *s) { while(*s != '\0') { /* Loop until end of string */ *UART0DR = (unsigned int)(*s); /* Transmit char */ s++; /* Next char */ } } void print_pointer(const char *s) { int new_value[4]; char buf_temp[4]; int temp,x; for (x = 0; x < 4; x++) { new_value[x] = temp % 10; temp = temp / 10; buf_temp[x] = new_value[x] +48; *UART0DR = (unsigned int)(buf_temp[x]); /* Transmit char */ } *UART0DR = '\n'; /* Transmit char */ } void c_entry() { print_uart0("Hello world!\n"); _sbrk(16); } char *heap_end = 0; caddr_t _sbrk(int incr) { extern char heap_low; /* Defined by the linker */ extern char heap_top; /* Defined by the linker */ char *prev_heap_end; if (heap_end == 0) { heap_end = &heap_low; } print_pointer(heap_low); print_pointer(heap_top); prev_heap_end = heap_end; if (heap_end + incr > &heap_top) { /* Heap and stack collision */ return (caddr_t)0; } heap_end += incr; return (caddr_t) prev_heap_end; }