Force all data in a C file to be in .text (or other) section

12,233

Solution 1

Most compilers/linkers, if you declare a variable as static const, it will place it in the text section instead of data. Obviously, these must be preinitialized and not modified at run-time, but that's the only way it makes sense to go in flash.

Solution 2

As other commenters pointed, 'static const' items usually end up in .rodata section which is likely to be placed right next to .text in potentially read-only memory. The caveat is that it may or may not be true in your case as that is specific to particular target and may be changed by particular build process (i.e. linker options, specific section specified via __attribute__((section("name"))) in C code, linker script, binaries tweaked after build with various binutils, etc).

If you need to have precise control over in-memory layout and you know what you're doing, you can use LD script to do it. Among other things it will let you specify that .rodata from file data.o should be placed just before/after .text from all other .o files linked into the executable.

You can use arm-<your toolchain variant>-ld -verbose to dump default linker script and use it as a starting point for tweaking.

Solution 3

Somewhere in the code (.text section) put like a sample:

__attribute__((section(".text")))
const int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};

or without const if you want a variable to change:

__attribute__((section(".text")))
int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};

Then try changing it:

test[0] = 0xffffffff;

This works on my Linux 32 intel machine.

Solution 4

IIRC, code in flash is usually required to be ROPI (read only position independent). So option_array_0_0 and width_array_0_0 would need const qualifiers (read only). However:

Window window_array_0[] =
{
    {
        option_array,
        width_array,
    },
};

needs to be changed somehow (I'm assuming option_array and width_array are indeed arrays). That makes window_array_0 not position independent.

Share:
12,233
DavidG
Author by

DavidG

Updated on June 04, 2022

Comments

  • DavidG
    DavidG almost 2 years

    I am using gcc to compile some code for an ARM Cortex-M4F microcontroller. My application uses a large collection of data that I have conveniently written into a C file: large arrays of ints and floats, circular linked lists pointing to those various arrays, various structs, that sort of thing.

    When I compile this it adds up to about 500K of data, plus a few hundred K for the actual application. gcc is putting all this data conveniently into the .data section; ld then tries to build the elf putting the .data section into RAM and .text (code) section into FLASH. The mcu I am using doesn't have 500K of RAM so it cannot build the ELF, but it does have 1M of FLASH. I tried changing my linker script so that both .data and .text are put into FLASH which "worked" but there are some other bit of code that expect its data to go into RAM, so ultimately execution failed; I can't make that sweeping change.

    What I need is to tell gcc to put every single object in this C file into the .text section so it can go into FLASH with the rest of the non-mutable stuff, or at least some other section which I can then instruct my linker script what to do with so that it doesn't interfere with existing blobs that have no problem fitting in RAM. I don't know how to do that. Here is a very slimmed down example of what I have

    /* data.c */
    static char* option_array_0_0[] =
    {
        "O=0.40",
        "K=FOO",
        "JAR=JAR",
    };
    
    static int width_array_0_0[] =
    {
        0,
        1,
        1,
    };
    
    Window window_array_0[] =
    {
        {
            option_array,
            width_array,
        },
    };
    
    /* main.c */
    extern Window window_array_0[];
    int main()
    {
        /* Do stuff */
    }
    

    The stuff in data.c, window_array_0 and everything (or most everything, maybe the string arrays are going to .text?) it links to, is being put in .data which my linker script puts into RAM. I want it all in a different section which I can then put into FLASH. There are thousands of these types of arrays in there, plus hundreds of structs and dozens of other bits of information. Is this possible to change? As a test I replaced my "window_array_0" with a char[500000] of random data and that compiled without complaint so I assume it put it all into .text (as would be expected), I just don't know how to make it do so for arbitrary objects. Thanks for your help.

  • alecov
    alecov over 10 years
    Point up for citing the section attribute -- this is the correct starting point for sanely laying out image data. Another option is to remap (merge) .rodata to .text (or the equivalent in that particular architecture).
  • DavidG
    DavidG over 10 years
    Ack! "static const" was actually the magic word I was looking for. I don't know how I missed that. I can work with this now. Thanks a lot!
  • BullyWiiPlaza
    BullyWiiPlaza over 6 years
    Can you please elaborate on how to accomplish forcing all data (or most) into the .text section with a linker script?
  • Harry
    Harry about 4 years
    It doesn't work. It says "cannot rename a section to another standard section"
  • isoux
    isoux about 4 years
    It is work for me with clang compiler. In fact, the code with this example is only compiled into clang, not commonly linked to the elf executable ...
  • TekuConcept
    TekuConcept almost 4 years
    Works with ARM GCC cross-compiler! My c-flags -nostartfiles -marm -ffreestanding -fomit-frame-pointer. My ld-flags -Xlinker -T format.ld where format.ld is my linker script ENTRY(main) SECTIONS { . = 0x100; .text: { *(.text.entry) *(.text) }}