如何创建不可重定位的符号

时间:2017-10-10 08:45:36

标签: assembly linker

如何使用最近的(启用PIC)gcc创建不可重定位的符号? 我基本上想让以下C程序打印NULL:

#include <stdio.h>

extern int mem_;

int main(void) {
  printf("%p\n", &mem_);
  return 0;
}

我尝试的是一个小的汇编程序文件:

    .data
    .globl  mem_
    .type mem_,@object
    .set mem_, 0

但是这会创建一个可重定位的符号,在运行时它没有值0。

背景:我正在尝试运行一个旧程序,它使用这个技巧直接从Fortran访问(分配)内存作为数组。由于该程序具有»10⁵LOC,因此重写所有内容是不可行的。

[edit] GNU汇编程序手册documents an "absolute section"

绝对部分:此部分的地址0始终“重定位”到运行时地址0.如果要引用重定位时ld不得更改的地址,这将非常有用。从这个意义上讲,我们所说的绝对地址是“不可重复的”:它们在重新安置期间不会改变。

这可能就是我在这里需要的(对吗?),但我找不到启用此部分的方法。 .struct指令为documented to switch to the "absolute section";但是以下汇编程序也不起作用:

    .globl  mem_
    .struct 0
mem_:   

在这种情况下,符号显示为*ABS* objdump

$ objdump -t memc

memc:     file format elf64-x86-64
[...]
0000000000000540 g     F .text  000000000000002b              _start
0000000000201030 g       .bss   0000000000000000              __bss_start
000000000000064a g     F .text  000000000000003c              main
0000000000000000 g       *ABS*  0000000000000000              mem_
[...]

但它仍在重新安置。

1 个答案:

答案 0 :(得分:4)

您可以将符号放在“fixedloc”部分中,并在链接时指定地址:

#include <stdio.h>
int mem_ __attribute__ ((section ("fixedloc")));

int main (void) {
        printf("%p\n", &mem_);
        return 0;
}

编译/链接它
gcc -O2 mem.c -o mem -Wl,--section-start=fixedloc=0x1230000

$ nm mem
...
0000000001230000 D mem
...
$ ./mem
0x1230000

请注意,如果/ proc / sys / vm / mmap_min_addr未设置为0(默认值为65536),它将无法在最近的Linux内核上使用位置0,即使这样,动态链接器也会对其进行扼流。但其他地址完美无缺。