Search code examples
clinkerarmembeddedlinker-scripts

Linker remove unused execution paths when linking with archive file


I have an embedded C application which is developed using the CrossWorks for ARM toolchain.

This project targets a specific processor which is getting old and hard to source, we are working towards revising our design with a new processor. So my plan is to divide the source code into a set of low level driver code which targets the old processor, and another set of common code which will be able to compile on both processors.

I got started making a drivers project which compiles down to a drivers.a file. Currently this file is literally empty. It's entire contents are

!<arch>

The problem I have is that mealy including this file into the compilation of the common code causes much bloating of the compiled size. And the resulting binary is about 33% larger...

Below is an example of the size of some of the sections from the map file, the symbols listed are the FatFs functions.

Size without drivers.a          Size with drivers.a
f_close         76              f_close         148         
f_closedir      84              f_closedir      136         
f_findfirst     48              f_findfirst     108         
f_findnext      116             f_findnext      144         
f_getfree       368             f_getfree       636         
f_lseek         636             f_lseek         1,148       
f_mkdir         488             f_mkdir         688         
f_mount         200             f_mount         256         
f_open          1,096           f_open          1,492       
f_opendir       324             f_opendir       472         
f_read          564             f_read          1,132       
f_readdir       176             f_readdir       268         
f_stat          156             f_stat          228         
f_sync          244             f_sync          440         
f_unlink        380             f_unlink        556         
f_write         668             f_write         1,324           

So clearly because of the additional drivers.a file the linker is unable to determine that certain parts of the code are unreachable due to the possibility that the linked in drivers.a code would call those routines. This makes sense I guess, but I need a way to get around it so that I can divide the code into separately maintainable code, while still compiling down as efficiently as before.

I hand not realized that linking *.a files could have this consequence, I previously had the mental image that *.a files were no different from a bunch of *.o files effectively tar'ed together into a single file. Clearly this isn't the case.


Solution

  • It turns out this has nothing to do with mealy linking in the drivers.a file...

    The way I had my project set up the compiler options were changing when I included the drivers.a. Effectively I believe I was actually comparing Debugging Level 3 to Debugging Level 2, in which case the added binary size is understandable.