MicrocontrollerMicros

The Easiest Way to Calculate Function Size in C

Unfortunately calculating function size is not as easy of finding variable size using sizeof() compile-time operator. There are numerous ways to calculate the size in run-time but to keep things simple, it’s better to check that information from linker, as for sure must knows it.

Let’s talk about what things we are going to use:

 

1- “.map” file generated by GCC/G++ linker:

 

This file has the symbols we have in the code/firmware either in flash, RAM or any other defined memory section. The following snippet is taken from compiling one of the examples of nRF52 SDK. If you want to try just run make default inside the following directory examples\peripheral\gpiote\pca10040\blank\armgcc. The first column is the symbol start address, the second column is the function size in HEX and the third one is the object file name containing that symbol.

You can scan this file until you find the function you’re looking for and find its length and start address. For instance bsp_board_led_invert takes 36 bytes in Flash.

 

2- “.out” file generated by GCC/G++ and NM GNU tool

 

Sometimes it’s hard to search a symbol in the .map file here comes nm tool found with GCC tool-chain to list all symbols in an object file. To list all your code symbols then use the .out file with nm or .elf file should also do the job too. This tool can list the symbols and also sort the symbols according to the size. I have the .out file from the first step, so simply to list the symbols by size run the following command (make sure you’re using the right command as I’m using ARM GCC here)

And here is a snippet from output

The first column is the start address in decimal, then the length and the symbol name.

 

Weird Symbols Names ?

 

If you found strange names as symbols, and mostly strange characters added as suffix and prefix to a function or variable name you know, then this comes from what is called name mangling. For example, get_event function could become something like that:

Why? This is because the compiler needs unique names for variables, functions, …etc and while we can have static variables or functions with same names in different source files, then the compiler need to distinguish between them. The same thing is applicable to c++ for overloading also.

To de-mangle the name, C++filt is the tool used to produce the original name, for example running the following to de-mangle the past example:

AD Space

Yahya Tawil

Embedded Hardware Engineer interested in open hardware and was born in the same year as Linux. Yahya is the editor-in-chief of Atadiat and believes in the importance of sharing free, practical, spam-free and high quality written content with others. His experience with Embedded Systems includes developing firmware with bare-metal C and Arduino, designing PCB&schematic and content creation.

4 Comments

  1. #include
    static int f(int x) { return x + 3; }
    static void following_f() { }
    int main() { return !printf(“%ld\n”, (long)following_f – (long)f); }

    1. Yeah, it’s a nice one but I feel not comfortable with it for 2 reasons:
      1- I had to do that for each function I would like to know its size and sometimes debugging messages are not available in the release edition of the firmware.
      2- I don’t trust linker that will fit the 2 functions sequentially in the memory.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.