How to place a variable at a given absolute address in memory (with GCC)

后端 未结 5 1798
野的像风
野的像风 2020-11-29 08:28

The RealView ARM C Compiler supports placing a variable at a given memory address using the variable attribute at(address):

int var __attribute_         


        
5条回答
  •  囚心锁ツ
    2020-11-29 09:02

    Minimal runnable linker script example

    The technique was mentioned at: https://stackoverflow.com/a/4081574/895245 but now I will now provide a concrete example.

    main.c

    #include 
    
    int myvar __attribute__((section(".mySection"))) = 0x9ABCDEF0;
    
    int main(void) {
        printf("adr %p\n", (void*)&myvar);
        printf("val 0x%x\n", myvar);
        myvar = 0;
        printf("val 0x%x\n", myvar);
        return 0;
    }
    

    link.ld

    SECTIONS
    {
      .mySegment 0x12345678 : {KEEP(*(.mySection))}
    }
    

    GitHub upstream.

    Compile and run:

    gcc -fno-pie -no-pie -o main.out -std=c99 -Wall -Wextra -pedantic link.ld main.c
    ./main.out
    

    Output:

    adr 0x12345678
    val 0x9abcdef0
    val 0x0
    

    So we see that it was put at the desired address.

    I cannot find where this is documented in the GCC manual, but the following syntax:

    gcc link.ld main.c
    

    seems to append the given linker script to the default one that would be used.

    -fno-pie -no-pie is required, because the Ubuntu toolchain is now configured to generate PIE executables by default, which leads the Linux kernel to place the executable on a different address every time, which messes with our experiment. See also: What is the -fPIE option for position-independent executables in gcc and ld?

    TODO: compilation produces a warning:

    /usr/bin/x86_64-linux-gnu-ld: warning: link.ld contains output sections; did you forget -T?
    

    Am I doing something wrong? How to get rid of it? See also: How to remove warning: link.res contains output sections; did you forget -T?

    Tested on Ubuntu 18.10, GCC 8.2.0.

提交回复
热议问题