如何从ARM组件中的位置无关代码(PIC)访问数据?

时间:2015-10-26 16:36:52

标签: assembly arm

我正在使用GCC选项// PersonMapper.java public class PersonMapper implements ResultSetMapper<Person> { public Person map(int index, ResultSet r, StatementContext ctx) throws SQLException { Person person = new Person(); person.setId(r.getInt("id")); person.setName(r.getString("name")); return person; } } -mpic-data-is-text-relative来生成与位置无关的代码。这适用于我的C代码。

但我也有需要使用PIC的汇编代码。问题是我找不到如何实现这个的例子。是否有一些ARM GCC程序集关键字,我是否需要设置自己的GOT表或是否有任何巧妙的技巧?

我正在尝试使用PIC从代码中获取变量:

-fpic

如上所述,在 .section .data @HWA_SWI_HND_DATA, "w" hwa_ext_reset_hnd: .word 0x00000000 .section .text @HWA_SWI_HND_CODE, "x" .code 32 .list .global hwa_reset_cb_attach hwa_reset_cb_attach: ldr r1, =hwa_ext_reset_hnd str r0, [r1] bx lr 调用中,我希望此地址获取为PIC。

2 个答案:

答案 0 :(得分:1)

Elf DATA遵循文本,并且可以在链接时知道数据的偏移量。您需要将PC添加到已知位置和数据之间的偏移量以访问数据。请参阅ARM ELFLinkers and loader chp8 by John Levine

显然,如果它由操作系统和加载程序托管,则需要使用平台的约定。以下内容是为裸机系统或您可以选择的地方编写的。

例如,

   .global hwa_reset_cb_attach
hwa_reset_cb_attach:
   adr r2, 1f                ; pc relative value of label '1'
   ldr r1, [r2]              ; offset between label and data to r1
   add r1, r1, r2            ; pc + offset
   str r0, [r1]              ; store to corrected address.
   bx lr
1: .word hwa_ext_reset_hnd-. ; offset from here to data fixed at link.

这适用于PIC代码,后面有数据。如果您有多次出现,可以创建一个宏来访问数据。如果有很多引用,可能更容易保持寄存器加载 .data 部分的开头。带有编译器选项-msingle-pic-base-mpic-register= reg 静态基础; 静态基础通常为r9。因此,数据的加载时间开始时间为r9一次,仅使用str rx,[r9, #hwa_ext_reset-start_of_data]。这是 u-boot 使用的策略,您甚至可以重新定位数据部分(从iram移动到SDRAM等)。但是,它会消耗额外的寄存器。

答案 1 :(得分:1)

如果裸机系统上的.text部分是可写的,最简单的方法是将变量移动到.text部分。然后,您可以使用LDR / STR / ADR直接使用PC相对寻址访问数据:

   .section .text @HWA_SWI_HND_CODE, "xw"
   .code 32

hwa_ext_reset_hnd:
   .word 0x00000000

   .global hwa_reset_cb_attach
hwa_reset_cb_attach:
   str r0, hwa_ext_reset_hnd
   bx lr

请注意,hwa_ext_reset_hnd不仅必须在同一部分中定义,还需要在同一个程序集文件中定义,以便汇编程序可以计算出PC的相对偏移量。

如果您的文本部分不可写,那么您仍然可以使用PC相对寻址来完成这些事情:

hwa_reset_cb_attach:
    ldr r1, _offset_hwa_ext_reset_hnd
_base_hwa_ext_reset_hnd:
    str r0, [pc, r1]
    bx lr

_offset_hwa_ext_reset_hnd:
    .word hwa_ext_reset_hnd - (_base_hwa_ext_reset_hnd + 8)