Defining Variables at Absolute Addresses with gcc

Many compilers offer a way to allocate a variable at an absolute address. For example for the Freescale S08 compiler, I can place my variable at a given address:

unsigned char buf[128]@0x2000;

This is very useful (and needed) e.g. if the hardware (like USB) needs a buffer at given address. The advantage of the above (non-ANSI and thus not portable) syntax is that I can define a variable at an absolute address, without the need to allocate it in the linker.

I wanted to do something similar with gcc for Kinetis/ARM, and searched many forums on the internet. Obviously, I’m not alone with this question. The solution I have found comes close to what I use e.g. for the S08 compiler.

How can I place a variable say at address 0x2000’0000 with gcc for ARM/Kinetis?

The idea I use here is to put the variable with a special section name, and then place it in the linker file at an absolute address.

💡 I have not found a way to place a variable at an absolute address *without* to modify the linker file? Post a comment if you know a better solution!


Gcc uses the __attribute__ keyword as a way to ‘mark’ variables with special attributes. It allows me put my variable into a special section, which I name here ‘.myBufSection’:

unsigned char __attribute__((section (".myBufSection"))) buf[128];

Another useful thing is: I can specify the alignment of that variable with an __attribute__ too:

unsigned char __attribute__((section (".myBufSection"))) buf[128] __attribute__ ((aligned (512)));

With this, my variable will be put into a section named ‘.myBufSection’, and it will be aligned on a 512 address boundary.

Absolute Section Placing in Linker File

The next step is to place that section at an address in the linker file. E.g. for the KL25Z of my Freedom board, I have this memory mapping in my linker file:

  m_interrupts  (rx) : ORIGIN = 0x00000000, LENGTH = 0xC0
  m_cfmprotrom  (rx) : ORIGIN = 0x00000400, LENGTH = 0x10
  m_text        (rx) : ORIGIN = 0x00000800, LENGTH = 128K - 0x800
  m_data       (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K

I could split my m_data block and create my memory block for my variable to place at 0x2000’0000. An easier way is to simply place my section from above into the SECTIONS block like this:

  /* placing my named section at given address: */
  .myBufBlock 0x20000000 :
    KEEP(*(.myBufSection)) /* keep my variable even if not referenced */
  } > m_data

  /* other placements follow here... */

With above linker statement, I define an absolute start address for all my variables in the section named .myBufSection, and place it into the m_data memory block. Additionally I need to use the KEEP keyword to tell the linker *not* to dead-strip my variable, in case I do not reference it from my code.

Checking the Allocation

After linking, now my object should be at the given address. While looking at the linker map is always a good idea, I have found another nice tool which comes with the GNU suite: nm. With nm I can examine binary files like the ELF file produced by the linker. In CodeWarrior for MCU10.3, that command line utility can be found in

<CW installation path>\Cross_Tools\arm-none-eabi-gcc-4_6_2\bin\arm-none-eabi-nm.exe

I could configure to run it as post-link step in CodeWarrior, or simply use it from the DOS command line prompt:

nm shows my variable at the absolute address

nm shows my variable at the absolute address


For gcc, placing a variable at an absolute address requires two steps: marking it with a section name in the source, and then placing it in the linker file at an absolute address.

It would be good if there would be a way to avoid the linker file change, but I have not found another or better solution.

Happy Absoluting 🙂

