Question

I am currently experimenting with GNU LD linker scripts.

I want to have multiple .text.* sections in the compiled & linked Linux x64 ELF binary. I compiled my sample code into an .o object file via

gcc -ffunction-sections -fdata-sections -c sample.c

and now every function is placed into a separate .text. section in the object file:

<...>
8 .text.main    0000003b  0000000000000000  0000000000000000  00000098  2**0
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
9 .text.printString 0000001f  0000000000000000  0000000000000000  000000d3  2**0
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
10 .text.addPrintNumbers 00000032  0000000000000000  0000000000000000  000000f2  2**0
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
11 .text.getAnotherNumber 0000000b  0000000000000000  0000000000000000  00000124  2**0
              CONTENTS, ALLOC, LOAD, READONLY, CODE
<...>

Linking this with LD and a custom script, leads to all code being merged into one monolithic .text section in the ELF binary. I tried two variants for .text.* merging:

<...>
.text           :
{
  KEEP (*(.text .text.*))
  KEEP (*(.text.unlikely .text.*_unlikely .text.unlikely.*))
  KEEP (*(.text.exit .text.exit.*))
  KEEP (*(.text.startup .text.startup.*))
  KEEP (*(.text.hot .text.hot.*))
  KEEP (*(.stub .gnu.linkonce.t.*))
  /* .gnu.warning sections are handled specially by elf32.em.  */
  KEEP (*(.gnu.warning))
}
<...>

(I know this KEEP arguments is only for the LD garbage collector to keep this section in code, not to place it into a separate section.

When I tried this experimental construct:

<...>
.text.addPrintNumbers :
{
  KEEP(*(.text.addPrintNumbers))
}
.text.printString :
{
  KEEP(*(.text.printString))
}
.text           :
{
  KEEP (*(.text .text.*))
  KEEP (*(.text.unlikely .text.*_unlikely .text.unlikely.*))
  KEEP (*(.text.exit .text.exit.*))
  KEEP (*(.text.startup .text.startup.*))
  KEEP (*(.text.hot .text.hot.*))
  KEEP (*(.stub .gnu.linkonce.t.*))
  /* .gnu.warning sections are handled specially by elf32.em.  */
  KEEP (*(.gnu.warning))
}
<...>

I had some partial success (objdump -x ./sample | less):

 <...>
 11 .text.addPrintNumbers 00000032  0000000000400400  0000000000400400  00000400  2**0
              CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text.printString 0000001f  0000000000400432  0000000000400432  00000432  2**0
              CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         00000112  0000000000400460  0000000000400460  00000460  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
 <...>

And the two manual linked sections where placed in the ELF binary and were still executable.

Is it possible to have all .text.* sections in the compiled and linked binary automatically, without a manual edited LD script. I am looking for a flag which does automatically, what I managed with the manually edited LD script.

Was it helpful?

Solution

About avoiding a custom linker script, I don't think it is possible. If you want to fiddle with sections you need a linker script.

In my machine, the command ld --verbose outputs:

  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  }

If you want to change that, you must change the script. There is no workaround!

OTHER TIPS

Try to turn optimization on. Somehow turning optimization on, e.g. -O2 flag, instructs the compiler and the linker not to merge .text.* sections

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top