Using C++ and GCC, can I declare an extern variable that uses a specific address in memory? Something like

int key __attribute__((__at(0x9000)));

AFAIK this specific option only works on embedded systems. If there is such an option for use on the x86 platform, how can I use it?

+1  A: 

It won't work for desktop applications (for memory mapped I/O in device drives it can make sense) because the memory is virtualized over the MMU on x86 platforms. So you will not know what physical address will be located somewhere in virtual space.

What would be the use case beside testing memory I/O or some other hack? On x86 in user space each memory cell is equivalent... To access variables use their name dlsym() is your friend under Linux, GetProcAddr() under Windows. Specifying the address yourself is not foreseen AFAIK.

Even providing a so called preferred load address for a shared lib or dll will not help, because it can be relocated to another place in case of overlap with other shared libs. The address randomization feature in modern OS'es makes it nearly unpredictable (what is the goal to avoid reproducible buffer overflow attacks)

+4  A: 

I can't find this attribute in GCC docs. It doesn't make sense for general-purpose programs because many modern systems provide address space layout randomization. The best you can ask for, I guess, is to put a variable into a specific section, as in

int init_data __attribute__ ((section ("INITDATA")));

Also, if you know [virtual] address of a variable, why not just access via pointer:

int* pkey = ( int* )0x9000;
*pkey = 0xdeadbeef;
Nikolai N Fetissov
You are forgetting that gcc is also often used for kernel programming where this would be very nice. Often important memory mapped devices are at a particular location.
Evan Teran
In the kernel this only makes sense in the bootstrap code when physical memory is being mapped into kernel virtual address space. Even then, do you really want to hardcode physical addresses into your source code (as opposed to offsets to some configurable base address)?
Nikolai N Fetissov
@Nikolai: It's still occasionally useful, e.g. for UTCBs whose virtual addresses are often fixed. And for *simple* kernels, without virtual memory or with a simple linear mapping from virtual to physical. The only advantage I can think of is that the symbols can be resolved at link time (as shown in my answer), so you don't need to recompile your object file just to change an address.
Yes, forgot about the linker option. Thanks Artelius.
Nikolai N Fetissov

No. Modern desktop operating systems use virtual memory, meaning that whatever address you have is meaningless until you give it to the OS, making a specific memory address worthless. There is no way and no advantage to this on desktop/x86.


I think that IAR's C compiler uses a non-standard extension that looks like

char foo @ 0x9000;

for this, at least for their MSP430 compiler. I never used GCC for the MSP430 much, but I think that it may have supported this as well so that it could achieve source compatibility with IAR's compiler.

If you want to do something that will work on all compilers without messing around with the linker you have to work a little harder up front.

#define CONST_ADDR_VAR( type, name, address ) type *const name##_addr =(type *)address

After calling that for each variable you want to specify you will also need to do #define var (*var_addr)

It would be nice if this could have been combined with the previous macro, but defining a macro within a macro isn't standard. I think there is a way to do it with GCC's preprocessor, though.

If you want to monkey around with your linker then you could probably find a way to tell it where these variables lived and just use them as extern in your C programs.

You could also use GCC's __attribute__((section( ... ) )) to do this, but you may end up needing a different section for each variable that you want to specify the address of. There were some other things that seemed a little confusing about this, and it would require you to tell the linker where these sections were anyway.



Since you tagged this with c++, you could easily use placement new. Which is nice and portable:

// an object type T at address 0x9000
T* t = new(reinterpret_cast<void*>(0x9000)) T;

Obviously this won't be a global since new can be used outside of a function. But you could easily have a function you call as early as possible to initialize some globals this way.

Evan Teran
+2  A: 

You could just use a macro:

#define KEY (*(int*)0x9000)

so that any writes to KEY write to that memory location, and any reads to KEY read from that memory location.

If that memory location could change outside of your control (e.g. if it represents a hardware register or some sort of memory-mapped I/O), then you should declare it volatile:

#define KEY (*(volatile int *)0x9000)

This will force the compiler to re-read the value from memory each time you read it and rewrite it back to memory every time you write it, instead of possibly caching it in a register.

Adam Rosenfield
If you don't like macros, use a const pointer as in my answer.
+5  A: 

Easy option:


int * const key = (int *)0x9000;

and refer to *key elsewhere (or use a reference).

Pointerless option:

All externs have specific addresses! These addresses may not be known until link time, but they must get resolved eventually. If you declare extern int key; then you must supply an address for the symbol key at link time. This can be done using a linker script (see Using ld) or at the linker command line, using the --defsym option.

If running gcc, you could use the -Xlinker flag to pass the option on to the linker. In your example,

gcc -o outfile -Xlinker --defsym -Xlinker key=0x9000 sourcefile.c

The following program, thus compiled, outputs 0x9000.

#include <stdio.h>
extern int key;
int main(void) {
    printf("%p\n", &key);
    return 0;

If you have a collection of variables you want to be in some region of memory, a more appropriate method might be to use output sections as suggested by Nikolai, perhaps in conjunction with a custom ld script.

Good point on the `const` pointer.
Nikolai N Fetissov
This is what I was looking for.I'm reversing a program by using DLL injection. Within my DLL code I have to access variables which belong to the target process. In order to access them WITHOUT pointers I needed some way to give an extern variable a specific address. Thanks!
Great, then if you want to change the variable addresses around for some reason you don't need to recompile your code, only relink :)