15

I've just started learning some ARM programming and I've got stuck in a slightly annoying problem. The toolchain I'm using to compile my sources is Sourcery CodeBench Lite 2013.05-23 (can be found here: https://sourcery.mentor.com/GNUToolchain/release2449)

What I would need is to tell GCC or LD or OBJCOPY to put the compiled bytecode of the 'main' function at the beginning of the .text section.

Is there any way to achieve this? (maybe through a linker script?)

Thank you

Zuzu Corneliu
  • 1,594
  • 2
  • 15
  • 27

3 Answers3

19

Solved the problem. For whoever faces it:

  • When compiling with GCC, add the -ffunction-sections option in the command-line. This will tell GCC to put each function in a separate section. The format of the section name will be .text.#function name#, without the # (that is, if the function belongs to the .text section [ which by default is true ]).
  • Secondly, use a linker script to order these "function-sections" into the final big .text section. As an example, putting the main function at the beginning of the .text section would result in an LD script that looks approximately like this:

    ENTRY(main)
    SECTIONS
    {
        .text :
        {
            *(.text.main);
            *(.text*);
        }
    }
    
Zuzu Corneliu
  • 1,594
  • 2
  • 15
  • 27
  • 7
    You can also use: 'int main(int argc, char **argv) __attribute__((section(".text.main")));' and keep the rest in the default section. – Goswin von Brederlow Feb 28 '15 at 09:38
  • How does one pass a linker script to GCC? Or is it done in 2 steps? Any example would help. – Brandon Ros Jul 29 '21 at 05:00
  • I think, in linker script, using `*(.text*.main);` instead of `*(.text.main);` is better and more generalized way, because there can be other phrases between `.text` and `.main`, like in my case, `main` tag was `.text.startup.main` and it wasn't working, then I fixed by adding wildcard into the middle. – Celuk Feb 15 '23 at 23:20
5

First, see how is the .text section defined in your gcc's default linker script (so you don't have to make your own), by calling it as:

gcc -Wl,-verbose

that will print out the default linker script. Mine shows this for the .text section:

/* text: Program code section */
  .text : 
  {
    *(.text)
    *(.text.*)
    *(.gnu.linkonce.t.*)
  }

So in order to have the "main" function be the first in the .text section (and the rest be contiguous), you have to set the "section" attribute for all other functions. For example:

void main(void);
void funct1(....) __attribute__ ((section (".text.A")));
void funct2(....) __attribute__ ((section (".text.A")));
void funct3(....) __attribute__ ((section (".text.A")));

It's enough with "attributing" the function prototypes. That way, when you compile now, the "main" function will be the first one in the ".text" section and all others will follow on the immediately consecutive addresses.

If you want to place the ".text" section (i.e. "main" function) at a specific address (for example 0x1000), remember to link with:

gcc .... -Wl,-Ttext=0x1000
Galland
  • 106
  • 1
  • 2
  • 1
    While this will work, adding a section to all other functions is far from the simplest way - please see the accepted answer for a simpler solution. – mdma Feb 11 '15 at 18:08
2

You can also just put 'main' in its own section using an __attribute__:

int main (void) __attribute__ ((section ("entry")));

and then in the ld file:

ENTRY(main)
SECTIONS
{
    .text :
    {
        *(main)
        *(.text)
    }
}

There are plenty of other interesting __attributes__, read more about them here: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
ordahan
  • 187
  • 9
  • 2
    The correct return type for `main` is `int`, not `void`. (`void main(void)` might be permitted by some compilers; `int main(void)` is universal for hosted implementations.) – Keith Thompson Nov 08 '13 at 22:51
  • 3
    Was just an example on using `__attributes__` - don't know how his main looks like :) – ordahan Nov 09 '13 at 07:12
  • Then you should have picked one of the two valid signatures for `main`. clang refuses to compile `void main()`. – Peter Cordes Aug 25 '18 at 15:51
  • 2
    @PeterCordes : those aren't the only 2 valid signatures. If someone is building in a freestanding (non-Hosted) environment (which could be the case for this question - it is umclear). I would expect CLANG would allow it to compile if using `-ffreestanding` – Michael Petch Aug 25 '18 at 17:02
  • 1
    @MichaelPetch: oh good point. Yes, that is the case for gcc and clang. https://godbolt.org/z/l5JGTu. (Turns out both gcc and clang reject `void main()` now in the default hosted mode. I still think it's a good edit, although this particular question is fairly likely to be about freestanding code. – Peter Cordes Aug 25 '18 at 17:12
  • @PeterCordes : not questioning the edit at all. May as well use a signature that works in both so I support the change. I was only making an observation about valid signatures in general. – Michael Petch Aug 25 '18 at 17:17