Arm 为什么这个链接器脚本会产生一个地址?

Arm 为什么这个链接器脚本会产生一个地址?,arm,llvm,stm32,ld,zig,Arm,Llvm,Stm32,Ld,Zig,我正在为ARM Cortex-M0微控制器(特别是作为STM32 Discovery开发板一部分的STM32F072B)编写一些固件代码 我的链接器脚本没有任何特殊功能,它只是填充向量表,然后包含代码中的所有文本和数据部分: OUTPUT_FORMAT("elf32-littlearm") MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 16K FLASH (r) : ORIGIN = 0x08000000

我正在为ARM Cortex-M0微控制器(特别是作为STM32 Discovery开发板一部分的STM32F072B)编写一些固件代码

我的链接器脚本没有任何特殊功能,它只是填充向量表,然后包含代码中的所有文本和数据部分:

OUTPUT_FORMAT("elf32-littlearm")

MEMORY {
    ROM (rx) : ORIGIN = 0x00000000, LENGTH = 16K
    FLASH (r) : ORIGIN = 0x08000000, LENGTH = 64K
    RAM (rw)  : ORIGIN = 0x20000000, LENGTH = 16K
}

ENTRY(_start)

PROVIDE(__stack_top = ORIGIN(RAM) + LENGTH(RAM));


SECTIONS {

    .vector_table : {
        LONG(__stack_top);                  /* 00 */
        LONG(_start);                       /* 04 */  
        LONG(dummy_isr);                    /* 08 */
        LONG(dummy_isr);                    /* 0C */
        LONG(dummy_isr);                    /* 10 */
        LONG(dummy_isr);                    /* 14 */
        LONG(dummy_isr);                    /* 18 */
        LONG(dummy_isr);                    /* 1C */
        LONG(dummy_isr);                    /* 20 */
        LONG(dummy_isr);                    /* 24 */
        LONG(dummy_isr);                    /* 28 */
        LONG(dummy_isr);                    /* 2C */
        LONG(dummy_isr);                    /* 30 */
        LONG(dummy_isr);                    /* 34 */
        LONG(dummy_isr);                    /* 38 */
        LONG(dummy_isr);                    /* 3C */
        LONG(dummy_isr);                    /* 40 */
        LONG(dummy_isr);                    /* 44 */
        LONG(dummy_isr);                    /* 48 */
        LONG(dummy_isr);                    /* 4C */
        LONG(dummy_isr);                    /* 50 */
        LONG(dummy_isr);                    /* 54 */
        LONG(dummy_isr);                    /* 58 */
        LONG(dummy_isr);                    /* 5C */
        LONG(dummy_isr);                    /* 60 */
        LONG(dummy_isr);                    /* 64 */
        LONG(dummy_isr);                    /* 68 */
        LONG(dummy_isr);                    /* 6C */
        LONG(dummy_isr);                    /* 70 */
        LONG(dummy_isr);                    /* 74 */
        LONG(dummy_isr);                    /* 78 */
        LONG(dummy_isr);                    /* 7C */
        LONG(dummy_isr);                    /* 80 */
        LONG(dummy_isr);                    /* 84 */
        LONG(dummy_isr);                    /* 88 */
        LONG(dummy_isr);                    /* 8C */
        LONG(dummy_isr);                    /* 90 */
        LONG(dummy_isr);                    /* 94 */
        LONG(dummy_isr);                    /* 98 */
        LONG(dummy_isr);                    /* 9C */
        LONG(dummy_isr);                    /* A0 */
        LONG(dummy_isr);                    /* A4 */
        LONG(dummy_isr);                    /* A8 */
        LONG(dummy_isr);                    /* AC */
        LONG(dummy_isr);                    /* B0 */
        LONG(dummy_isr);                    /* B4 */
        LONG(dummy_isr);                    /* B8 */
        LONG(dummy_isr);                    /* BC */
    } > ROM AT > FLASH
    
    .text : {
        *(.text*)
    } > ROM AT > FLASH

    .rodata : {
        *(.rodata*)
        *(.data.rel.ro)
    } > FLASH

    .bss (NOLOAD) : {
        *(.bss*)
        *(COMMON)
    } > RAM

    .data : {
        *(.data*)
    } > RAM

    .ARM.exidx : {
       *(.ARM.exidx)
    } > FLASH

}
当我构建并链接ELF文件并转储符号时,我注意到最后出现在
.vector_table
部分的地址以及ELF入口点都被一个关闭:

[shell]$ llvm-objdump --syms zig-cache/bin/main-flash 

