在x86-64中,我可以使用gcc为不同的变量选择RIP相对寻址还是绝对寻址

在x86-64中,我可以使用gcc为不同的变量选择RIP相对寻址还是绝对寻址,gcc,x86-64,addressing-mode,relative-addressing,Gcc,X86 64,Addressing Mode,Relative Addressing,我编写自己的链接脚本,将不同的变量放入两个不同的数据部分(A和B) A链接到零地址; B链接到代码附近,位于高地址空间(高于4G,这在x86-64中不适用于正常的绝对寻址) A可以通过绝对寻址访问,但不能通过RIP相对寻址访问; B可以通过RIP相对寻址访问,但不是绝对寻址 我的问题是:在gcc中,有没有办法为不同的变量选择RIP相对或绝对寻址?也许使用一些注释,如#pragma?而不攻击GCC源代码,您不会让它发出32位绝对地址,但在某些情况下,GCC将使用64位绝对地址 -mcmodel=

我编写自己的链接脚本,将不同的变量放入两个不同的数据部分(A和B)

A链接到零地址; B链接到代码附近,位于高地址空间(高于4G,这在x86-64中不适用于正常的绝对寻址)

A可以通过绝对寻址访问,但不能通过RIP相对寻址访问; B可以通过RIP相对寻址访问,但不是绝对寻址


我的问题是:在gcc中,有没有办法为不同的变量选择RIP相对或绝对寻址?也许使用一些注释,如
#pragma

而不攻击GCC源代码,您不会让它发出32位绝对地址,但在某些情况下,GCC将使用64位绝对地址


-mcmodel=medium
使用64位绝对地址将大对象放入一个单独的节中。(具有所有对象都必须同意的大小阈值,由
-mlarge data threshold=
设置)。但仍然对所有其他变量使用RIP-relative

有关不同内存型号的更多信息,请参阅x86-64 System V ABI文档。和/或用于
-mcmodel=
-mlarge data threshold=

默认值是
-mcmodel=small
:所有内容都在2GB以内,因此RIP relative可以正常工作。对于非PIE可执行文件,这是低2GiB的虚拟地址空间,因此静态地址可以是32位绝对符号或零扩展立即数,也可以是寻址模式下的disp32

int a[1000000];
int b[1];

int fa() {   return a[0];  }
int fb() {   return b[0];  }
ASM输出():

为了加载到AL/AX/EAX/RAX以外的寄存器中,GCC将使用
movabs r64、imm64
和地址,然后使用
mov reg、[reg]

您不会让gcc对A部分使用32位绝对寻址。它将始终使用64位绝对寻址,而不会
[array+rdx*4]
[abs foo]
(NASM语法)。永远不要
mov edi,msg
(imm32)将地址放入寄存器,始终
mov rdi,qword msg
(imm64)

GCC将
b
放在
.lbss
部分,将
a
放在常规
.bss
部分。大概您可以在上使用
\uuuuuuu属性((节(“名称”))

        .globl  b
        .section        .lbss,"aw"           # "aw" = allocate(?), writeable
        .align 32
        .size   b, 4000000
b:
        .zero   4000000

        .globl  a
        .bss                      # shortcut for .section
        .align 4
a:
        .zero   4

不起作用的事情:

  • \uuuuu属性(优化(“mcmodel=large”))
    基于每个函数。实际上不起作用,而且是每个函数,而不是每个变量
  • 不记录与内存模型或大小相关的任何x86或公共变量属性。唯一特定于x86的变量属性是ms vs gcc struct layout

    函数和类型有x86特定的属性,但这些属性没有帮助


可能的黑客: 将所有section-A变量放在一个比任何section-B全局/静态对象都大的大型结构中。可能会在其末尾填充一个虚拟数组以使其更大:您的链接器脚本可能会避免实际为该虚拟数组分配额外空间


然后使用该大小的
-mcmodel=medium mlarge data threshold=
进行编译。

目前我们有一些使用A节的代码,这些代码只允许绝对寻址。(代码直接从一个位置复制到一个运行时堆,并被执行)
        .globl  b
        .section        .lbss,"aw"           # "aw" = allocate(?), writeable
        .align 32
        .size   b, 4000000
b:
        .zero   4000000

        .globl  a
        .bss                      # shortcut for .section
        .align 4
a:
        .zero   4