This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

armcc 5.06u6: --multifile and the elimination of unused variables

Hello,

I have successfully used armcc 5.06u6 to compile and run a firmware for an ARM7TDMI target with 32kB flash. To save some space now I am trying to use the --multifile option. This actually saves some additional space, which is nice, but I have made the observation that some unused data structures (from common files shared by various projects), and code referenced from these data structures, seem to not be removed by the linker, as opposed to the normal compilation mode (without --multifile), where these unused parts are eliminated as expected. So, without manual intervention, --multifile mode, under certain conditions, appears to result in larger code size numbers. Even if an object file is completely unused by the main application, its (unused) variable definitions may be included into the resulting executable.

I have reduced my program to a minimal example that demonstrates the behaviour: https://github.com/knieriem/armcc_5_06_u6_multifile_var_elim

The program sizes displayed are ...

... with --multifile:

compiling --multifile main.c partly_used.c unused.c unused2.c unused3.c unused4.c
linking Build/linker_test_multifile.axf
Program Size: Code=248 RO-data=2024 RW-data=3656 ZI-data=0
--

... without --multifile:


linking Build/linker_test_normal.axf
Program Size: Code=160 RO-data=20 RW-data=8 ZI-data=0
--

Since without the --multifile option, the elimination of unused parts works reliably, I would assume that this is also the case in --multifile mode. What might cause this different behaviour? Am I missing another command line option? Or is one of the compiler resp. linker options I used in the Makefile preventing armcc from eliminating the unused parts?

  • Hi Michael,

    What you are seeing is correct behavior, even if not initially obvious.

    Multifile compilation will compile all input files together, meaning in general all will go to one ELF section, allowing optimization between them (for example, a single pointer to data). At compile time, it is not known what is used and unused (unless linker feedback is used), and so by default all code is linked into one section. Then at link time, the linker is no longer able to remove that unused code, as it is in the same section as some used code (see below output of fromelf -z)

    ** Section #1 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 60 bytes (alignment 4)
        Address: 0x00000000
    
        $a
        .text
        fn_used
            0x00000000:    e3a0002a    *...    MOV      r0,#0x2a
            0x00000004:    e12fff1e    ../.    BX       lr
        main
            0x00000008:    e59f001c    ....    LDR      r0,[pc,#28] ; [0x2c] = 0
            0x0000000c:    e59f101c    ....    LDR      r1,[pc,#28] ; [0x30] = 0
            0x00000010:    e5810000    ....    STR      r0,[r1,#0]
            0x00000014:    e3a0002a    *...    MOV      r0,#0x2a
            0x00000018:    e12fff1e    ../.    BX       lr
        fn_unused5
            0x0000001c:    e59f0010    ....    LDR      r0,[pc,#16] ; [0x34] = 0x4
            0x00000020:    e12fff1e    ../.    BX       lr
        fn_unused
            0x00000024:    e59f000c    ....    LDR      r0,[pc,#12] ; [0x38] = 0x404
            0x00000028:    e12fff1e    ../.    BX       lr
        $d
            0x0000002c:    00000000    ....    DCD    0
            0x00000030:    00000000    ....    DCD    0
            0x00000034:    00000004    ....    DCD    4
            0x00000038:    00000404    ....    DCD    1028

    When you apply linker feedback, those unused functions can now be moved to their own sections, and hence now be removed:

    ** Section #1 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 8 bytes (alignment 4)
        Address: 0x00000000
    
        $a
        .text
        fn_used
            0x00000000:    e3a0002a    *...    MOV      r0,#0x2a
            0x00000004:    e12fff1e    ../.    BX       lr
    
    ** Section #2 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 28 bytes (alignment 4)
        Address: 0x00000000
    
        $a
        .text
        main
            0x00000000:    e59f000c    ....    LDR      r0,[pc,#12] ; [0x14] = 0
            0x00000004:    e59f100c    ....    LDR      r1,[pc,#12] ; [0x18] = 0
            0x00000008:    e5810000    ....    STR      r0,[r1,#0]
            0x0000000c:    e3a0002a    *...    MOV      r0,#0x2a
            0x00000010:    e12fff1e    ../.    BX       lr
        $d
            0x00000014:    00000000    ....    DCD    0
            0x00000018:    00000000    ....    DCD    0
    
    ** Section #15 '.rel.text' (SHT_REL)
        Size   : 16 bytes (alignment 4)
        Symbol table #14 '.symtab'
        2 relocations applied to section #2 '.text'
    
    
    ** Section #3 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 12 bytes (alignment 4)
        Address: 0x00000000
    
        $a
        .text
        fn_unused5
            0x00000000:    e59f0000    ....    LDR      r0,[pc,#0] ; [0x8] = 0x4
            0x00000004:    e12fff1e    ../.    BX       lr
        $d
            0x00000008:    00000004    ....    DCD    4
    
    ** Section #16 '.rel.text' (SHT_REL)
        Size   : 8 bytes (alignment 4)
        Symbol table #14 '.symtab'
        1 relocations applied to section #3 '.text'
    
    
    ** Section #4 '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
        Size   : 12 bytes (alignment 4)
        Address: 0x00000000
    
        $a
        .text
        fn_unused
            0x00000000:    e59f0000    ....    LDR      r0,[pc,#0] ; [0x8] = 0x404
            0x00000004:    e12fff1e    ../.    BX       lr
        $d
            0x00000008:    00000404    ....    DCD    1028

    For this reason we recommend use of multifile compilation with care, as it can lead to exactly the situation you report here.

    Hope this explains what is happening.

    Ronan