Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a non-relocatable symbol

How can I create a non-relocatable symbol with recent (with PIC enabled) gcc? I basically want to have the following C program printing NULL:

#include <stdio.h>

extern int mem_;

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

What I tried is a small assembler file:

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

but this creates a relocatable symbol, which at runtime does not have the value 0.

Background: I am trying to get an old program running, which uses this trick to directly access (allocated) memory from Fortran as an array. Since the program has ≫10⁵ LOC, it would be not feasable to rewrite everything.

[edit] The GNU assembler manual documents an "absolute section" as

absolute section: Address 0 of this section is always "relocated" to runtime address 0. This is useful if you want to refer to an address that ld must not change when relocating. In this sense we speak of absolute addresses being "unrelocatable": they do not change during relocation.

This is probably what I would need here (right?), but I couldn't find a way enable this section. The .struct directive is documented to switch to the "absolute section"; however the following assembler does not work either:

    .globl  mem_
    .struct 0
mem_:   

The symbol appears in this case as *ABS* with 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_
[...]

but it is still relocated.

like image 956
olebole Avatar asked Oct 10 '17 08:10

olebole


1 Answers

You can put your symbol in a section "fixedloc" and specify the address at link time:

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

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

And compile/link it with

gcc -O2 mem.c -o mem -Wl,--section-start=fixedloc=0x1230000

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

Note that it will not work with location 0 on recent linux kernels if /proc/sys/vm/mmap_min_addr is not set to 0 (default is 65536) and even then, the dynamic linker chokes on it. But other addresses work flawlessly.

like image 150
Ctx Avatar answered Sep 19 '22 10:09

Ctx