链接的输出部分在地址上重叠



我有这个链接脚本测试。ld:

/* write for machine virt */
ENTRY(_Reset)
MEMORY
{
rm(rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
ram (rwx) : ORIGIN = 0x40000000, LENGTH = 0x40000000
}
SECTIONS
{
. = 0x10000;
.startup . : { startup.o(.startup) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}

和启动代码启动。s:

.section .startup
.global _Reset
_Reset:
ldr x5, stack_top
msr sp_el0, x5
bl c_entry
b .
test.c for print:
volatile unsigned int * const UART0DR = (unsigned int *)0x09000000;
void print_uart0(const char *s) {
while(*s != '') { /* Loop until end of string */
*UART0DR = (unsigned int)(*s); /* Transmit char */
s++; /* Next char */
}
}
void c_entry() {
print_uart0("Hello world!n");
}

这是我编译和链接程序的方法。

aarch64-elf-as startup.s -o startup.o
aarch64-elf-gcc -c -g test.c -o test.o
aarch64-elf-ld -T test.ld test.o startup.o -o test.elf
aarch64-elf-objcopy -O binary test.elf test.bin

当我对aarch64-none-elf-objdump -D test.elf的最终结果执行objdump时,我看到了这个结果:

test.elf:     file format elf64-littleaarch64

Disassembly of section .startup:
0000000000010000 <_Reset>:
10000:       58f88405        ldr     x5, 1080 <stack_top>
10004:       d5184105        msr     sp_el0, x5
10008:       97ffc00f        bl      44 <c_entry>
1000c:       14000000        b       1000c <_Reset+0xc>
Disassembly of section .text:
0000000000000000 <print_uart0>:
0:   d10043ff        sub     sp, sp, #0x10
4:   f90007e0        str     x0, [sp, #8]
8:   14000008        b       28 <print_uart0+0x28>
c:   f94007e0        ldr     x0, [sp, #8]
10:   39400001        ldrb    w1, [x0]
14:   d2a12000        mov     x0, #0x9000000                  // #150994944
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:   7100001f        cmp     w0, #0x0
34:   54fffec1        b.ne    c <print_uart0+0xc>  // b.any
38:   d503201f        nop
3c:   910043ff        add     sp, sp, #0x10
40:   d65f03c0        ret
0000000000000044 <c_entry>:
44:   a9bf7bfd        stp     x29, x30, [sp, #-16]!
48:   910003fd        mov     x29, sp
4c:   90000000        adrp    x0, 0 <print_uart0>
50:   9101c000        add     x0, x0, #0x70
54:   97ffffeb        bl      0 <print_uart0>
58:   d503201f        nop
5c:   a8c17bfd        ldp     x29, x30, [sp], #16
60:   d65f03c0        ret
Disassembly of section .rodata:
0000000000000068 <UART0DR>:
68:   09000000        .inst   0x09000000 ; undefined
6c:   00000000        .inst   0x00000000 ; undefined
70:   6c6c6548        ldnp    d8, d25, [x10, #-320]
74:   6f77206f        umlal2  v15.4s, v3.8h, v7.h[3]
78:   21646c72        .inst   0x21646c72 ; undefined
7c:   Address 0x000000000000007c is out of bounds.

我不知道为什么_Reset正确地位于0x10000,但是print_uart0和c_entry函数位于0x00000000。根据链接器脚本,.text部分不应该放在。startup部分之后吗?

_Reset位于0x10000,因为您的脚本明确地使用. = 0x10000;语句请求它。

你可能应该告诉链接器.startup应该放在,并且在开头,所有.text相关的东西:

/* write for machine virt */
ENTRY(_Reset)
MEMORY
{
rm(rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
ram (rwx) : ORIGIN = 0x40000000, LENGTH = 0x40000000
}
SECTIONS
{
.text : {
*(.startup)
*(.text)
}
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}

结果将是:

test.elf:     file format elf64-littleaarch64

Disassembly of section .text:
0000000000000000 <_Reset>:
0:   58008485    ldr x5, 1090 <stack_top>
4:   d5184105    msr sp_el0, x5
8:   94000014    bl  58 <c_entry>
c:   14000000    b   c <_Reset+0xc>
0000000000000010 <print_uart0>:
10:   d10043ff    sub sp, sp, #0x10
14:   f90007e0    str x0, [sp, #8]
18:   14000008    b   38 <print_uart0+0x28>
1c:   f94007e0    ldr x0, [sp, #8]
20:   39400001    ldrb    w1, [x0]
24:   d2a12000    mov x0, #0x9000000              // #150994944
28:   b9000001    str w1, [x0]
2c:   f94007e0    ldr x0, [sp, #8]
30:   91000400    add x0, x0, #0x1
34:   f90007e0    str x0, [sp, #8]
38:   f94007e0    ldr x0, [sp, #8]
3c:   39400000    ldrb    w0, [x0]
40:   7100001f    cmp w0, #0x0
44:   54fffec1    b.ne    1c <print_uart0+0xc>  // b.any
48:   d503201f    nop
4c:   d503201f    nop
50:   910043ff    add sp, sp, #0x10
54:   d65f03c0    ret
0000000000000058 <c_entry>:
58:   a9bf7bfd    stp x29, x30, [sp, #-16]!
5c:   910003fd    mov x29, sp
60:   90000000    adrp    x0, 0 <_Reset>
64:   91020000    add x0, x0, #0x80
68:   97ffffea    bl  10 <print_uart0>
6c:   d503201f    nop
70:   a8c17bfd    ldp x29, x30, [sp], #16
74:   d65f03c0    ret
Disassembly of section .rodata:
0000000000000078 <UART0DR>:
78:   09000000    .inst   0x09000000 ; undefined
7c:   00000000    udf #0
80:   6c6c6548    ldnp    d8, d25, [x10, #-320]
84:   6f77206f    umlal2  v15.4s, v3.8h, v7.h[3]
88:   21646c72    .inst   0x21646c72 ; undefined
8c:   Address 0x000000000000008c is out of bounds.

请注意,如果您希望您的代码从0x40000000开始,您必须在链接器脚本中通过添加> ram来指定.text部分的定义(.data部分也是如此):

/* write for machine virt */
ENTRY(_Reset)
MEMORY
{
rm(rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
ram (rwx) : ORIGIN = 0x40000000, LENGTH = 0x40000000
}
SECTIONS
{
.text : {
*(.startup)
*(.text)
} > ram
.data : {
*(.data)
} > ram
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}

结果将是:

test.elf:     file format elf64-littleaarch64

Disassembly of section .text:
0000000040000000 <_Reset>:
40000000:   58008485    ldr x5, 40001090 <stack_top>
40000004:   d5184105    msr sp_el0, x5
40000008:   94000014    bl  40000058 <c_entry>
4000000c:   14000000    b   4000000c <_Reset+0xc>
0000000040000010 <print_uart0>:
40000010:   d10043ff    sub sp, sp, #0x10
40000014:   f90007e0    str x0, [sp, #8]
40000018:   14000008    b   40000038 <print_uart0+0x28>
4000001c:   f94007e0    ldr x0, [sp, #8]
40000020:   39400001    ldrb    w1, [x0]
40000024:   d2a12000    mov x0, #0x9000000              // #150994944
40000028:   b9000001    str w1, [x0]
4000002c:   f94007e0    ldr x0, [sp, #8]
40000030:   91000400    add x0, x0, #0x1
40000034:   f90007e0    str x0, [sp, #8]
40000038:   f94007e0    ldr x0, [sp, #8]
4000003c:   39400000    ldrb    w0, [x0]
40000040:   7100001f    cmp w0, #0x0
40000044:   54fffec1    b.ne    4000001c <print_uart0+0xc>  // b.any
40000048:   d503201f    nop
4000004c:   d503201f    nop
40000050:   910043ff    add sp, sp, #0x10
40000054:   d65f03c0    ret
0000000040000058 <c_entry>:
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:   97ffffea    bl  40000010 <print_uart0>
4000006c:   d503201f    nop
40000070:   a8c17bfd    ldp x29, x30, [sp], #16
40000074:   d65f03c0    ret
Disassembly of section .rodata:
0000000040000078 <UART0DR>:
40000078:   09000000    .inst   0x09000000 ; undefined
4000007c:   00000000    udf #0
40000080:   6c6c6548    ldnp    d8, d25, [x10, #-320]
40000084:   6f77206f    umlal2  v15.4s, v3.8h, v7.h[3]
40000088:   21646c72    .inst   0x21646c72 ; undefined
4000008c:   Address 0x000000004000008c is out of bounds.

最新更新