76 thoughts on “Defining Variables at Absolute Addresses with gcc

    • Hello Erich,
      first of all thanks for the good solution!
      I would like to ask this: if I need to create more than one variables ( I need few arrays..), have I to declare a section for each array? Or there is easier way, using code instead of adding more sections?



    • Hi Barrie,
      yes, using a casted pointer is the preferred way to access peripherals. The problem with this is that it is only accessing an object, but not defining it. In my case I want to reserve memory for it, not only accessing it. and if it is just such a pointer access, that will not work.


  1. Is there any way of doing this while allowing Processor Expert to generate the linker file itself? I’ve had to disable “Generate Linker File” in order to maintain the modification to the linker file. Not a big deal, just curious if it’s possible. I didn’t see anything while looking through PE.


  2. Pingback: GNU Linker, can you NOT Initialize my Variable? | MCU on Eclipse

  3. Hi Erich, I’m looking for a DoOnStack equivalent for Kinetis and Google redirects here. Do you know if a DoOnStack equivalent routine exist? Thank you


  4. Eric,

    i am using your post for embedding a version inside the output file.
    i did as you have described:
    in the linker script:
    .myBufBlock 0x00000000 : {

    in the code:
    int __attribute__((section (“.myBufSection”))) SWVersionInFile = 0x0306060A; //

    the problem that in the output file itself, the data is placed as ASCII and not as its value.
    meaning that the values looks like that:
    30 33 30 36 30 36 30 41
    instead of::
    03 06 06 0A

    Where is the problem?


    • Hi shurik,
      hmm, that’s really strange. I tried to replicate this, and added this to my .text section:
      .text :
      . = ALIGN(4);
      *(.text) /* .text sections (code) */
      *(.text*) /* .text* sections (code) */
      *(.rodata) /* .rodata sections (constants, strings, etc.) */
      *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
      *(.glue_7) /* glue arm to thumb code */
      *(.glue_7t) /* glue thumb to arm code */
      KEEP (*(.init))
      KEEP (*(.fini))
      . = ALIGN(4);
      } > m_text
      but for me the result was as expected (0x306060a). Could it be that you look at the wrong variable? Can you verifiy in the linker map file that your variable has indeed be linked (and not be removed by the linker as not used?).


  5. Hello Erich,
    first of all thanks for the good solution!
    I would like to ask this: if I need to create more than one variables ( I need few arrays..), have I to declare a section for each array? Or there is easier way, using code instead of adding more sections?



    • Found it 🙂
      u simple declare the second array just after the first one, with the same __attribute__((section (“.myBufSection”))).
      The linker will put the second array in the location just after the first one.


      • I do not believe that there’s any guarantee that they will end up in memory in source-order. See however my (simpler) alternative method in the comments above; you can just do
        buf = 0x20000000;
        buf2 = buf + 0x1000;
        or whatever. BTW, I put them in a SECTIONS { } block above, but that actually turns out to be optional. You can just put assignments like those in a text file named “whatever.ld” and provide it to ld or even to gcc as a source file (or rather, it is treated as an object file of a slightly strange sort).


        • For having the variables in the same source order you can use a structure. And if you want them on the same order and without wasted space because of padding then you can use a PACKED structure. That way you guarantee the order along with the position in memory.


  6. I wonder if I can use this technique so I can make use of the 832-byte memory area in the KL05 that occupies the space between the end of the m_interrupt area at address 0xc0 and the 16-byte “Flash Configuration Field” – fixed at address 0x400. This appears to be wasted. Can I set m_text start address to 0xc0 simply tell the linker to place the Flash Configuration Field (defined as _cfm[] in Cpu.c) at 0x400?

    I tried to copy your example and ended up with _cfm correctly at 0x400, but none of the space between 0xc0 and 0x400 was used.


  7. An example for ARM:

    asm (“.set mivar, 0x1234”);
    extern int mivar;

    main(int argc, char **argv)

    This is the code generated:

    00008018 :
    8018: e59f2008 ldr r2, [pc, #8] ; 8028
    801c: e59f3008 ldr r3, [pc, #8] ; 802c
    8020: e5832000 str r2, [r3]
    8024: e12fff1e bx lr
    8028: 00004567 .word 0x00004567
    802c: 00001234 .word 0x00001234


      • You’re welcome.
        BTW, you may also consider to include the following asm line if you’re going to reference the absolute variable from a different source file:

        asm (“.global mivar”);

        The main problem I’m seeing with this solution is the lack of portability due to the different assembler directives for other architectures.


    • What an ugly hack, but so easily solves all problems of making constant values computed using a C++ `constexpr` usable in ASM code by passing them though the linker. Thanks!

      For others in the future, some versions of gcc also provide `#pragma LOCATION(address)` and/or `__attribute__((location(address)))` to specify the address to put a variable, which is slightly cleaner if available….


        • Correct, I have not seen it anywhere else besides the TI compiler and even there it is proving to be quite flakey. Sometimes code will compile and link with no errors or warnings, but the variable will inexplicably end up at address `0x0001`. :/

          Sadly in my case I think I am going to have to resort to code-that-writes-code; write a C++ program that emits ASM source with hard coded address constants which is then assembled into an OBJ that is linked back into the final program. Not happy about it though.


        • Using the __attribute__((section (“.mysectionName”))) worked very well for me. So far I have just tweaked the linker file for it, and that was not hard. I was considering writing a small script to make a linker script file I could include into the linker script, but so far it was easier to do it by hand.


  8. Thanks for the information. I tried both methods above and my variable is indeed at the location I want, however the linker also put another variable at the same location. This is verified by seeing the other variables address in both the map file as well as in the watch window. Any suggestions?


  9. Hey Erich
    Awesome Solution. Now We know how to place a variable in a specific location. But If I want to place a piece of code in a specific memory address. What should I do ?

    unsigned int i;
    Bit1_ClrVal(); // passing ‘0’ to CR1 LED port

    for(i=0;i<=1000000;i++); //software delay

    Bit1_SetVal(); // passing '1' to CR1 LED port

    for(i=0;i<=1000000;i++); //software delay

    I want to put this code into the flash memory area of my KINETIS E series controller (MKE02Z64VLD2). Flash region is 0X0000_0000 to 0X07FF_FFFF. Can u say how it is done ?
    Ganesh R


  10. Thanks a ton for this post! I need to be able to reprogram data in non-volatile memory, and my chip can only do that 4kB at a time. I can’t mess with the execution instructions that the data used to be mixed in with, so I can’t just use an absolute pointer as others suggested. I need a section of ROM that I know I can mess with without interrupting operation of the device.


  11. Erich, is there a way to get the base address for a section that is defined in the linker script (like the .myBufSection you created in your example above), if for example, you wanted to read a few bytes starting from the beginning of this section ?


  12. Pingback: Accessing GNU Linker Script Symbols from C/C++ | MCU on Eclipse

  13. Pingback: Flash-based Configuration Data Using The ld Linker – vilimblog

  14. I have two comments to add:

    1. Given this code:

    unsigned char __attribute__((section (“.myBufSection”))) buf[128] __attribute__ ((aligned (512)));

    I think it can be written in a shorter manner by separating the attributes with a comma:

    unsigned char __attribute__((section (“.myBufSection”), aligned (512))) buf[128];

    2. By using the “used” attribute, GCC is explicitly told not to dead-strip the variable when not referenced. I think it’s similar to the KEEP() directive of link scripts:

    void __attribute__ ((used, section (“.init3”), naked)) move_sp(void) {…}


    • Yes, __attribute__ settings can be combined, but sometimes they have be before or after a declaration. I have not checked in that particular case if both can be before the declaration.
      The used attribute is something too, but to my knowledge it is working for functions only, but not for variables. That way the KEEP inside the linker script is very useful.


  15. Thank you very much Erich! This is a great thing and helps a lot! I’ve tested it with success in debug mode. If I switch to Release it doesn’t work any more. I found out the reason: Debug Setting -> Optimization Level: None, Release Setting -> Optimization Level: Optimize for size. If I change this in Release mode it works well again. But I have bigger code-size. I thought the KEEP instruction in the linker script would prevent this? Or am I doing something wrong?
    Regards, Dirk


  16. Pingback: Getting Started: ROM Bootloader on the NXP FRDM-KL03Z Board | MCU on Eclipse

  17. Pingback: Using Multiple Memory Regions with the FreeRTOS Heap | MCU on Eclipse

  18. A really nice explanation about this topic, I don’t like the method but guess there is not other way to do it. Thanks


      • I have also used the flag -fdata-sections and while it still requires linker magic, it avoids the need for the attributes in the source code. It also will allow you to order specific declarations in a section if needed.


        • The -fdata-sections flag basically means that the linker creates a section name for each variable. That way the name of that section or variable can be used in the linker file. That’s indeed another good approach.


  19. Why can’t be simply done like this:
    DIM var AS [XRAM/SRAM/ERAM]type [AT location/variable] [OVERLAY]
    I think, Bascom solution is the best and most elegant. Does exist something like this for C – ARM? Is C stupid or me? How to improve C? How to translate such code to C? I start learn C and would really like to hear opinions.


    • That example is with BASIC, and the concepts are really different to the C language. C has a long heritage plus must conform to standards which might be counter intutitive. On the plus side: C (and C++) are close to the hardware so you can know what happens for every line of your program. And you get C for virtually any architecture/CPU/microcontroller where Bascom is more of a nice solution to me? I think you have to go through that learning experience, I’m affraid.


  20. Pingback: Stack Canaries with GCC: Checking for Stack Overflow at Runtime | MCU on Eclipse

  21. If I create a section at the end of .text, this is, if .text is declared having a size of 0x8000 and I “resize” .text to 0x7FC00 (assuming a flash sector of 1K), and create my section starting on 0x7FC00 with a size of 0x400 (1k), is the flashing tool not going to touch this section?

    I ask because I want to use this portion of memory at the end of .text to store non-volatile data and it is not desirable at all that the flashing tool would wipe it out, but I’m not sure if I have to do any additional steps or add additional declarations to the linker file or the project to keep the flashing tool from touching this area.


    • If an area is erased or not depends on multiple factors:
      – debug probe: some debug probe will erase the whole device (all sectors), some only the sectors which are part to the binary. Some have a setting to configure this
      – on chip/bootloader: usually you can define which sectors are erased (or protected)
      The linker itself does not control this: all what it does is to build the binary


  22. That would be flash tool dependant. Some erase the entire chip and some you can specify what range to erase. Even in that case some will erase the chip and then restore the preserved areas back. A linker script change will not necessarily help you here.


  23. Hi,

    How do I write the same thing as this:

    #pragma location = “OPTBYTE”
    __root const char opbyte0 = 0xFF;
    #pragma location = “OPTBYTE”
    __root const char opbyte1 = 0xF3;

    but with gcc?

    Im trying to build this code in e2 studio but i keep getting a lot of erros
    thank you


  24. To access a struct at some fixed address, just use a pointer whose value is the address:

    struct type_t *varp = (type_t *)0x200000;

    I suppose this might not work in some environments but it’s what I do when I need.


    • Hi Joe,
      yes, that’s the normal way for accessing hardware/etc which are already at a fixed address, or if an object has an address. The bigger problem is how to place an arbitrary object at a specific address (not necessarily accessing it).


  25. Hi,
    If the problem is the selection of a RAM region to store a heap (FreeRTOS heap for example), there is a simpler mean with mcuxpresso IDE to do the stuff without writing custom linker script (or changing the generated one).
    If for example I have:
    uint8_t __attribute__((section (“.mySection”))) ucHeap[ configTOTAL_HEAP_SIZE ];
    Then in Project/properties/C/C++ Buid/Settings/MCU Linker/Managed Linker Script, there is “Extra linker script input sections” where in the
    “Input section description” field I can put *(.mySection)
    “Region” I can select one of my uC region listed
    “Section Type” select .bss


    • Hi Oliver,
      thanks! I’m using the same approach for my FreeRTOS heap allocation where I use an already existing section name by default.
      Good hint about the ability to add your own section that way, I like that!

      Liked by 1 person

What do you think?

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.