9

I have created a small program as a proof-of-concept for a system which are to be implemented on an embedded platform. The program is written in C++11 with use of std and compiled to run on a laptop. The final program which should be implemented later is an embedded system. We do not have access to the compiler of the embedded platform.

I would like to know if there is a way to determine a programs static memory (the size of the compiled binaries) in a sensible and comparable way when it should be ported to an embedded platform. The requirement is that the size of the binary is less than 10kb. Our binary has a size of 700Kb when compiled and stripped with the following flags:

g++ options:     -Os -s -ffunction-sections -fdata-sections
linker options:  -s -Wl,--gc-sections

strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note

It took up 4MB before we used strip and optimization options.

I am still way off and it is not really that big a program. How can I justify a comparison in any way with an equivalent program on an embedded platform.

CodeTower
  • 6,293
  • 5
  • 30
  • 54
  • 2
    While there may be some easily removed bloat, there's a high chance you will need to do some major re-architecting and re-writing with an embedded mindset to hit a 10Kb target size. Also, is your laptop build statically linked (often very difficult to do today)? If the embedded version will need to be, it's only fair for the comparison to be as well. And while you don't mention it, most platforms that would restrict you to 10Kb code also have severe RAM limits as well. – Chris Stratton May 29 '13 at 17:42
  • Every library used and statically linked will bloat your final code. Also, for such a small app, does it have floating point support? If not, there is another area to beware. POD types versus classes in arrays can also bloat heavily. I've done this type of thing quite a few times and the map file / sections suggested below is an excellent place to start. – Michael Dorgan May 29 '13 at 18:42
  • 2
    Can you compile with `-fno-rtti` and `-fno-exceptions`? These generate large tables which normally sit on a disk for a PC. However, they need to occupy RAM/Flash on an embedded device. Typical saving were 10-30%, the last time I measured. The CPU ISA can reduce/increase code size by +/-30% as well. Still, you have some work to do as [Chris](http://stackoverflow.com/users/429063/chris-stratton) points out. – artless noise May 29 '13 at 20:01

2 Answers2

5

Note that the size of the binary can be a little deceptive in the sense that uninitialised variables, the .bss sections, will not necessarily take up physical space in the binary as these are generally just noted as present without actually have any space given to them... this normally happens by the OS loader when it runs your program.

objdump (http://www.gnu.org/software/binutils/) or perhaps elfdump or the elf tool chain (http://sourceforge.net/apps/trac/elftoolchain/) will help you determine the size of your various segments, data and text, as well as the size of individual functions and globals etc. All these programs "look" into your compiled binary and extract a lot of information such as the size of the .text, .data section, list the various symbols, their locations and sizes, and can even dissasemble the .text section...

An example of using elfdump on an ELF image test.elf might be elfdump -z test.elf > output.txt. This will dump everything including text section dissassembly. For example, from an elfdump on my system I saw

Section #6: .text, type=NOBITS, addr=0x500, off=0x5f168
             size=149404(0x2479c), link=0, info=0, align=16, entsize=1
             flags=<WRITE,ALLOC,EXECINSTR>
Section #7: .text, type=NOBITS, addr=0x24c9c, off=0x5f168
             size=362822(0x58946), link=0, info=0, align=4, entsize=1
             flags=<WRITE,ALLOC,EXECINSTR,INCLUDE>
....
Section #9: .rodata, type=NOBITS, addr=0x7d5e4, off=0x5f168
             size=7670(0x1df6), link=0, info=0, align=4, entsize=1
         flags=<WRITE,ALLOC>

So I can see how much my code is taking up (the .text sections) and my read only data. Later in the file I then see...

Symbol table ".symtab"
         Value    Size     Bind Type Section                  Name
         -----    ----     ---- ---- -------                  ----
218      0x7c090  130      LOC  FUNC .text               IRemovedThisName

So I can see that my function IRemovedThisName takes 130 bytes. A quick script would allow you list functions sorted by size and variables sorted by size. This could point you at places to optimize...

For a good example of objdump try http://www.thegeekstuff.com/2012/09/objdump-examples/, specifically the section 3, which shows you how to get the contents of the section headers using the -h option.

As to how the program will compare on two different platforms I think you will just have to compile on both platforms and compare the results you get from your obj/elfdump on each system - the results will depend on the system instruction set, how well each compiler can optimize, general hardware architecture differences etc.

If you don't have access to the embedded system, you might try using a cross-compiler, configured for your eventual target, on your laptop. This would give you a binary suited to the embedded platform and the tools to analyze the file (i.e. the cross-platform version of objdump). This would give you some ball-park figures for how the program would look on the eventual embedded sys.

Hope this helps.

EDIT: This will also help How to get the size of a C function from inside a C program or with inline assembly?

Community
  • 1
  • 1
Jimbo
  • 4,352
  • 3
  • 27
  • 44
1

It appeared that the included libraries took up an enormous of space (as it was pointed out in the comment) and by removing these it was possible to reduce the size to nearly nothing in combination with the following flags:

set(CMAKE_CXX_FLAGS "-Os -s  -ffunction-sections -fdata-sections -DNO_STD -fno-rtti -fno-exceptions")
set(CMAKE_EXE_LINKER_FLAGS "-s -Wl,--gc-sections")  

And stripping away any unnecessary code using:

strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note

The 4MB could be reduced to 9.4kb which is below our limit.

In summary, std takes up an tremendous amount of space.

CodeTower
  • 6,293
  • 5
  • 30
  • 54