zig-cache/bin/main-flash:       file format elf32-littlearm

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 main-flash
0000013c l       .text  00000000 $d.1
000000c0 l       .text  00000000 $t.0
000000c4 g     F .text  00000088 _start
000000c0 g     F .text  00000002 dummy_isr
20004000 g       *ABS*  00000000 __stack_top

符号表显示0xC4处的
\u start
,而链接器脚本中定义为
\u start
的ELF入口点设置为0xC5。类似地,写入向量表的
dummy_isr
的地址也会被关闭1(
dummy_isr
符号定义为0xC0,而0xC1由链接器写入向量表)。对
.text
的反汇编确认
\u dummy\u isr
\u start
分别从0xC0和0xC4开始,因此链接器正在写入的地址是错误的:

[shell]$ llvm-objdump --disassemble --section=.text zig-cache/bin/main-flash 
                                                               
zig-cache/bin/main-flash:       file format elf32-littlearm
                                                               

Disassembly of section .text:
                                                               
000000c0 <dummy_isr>:                                          
      c0: fe e7         b       #-4 <dummy_isr>   
      c2: c0 46         mov     r8, r8            
                               
000000c4 <_start>:
      c4: 82 b0         sub     sp, #8
      c6: 01 23         movs    r3, #1
      c8: d8 04         lsls    r0, r3, #19
      ca: 1c 49         ldr     r1, [pc, #112]
...

[shell]$llvm objdump--discompose--section=.text zig cache/bin/main flash
zig缓存/bin/main闪存:文件格式elf32 littlearm
第节的分解。正文:
000000c0:
c0:fe e7 b#-4
c2:c0 46 mov r8,r8
000000 C4:
c4:82 b0子sp,#8
c6:01 23 movs r3,#1
c8:d8 04 lsls r0,r3,#19
ca:1c 49 ldr r1,[pc,#112]
...

0xC1和0xC5甚至不是有效指令的地址,它们都在指令的中间。什么会导致这种差异?

这被称为“互通地址”

地址的最低有效位指示目标指令是ARM(0)还是Thumb(1)。获取的地址始终将LSB设置为零

由于此平台仅在Thumb模式下工作,所有矢量地址以及BX和BLX指令使用的地址必须为奇数(X表示(ex)更改指令集)。

这称为“互通地址”

地址的最低有效位指示目标指令是ARM(0)还是Thumb(1)。获取的地址始终将LSB设置为零


由于此平台仅在Thumb模式下工作,因此所有向量地址以及BX和BLX指令使用的地址必须为奇数(X表示(ex)更改指令集)。

请参阅arm文档,向量必须位于处理器地址,或者使用一个。(lsbit设置,表示这是一个thumb函数)如果未设置lsbit,则您将得到一个错误这是否回答了您的问题?“所有其他条目的位[0]必须设置为1,因为该位定义了异常条目上的EPSR.T位。”“在异常条目上,如果相关向量表条目的位[0]为0,则执行第一条指令会导致硬故障。”查看arm文档,向量需要位于处理程序地址或使用一个。(lsbit设置,表示这是一个thumb函数)如果未设置lsbit,则您将得到一个错误这是否回答了您的问题?“所有其他条目的位[0]必须设置为1,因为该位定义了异常条目上的EPSR.T位。”“在异常条目上,如果相关向量表条目的位[0]为0,则执行第一条指令会导致硬故障。”这不是互通,这是异常处理,同样的原因,但bx和blx并没有在本文中使用。我没有说使用bx或blx,我说LSB的目的是相同的。ARM上任何LSB指示目标指令处理器模式的地址都被命名为“互通地址”。这不是互通地址,这是异常处理,原因类似,但在此上下文中不使用bx和blx。我没有说使用bx或blx,我说的是LSB的用途是相同的。ARM上任何LSB指示目标指令处理器模式的地址都称为“互通地址”。
[shell]$ readelf -h zig-cache/bin/main-flash 
ELF Header:
...
  Entry point address:               0xc5
[shell]$ llvm-objdump --disassemble --section=.text zig-cache/bin/main-flash 
                                                               
zig-cache/bin/main-flash:       file format elf32-littlearm
                                                               

Disassembly of section .text:
                                                               
000000c0 <dummy_isr>:                                          
      c0: fe e7         b       #-4 <dummy_isr>   
      c2: c0 46         mov     r8, r8            
                               
000000c4 <_start>:
      c4: 82 b0         sub     sp, #8
      c6: 01 23         movs    r3, #1
      c8: d8 04         lsls    r0, r3, #19
      ca: 1c 49         ldr     r1, [pc, #112]
...