You copied the Doc URL to your clipboard.

Arm Compiler Migration and Compatibility Guide : Compiling with -mexecute-only generates an empty .text section

Compiling with -mexecute-only generates an empty .text section

A change between Arm® Compiler 6.8 and Arm Compiler 6.9 means that compiling with -mexecute-only always generates an empty .text section that is read-only. That is, a section that does not have the SHF_ARM_PURECODE attribute.

The linker normally removes the empty .text section during unused section elimination. However, the unused section elimination does not occur when:

  • The image has no entry point.
  • You specify one of the following linker options:
    • --no_remove.
    • --keep (<object-file-name>(.text)).

If you use a scatter file to merge execute-only (XO) and read-only (RO) sections into a single executable region, then the XO sections lose the XO attribute and become RO.

When compiling with -fno-function-sections, all functions are placed in the .text section with the SHF_ARM_PURECODE attribute. As a result, there are two sections with the name .text, one with and one without the SHF_ARM_PURECODE attribute. You cannot select between the two .text sections by name. Therefore, you must use attributes as the selectors in the scatter file to differentiate between XO and RO sections.

Examples

The following example shows how Arm Compiler 6 handles .text sections:

  1. Create the file example.c containing:

    void foo() {}
    
    int main() {
      foo();
    }
  2. Compile the program and examine the object file with fromelf.

    armclang --target=arm-arm-none-eabi -mcpu=Cortex-M3 -mexecute-only -c -o example.o example.c
    fromelf example.o

    The output shows that Section #2 is the empty RO .text section:

    ...
    ** Section #1 '.strtab' (SHT_STRTAB)
        Size   : 148 bytes
    
    
    ** Section #2 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 0 bytes (alignment 4)
        Address: 0x00000000
    
    
    ** Section #3 '.text.foo' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ARM_PURECODE]
        Size   : 2 bytes (alignment 4)
        Address: 0x00000000
    
    
    ** Section #4 '.ARM.exidx.text.foo' (SHT_ARM_EXIDX) [SHF_ALLOC + SHF_LINK_ORDER]
        Size   : 8 bytes (alignment 4)
        Address: 0x00000000
        Link to section #3 '.text.foo'
    
    
    ** Section #5 '.rel.ARM.exidx.text.foo' (SHT_REL)
        Size   : 8 bytes (alignment 4)
        Symbol table #13 '.symtab'
        1 relocations applied to section #4 '.ARM.exidx.text.foo'
    
    
    ** Section #6 '.text.main' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ARM_PURECODE]
        Size   : 10 bytes (alignment 4)
        Address: 0x00000000
    ...
  3. Create the file example.scat containing:

    LR_XO 0x10000
    {
      ER_MAIN_FOO 0x10000
      {
         example.o(.text*)
      }
    }
    
    LR_2 0x20000
    {
      ER_REST 0x20000
      {
         *(+RO, +ZI)
      }
      ARM_LIB_STACKHEAP 0x80000 EMPTY -0x1000 {}
    }
  4. Create an image file with armlink and examine the image file with fromelf:

    armlink --scatter example.scat -o example_scat.axf example.o
    fromelf example_scat.axf

    The output shows that Section #1 has the SHF_ARM_PURECODE attribute:

    ...
    ** Section #1 'ER_MAIN_FOO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ARM_PURECODE]
        Size   : 16 bytes (alignment 4)
        Address: 0x00010000
    
    
    ** Section #2 'ER_REST' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 604 bytes (alignment 4)
        Address: 0x00020000
    ...
  5. Repeat the link again with the linker option --no_remove and examine the image file with fromelf.

    armlink --scatter example.scat --no_remove -o example_scat.axf example.o
    fromelf example_scat.axf

    The output shows that Section #1 does not have the SHF_ARM_PURECODE attribute:

    ...
    ** Section #1 'ER_MAIN_FOO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 16 bytes (alignment 4)
        Address: 0x00010000
    
    
    ** Section #2 'ER_REST' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 604 bytes (alignment 4)
        Address: 0x00020000
    ...

    The empty RO .text section is no longer removed and is placed in the same execution region as .text.main and .text.foo. Therefore, these sections become read-only.

    The same result is obtained when linking with --keep example.o(.text) or if there is no main or no entry point.

  6. To ensure that the sections remain as execute-only, either:

    • Change the scatter file to use the XO attribute selector as follows:

      LR_XO 0x10000
      {
        ER_MAIN_FOO 0x10000
        {
           example.o(+XO)
        }
      }
      
      LR_2 0x20000
      {
        ER_REST 0x20000
        {
           *(+RO, +ZI)
        }
        ARM_LIB_STACKHEAP 0x80000 EMPTY -0x1000 {}
      }
    • Explicitly place sections in their execution regions. However, compiling with -fno-function sections generates two .text sections with different attributes:

      armclang --target=arm-arm-none-eabi -mcpu=Cortex-M3 -mexecute-only -fno-function-sections -c -o example.o example.c
      fromelf example.o
      ...
      ** Section #1 '.strtab' (SHT_STRTAB)
          Size   : 107 bytes
      
      
      ** Section #2 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
          Size   : 0 bytes (alignment 4)
          Address: 0x00000000
      
      
      ** Section #3 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ARM_PURECODE]
          Size   : 14 bytes (alignment 4)
          Address: 0x00000000
      ...

      In this case, differentiating the sections by name only is not possible. If unused section elimination does not remove the empty .text sections, the attribute selectors are required to place the sections in different output sections.

Was this page helpful? Yes No