开发者

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

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

int var __attribute__((at(0x40001000)));
var = 4;   // changes the memory located at 0x40001000

Does GCC 开发者_C百科have a similar variable attribute?


I don't know, but you can easily create a workaround like this:

int *var = (int*)0x40001000;
*var = 4;

It's not exactly the same thing, but in most situations a perfect substitute. It will work with any compiler, not just GCC.

If you use GCC, I assume you also use GNU ld (although it is not a certainty, of course) and ld has support for placing variables wherever you want them.

I imagine letting the linker do that job is pretty common.

Inspired by answer by @rib, I'll add that if the absolute address is for some control register, I'd add volatile to the pointer definition. If it is just RAM, it doesn't matter.


You could use the section attributes and an ld linker script to define the desired address for that section. This is probably messier than your alternatives, but it is an option.


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 <stdio.h>

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.


You answered your question, In your link above it states:

With the GNU GCC Compiler you may use only pointer definitions to access absolute memory locations. For example:

#define IOPIN0         (*((volatile unsigned long *) 0xE0028000))
IOPIN0 = 0x4;

Btw http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Variable-Attributes.html#Variable%20Attributes


Here is one solution that actually reserves space at a fixed address in memory without having to edit the linker file:

    extern const uint8_t dev_serial[12];
    asm(".equ dev_serial, 0x1FFFF7E8");
/* or    asm("dev_serial = 0x1FFFF7E8"); */
    ...
        
    for (i = 0 ; i < sizeof(dev_serial); i++)
        printf((char *)"%02x ", dev_serial[i]);


In GCC you can place variable into specific section:

__attribute__((section (".foo"))) static uint8_t * _rxBuffer;

or

static uint8_t * _rxBuffer __attribute__((section (".foo")));

and then specify address of the section in GNU Linker Memory Settings:

.foo=0x800000 


I had a similar issue. I wanted to allocate a variable in my defined section at a special offset. In the same time I wanted the code to be portable (no explicit memory address in my C code). So I defined the RAM section in the linker script, and defined an array with the same length of my section (.noinit section is 0x0F length).

uint8_t no_init_sec[0x0f] __attribute__ ((section (".noinit")));

This array maps all locations of this section. This solution is not suitable when the section is large as the unused locations in the allocated array will be a wasted space in the data memory.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