# How to Dig into Firmware Code Size

**URL:** <https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45>\
**Category:** Blog\
**Created:** [June 6, 2019, 9:12pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45 "2019-06-06T21:12:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![discobot](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/discobot/32/1_2.png) [@discobot](https://community.memfault.com/u/discobot)\
**Post date:** [June 6, 2019, 9:12pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/1 "2019-06-06T21:12:39Z")

</div>

Every firmware engineer has run out of code space at some point or another. Whether they are trying to cram in another feature, or to make enough space for [A/B firmware updates](https://sbabic.github.io/swupdate/overview.html#double-copy-with-fall-back) more code space is always better.

* * *
This is a companion discussion topic for the original entry at [https://interrupt.memfault.com/blog/best-firmware-size-tools](https://interrupt.memfault.com/blog/best-firmware-size-tools)

---

<div class="post-metadata">

**Author:** ![ngotes](https://avatars.discourse-cdn.com/v4/letter/n/c57346/32.png) [@ngotes](https://community.memfault.com/u/ngotes)\
**Post date:** [August 18, 2019, 8:24am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/2 "2019-08-18T08:24:54Z")

</div>

Hi,

First of all, thanks a lot for this article, it’s very helpful!  
My question is - does the pacover tool works also on axf files? if yes, how do I need to prepare my codebase?

---

<div class="post-metadata">

**Author:** ![chrisc](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/chrisc/32/22_2.png) [@chrisc](https://community.memfault.com/u/chrisc)\
**Post date:** [August 18, 2019, 8:53pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/3 "2019-08-18T20:53:51Z")

</div>

Hi @ngotes

The puncover tool works on any file that was built with debug information and stored in the ELF file format.

`.axf` (and `.out`) files usually use the ELF format so you should just be able to follow the instructions as is.

You can easily check to see if the file is in the ELF format by checking to see if the file starts with the [EI\_MAG header](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header) which is 0x7F followed by ‘E’, ‘L’, ‘F’. For example, here’s an axf file I generated recently using the NXP MCUXpressoIDE:

```auto
xxd lpcxpresso55s69_freertos_blinky_s.axf | head -1
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............

```

You can use a tool like readelf to check and see if the ELF was compiled with debug information. If it was there will be debug\_\* sections in the file, i.e

```auto
arm-none-eabi-readelf -S lpcxpresso55s69_freertos_blinky_s.axf | grep debug
  [10] .debug_info PROGBITS 00000000 02fe60 01dab9 00 0 0 1
  [11] .debug_abbrev PROGBITS 00000000 04d919 003287 00 0 0 1
  [12] .debug_aranges PROGBITS 00000000 050ba0 0009d8 00 0 0 1
  [13] .debug_ranges PROGBITS 00000000 051578 000948 00 0 0 1
  [14] .debug_macro PROGBITS 00000000 051ec0 01a019 00 0 0 1
  [15] .debug_line PROGBITS 00000000 06bed9 008c00 00 0 0 1
  [16] .debug_str PROGBITS 00000000 074ad9 0d42f3 01 MS 0 0 1
  [19] .debug_frame PROGBITS 00000000 148ef8 002a44 00 0 0 4
  [20] .debug_loc PROGBITS 00000000 14b93c 0009d1 00 0 0 1

```

---

<div class="post-metadata">

**Author:** ![ngotes](https://avatars.discourse-cdn.com/v4/letter/n/c57346/32.png) [@ngotes](https://community.memfault.com/u/ngotes)\
**Post date:** [August 21, 2019, 6:23am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/4 "2019-08-21T06:23:43Z")

</div>

Hi @chrisc

Thanks a lot for the detailed answer.  
It works fine on both files!

---

<div class="post-metadata">

**Author:** ![chrisc](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/chrisc/32/22_2.png) [@chrisc](https://community.memfault.com/u/chrisc)\
**Post date:** [August 21, 2019, 3:23pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/5 "2019-08-21T15:23:51Z")

</div>

Great! Glad to hear it!

---

<div class="post-metadata">

**Author:** ![rdmeneze](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/rdmeneze/32/78_2.png) [@rdmeneze](https://community.memfault.com/u/rdmeneze)\
**Post date:** [July 27, 2020, 12:17pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/6 "2020-07-27T12:17:29Z")

</div>

well, the puncover do not works with Windows 10…  
😒

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [July 28, 2020, 2:29am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/7 "2020-07-28T02:29:40Z")

</div>

@rdmeneze Could you share more information? What problem did you run into? It should work fine provided you have the right tools installed.

---

<div class="post-metadata">

**Author:** ![rdmeneze](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/rdmeneze/32/78_2.png) [@rdmeneze](https://community.memfault.com/u/rdmeneze)\
**Post date:** [July 28, 2020, 11:17am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/8 "2020-07-28T11:17:28Z")

</div>

I’m using the same configuration that you described at the post.

well, look the error bellow:

> (venv) C:\sources\git\tools\puncover\>python runner.py --arm\_tools\_dir=c:\arm\8-2019-q3-update --elf\_file c:\sources\git\fw\imetos\iMetos3\_RTX\iMetosEcoD3\_Full\_Debug\iMetos3\_RTX.elf  
> DEPRECATED: argument --arm\_tools\_dir will be removed, use --gcc\_tools\_base instead.  
> parsing ELF at c:\sources\git\fw\imetos\iMetos3\_RTX\iMetosEcoD3\_Full\_Debug\iMetos3\_RTX.elf  
> Traceback (most recent call last):  
> File “runner.py”, line 11, in   
> main()  
> File “C:\sources\git\tools\puncover\puncover\puncover.py”, line 58, in main  
> builder.build\_if\_needed()  
> File “C:\sources\git\tools\puncover\puncover\builders.py”, line 32, in build\_if\_needed  
> self.build()  
> File “C:\sources\git\tools\puncover\puncover\builders.py”, line 22, in build  
> self.collector.parse\_elf(self.get\_elf\_path())  
> File “C:\sources\git\tools\puncover\puncover\collector.py”, line 306, in parse\_elf  
> self.parse\_assembly\_text(“”.join(self.gcc\_tools.get\_assembly\_lines(elf\_file)))  
> File “C:\sources\git\tools\puncover\puncover\gcc\_tools.py”, line 27, in get\_assembly\_lines  
> return self.gcc\_tool\_lines(‘objdump’, [‘-dslw’, os.path.basename(elf\_file)], os.path.dirname(elf\_file))  
> File “C:\sources\git\tools\puncover\puncover\gcc\_tools.py”, line 23, in gcc\_tool\_lines  
> proc = subprocess.Popen([self.gcc\_tool\_path(name)] + args, stdout=subprocess.PIPE, cwd=cwd)  
> File “C:\sources\git\tools\puncover\puncover\gcc\_tools.py”, line 18, in gcc\_tool\_path  
> raise Exception(“Could not find %s” % path)  
> Exception: Could not find c:\arm\8-2019-q3-update\bin/arm-none-eabi-objdump

---

<div class="post-metadata">

**Author:** ![tyler](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/tyler/32/18_2.png) [@tyler](https://community.memfault.com/u/tyler)\
**Post date:** [July 28, 2020, 6:24pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/9 "2020-07-28T18:24:18Z")

</div>

There seem to be a couple of solutions that you could patch on top of puncover in this Github Issue to get Windows to work: [https://github.com/HBehrens/puncover/issues/37](https://github.com/HBehrens/puncover/issues/37).

If you have any favorite tools to explore code size on Windows, I’d love to link them in this post.

---

<div class="post-metadata">

**Author:** ![donar](https://avatars.discourse-cdn.com/v4/letter/d/8baadc/32.png) [@donar](https://community.memfault.com/u/donar)\
**Post date:** [September 4, 2020, 11:13am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/10 "2020-09-04T11:13:10Z")

</div>

hey there. I wanted to use puncover for a msp430 gcc toolchain. Is this specifically made for arm controllers? because i get the following error message:

```
raise Exception("Could not find %s" % path)

```

Exception: Could not find C:…\msp430-gcc-8.3.0.16\_win32\bin/arm-none-eabi-objdump

this file is in my case named: msp430-elf-objdump

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [September 4, 2020, 5:21pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/11 "2020-09-04T17:21:23Z")

</div>

@donar I believe it’s only ever been tested with ARM, but you may be able to get it to work by setting the `--gcc_tools_base` path rather than the `--arm_tools_dir` flag. Something like `--gcc_tools_base=C:\...msp430-gcc-8.3.0.16_win32\bin\msp430-none-eabi-`

Let me know if that works!

---

<div class="post-metadata">

**Author:** ![donar](https://avatars.discourse-cdn.com/v4/letter/d/8baadc/32.png) [@donar](https://community.memfault.com/u/donar)\
**Post date:** [September 7, 2020, 5:00am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/12 "2020-09-07T05:00:59Z")

</div>

@francois Thanks for the answer. I get the following output, and after jumping over the python code I think it will not work without changes

C:\repos\python\puncoverTest\venv\Scripts\>puncover.exe --gcc\_tools\_base=C:/ti/ccs920/ccs/tools/compiler/msp430-gcc-8.3.0.16\_win32/bin/ --elf\_file C:\Users\baerch\workspace\_v9\_2\testCCode\Debug\testCCode.out  
parsing ELF at C:\Users\baerch\workspace\_v9\_2\testCCode\Debug\testCCode.out  
Traceback (most recent call last):  
File “C:\repos\python\puncoverTest\venv\Scripts\puncover-script.py”, line 11, in   
load\_entry\_point(‘puncover==0.0.1’, ‘console\_scripts’, ‘puncover’)()  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\puncover.py”, line 58, in main  
builder.build\_if\_needed()  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\builders.py”, line 32, in build\_if\_needed  
self.build()  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\builders.py”, line 22, in build  
self.collector.parse\_elf(self.get\_elf\_path())  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\collector.py”, line 306, in parse\_elf  
self.parse\_assembly\_text("".join(self.gcc\_tools.get\_assembly\_lines(elf\_file)))  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\gcc\_tools.py”, line 27, in get\_assembly\_lines  
return self.gcc\_tool\_lines(‘objdump’, [’-dslw’, os.path.basename(elf\_file)], os.path.dirname(elf\_file))  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\gcc\_tools.py”, line 23, in gcc\_tool\_lines  
proc = subprocess.Popen([self.gcc\_tool\_path(name)] + args, stdout=subprocess.PIPE, cwd=cwd)  
File “C:\repos\python\puncoverTest\venv\lib\site-packages\puncover\gcc\_tools.py”, line 18, in gcc\_tool\_path  
**raise Exception(“Could not find %s” % path)**  
Exception: Could not find C:/ti/ccs920/ccs/tools/compiler/msp430-gcc-8.3.0.16\_win32/bin/objdump

---

<div class="post-metadata">

**Author:** ![tyler](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/tyler/32/18_2.png) [@tyler](https://community.memfault.com/u/tyler)\
**Post date:** [September 8, 2020, 3:18am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/13 "2020-09-08T03:18:30Z")

</div>

You can find a patch to make it work on Windows on this Github issue: [https://github.com/HBehrens/puncover/issues/37](https://github.com/HBehrens/puncover/issues/37)

---

<div class="post-metadata">

**Author:** ![donar](https://avatars.discourse-cdn.com/v4/letter/d/8baadc/32.png) [@donar](https://community.memfault.com/u/donar)\
**Post date:** [September 8, 2020, 10:46am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/14 "2020-09-08T10:46:12Z")

</div>

Main problem is that all the gcc stuff is named with the prefix : msp430-elf-…exe.  
After I renamed all the needed files I got the error message: AttributeError: ‘Collector’ object has no attribute ‘parse\_size\_line\_re’

---

<div class="post-metadata">

**Author:** ![czr](https://avatars.discourse-cdn.com/v4/letter/c/ba8739/32.png) [@czr](https://community.memfault.com/u/czr)\
**Post date:** [September 17, 2020, 7:57am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/15 "2020-09-17T07:57:28Z")

</div>

Hi all,

Since this is the best documentation on how to use puncover, I’d like to add some corrections that were necessary to get things working (ran through the article yesterday).

1. Please use upstream [https://github.com/HBehrens/puncover](https://github.com/HBehrens/puncover) version instead of the memfault fork (not clear why one should use the memfault version, other than tox support).
2. To install, after checkout: `python3 ./setup.py install --user` . This will handle all of the requirements and install puncover to user controlled directory (`/home/user/.local/bin/puncover` over here, on Ubuntu). `puncover` should then be executable just by the program name (`~/.local/bin/` should be already in your `PATH`). Using python2.7 will not work. Running setup like this replaces the **Setting up for puncover** section in the article.
3. I’m not sure whether `-fdebug-prefix-map` is required anymore. Things seem to work here without it with `build_dir` option to puncover.
4. Since the article came out, puncover learned to also collate the build time generated stack usage information. Add `-fstack-usage` option to your GCC runs to get the `*.su` files that puncover will collect.

I use the following command line for a project that is built in the source directory (yes I know it’s bad, but it’s just a sandbox for playing):  
`puncover --gcc_tools_base /home/user/local/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi- --elf_file ${PWD}/generic-test.elf --build_dir ${PWD}`

Important bit here being that the expected format for the new `gcc_tools_base` is a prefix, not just a path (compared to the old `arm_tools_dir`). The paths to the puncover options also need to be absolute.

After this, you should have nice interactively navigatable view into stack, static SRAM and code space usage.

---

<div class="post-metadata">

**Author:** ![Remember](https://avatars.discourse-cdn.com/v4/letter/r/ecccb3/32.png) [@Remember](https://community.memfault.com/u/Remember)\
**Post date:** [December 4, 2020, 7:13am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/16 "2020-12-04T07:13:42Z")

</div>

I got `puncover` from [HBehrens’ repository](https://github.com/HBehrens/puncover) and installed it successfully. But I cannot get the output in a webpage. How could I figure out what’s wrong here?

 ![puncover](https://canada1.discourse-cdn.com/flex030/uploads/memfault/original/1X/58cd7a77f7aba3ff7c230c5887cf80378ef63d76.png)

---

<div class="post-metadata">

**Author:** ![sjalloq](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@sjalloq](https://community.memfault.com/u/sjalloq)\
**Post date:** [February 18, 2021, 4:02pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/17 "2021-02-18T16:02:09Z")

</div>

Looks like the instructions for Puncover are out of date now. I think you just need to ‘pip install -e .’ from the cloned repo.

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [February 19, 2021, 7:01am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/18 "2021-02-19T07:01:55Z")

</div>

Split this topic on February 19, 2021, 7:01am UTC

A post was split to a new topic: [BSS section larger than expected](https://community.memfault.com/t/bss-section-larger-than-expected/355)

---

<div class="post-metadata">

**Author:** ![bora](https://avatars.discourse-cdn.com/v4/letter/b/e56c9b/32.png) [@bora](https://community.memfault.com/u/bora)\
**Post date:** [July 28, 2021, 1:57pm UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/19 "2021-07-28T13:57:36Z")

</div>

Hi, I tried out puncover and really like the interface, however the code size reporting is not accurate for me. Some symbols are reported with a lower code size (compared to the size reported by nm), resulting in around 10% lower than the actual total size. I don’t understand the cause yet, but someone else in GitHub has a similar issue: [use map files instead of output from nm as a source of symbols and sizes · Issue #41 · HBehrens/puncover · GitHub](https://github.com/HBehrens/puncover/issues/41). If someone has an idea, I would be interested.

Bloaty reports the sizes accurately, however I found the usage a bit confusing and not as powerful as the GUI of puncover. Nevertheless it could be strong basis for a visual tool.

There is one more tool I would like to share: [GitHub - ARMmbed/mbed-os-linker-report: Post-processing of linker output to calculate and visualize memory usage for elf-sections](https://github.com/ARMmbed/mbed-os-linker-report). This one comes from the Mbed community and has a very useful pie chart visualization. However this also suffers from the same inaccuracy issue with puncover. Maybe they use the same tooling underneath, I didn’t look into it that much.

---

<div class="post-metadata">

**Author:** ![ali-rostami](https://avatars.discourse-cdn.com/v4/letter/a/b5ac83/32.png) [@ali-rostami](https://community.memfault.com/u/ali-rostami)\
**Post date:** [December 15, 2023, 10:41am UTC](https://community.memfault.com/t/how-to-dig-into-firmware-code-size/45/20 "2023-12-15T10:41:40Z")

</div>

Hi, thanks for your nice article.  
Puncover seems a very nice tool. But it doesn’t show me anything in the stack column. Folders are also unknown!

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/memfault/original/1X/9eacaa243100c8047e8a98ae7cf42543fd881162.png)

Any idea what is wrong here?

PS: I used these flags, in my make file:  
CFLAGS += -fstack-usage  
CFLAGS += -fdebug-prefix-map=/=
