Memory usage on microcontroller programs

This is only a short post, mostly to remind myself. When writing code for microcontrollers, memory usage is often a concern – both for flash and for RAM. Currently I am using an AVR32 processor with 512kb flash and 64kb RAM, which is plenty for a lot of applications, but in some cases particularly the RAM can become thin. Fortunately there are multiple ways to monitor memory usage, and figure out where the memory is used:

To show the memory use of the various sections, avr32-size can be added to the makefile:

avr32-size $(IntermediateDirectory)/../$(ProjectName).elf

Which will produce an output like this:

   text	   data	    bss	    dec	    hex	filename
 107234	   5016	  16236	 128486	  1f5e6	program.elf

The ‘text’ section represents all the executable code. Data contains initialisation values and constants, and will also end up in the flash. The ‘bss’ section is the RAM. So, all in the green for this example.

But what if we need to reduce memory usage? Where are the biggest offenders? This is where the utilities ‘readelf’, ‘nm’ and ‘pahole’ come in.

nm

avr32-nm -S program.elf

This shows all defined symbols with their memory address and size, and which section they are in (e.g. ‘T’ for text=code, or ‘b’ for uninitialised=variables). It is very useful to get the sizes of functions, to know where to start optimising the code for size, and to see how much the compiler optimisation can do. However, I found that it is not so good for displaying variables. I’m probably doing it wrong, but there are a lot of them missing in the output.

readelf

avr32-readelf -sW program.elf | sort -k3 -nr

This will show a table of functions and variables as well, sorted by size. And this time all globally defined variables are there. This is a good start for analysing data structures, but in my case, most data is stored in structs, which themselves can contain more structs. As readelf will only show the top instance, it is not easy to see what exactly uses how much. Poke-a-hole (pahole) to the rescue!

Pahole

This is a strange but very useful tool. Useful, because it can go into structs, show exactly how much each of their sub-members use, how they are aligned in memory, if there are any gaps, and even suggest optimisations. Strange, because the output is a c-like code dump with annotations in c-style comments, which makes it very difficult to parse with follow-up tools or frontends. More on that later I think, as I’m hoping to write a graphical interactive tool that makes this sort of analysis quicker and easier.

pahole -Ia program.elf

will list all structs with their memory layout and sizes behind each line. It is also possible to specify a particular struct to limit the output with the -C option:

pahole -I -C example_struct_t program.elf

will only show ‘example_struct_t’.

Note that structs have to be defined with a name, i.e. not as an anonymous  struct. With the -a option, pahole does show anonymous structs as well, but the -C option will ignore them. The struct definition would look like this:

typedef struct example_struct_t {
   int a;
} example_struct_t;

While this is already very useful, I would like to have a tool that lists all data structures and functions in a tree structure, where it is possible to unfold subsections, filter and sort interactively, and click through to the actual source file for code analysis and editing. Parsing the pahole output will be annoying – maybe there is a way to get a more machine-readable output, or alternatively lift the useful parts from its source code and integrate it into a new tool. But for now, this is all. Happy optimising!

Leave a Reply

Your email address will not be published. Required fields are marked *