Knowledge · IAR

IAR firmware SBOM: reading components from the .out

From the .out: compiler and linker with their versions, linked libraries and functions, and some component versions.

IAR Embedded Workbench for Arm writes the linker output as an .out, an ELF file with DWARF debug information. In the public example the FreeRTOS version is in the image, the versions of FreeRTOS+TCP and the HAL are not: the project headers supply those.

As of 23 October 2026 · 5 min readYou make the conformity statement. This page and our reports provide technical findings as its basis.

The test subject
Project
USB RNDIS demo with HTTP server, IAR EWARM
Chip
STM32F411, Cortex-M4
File
ITAT_RNDIS.out, debug build, 1,072,120 bytes
SHA-256
8c2b9a4dcc3b16532d8b0a0e470433436844cbd70aeab33b17d917070a852f08

Public on GitHub, commit 1fd48f2 (MIT)

The test subject: Public on GitHub, commit 1fd48f2 (MIT)

Which files does an IAR build produce?

According to IAR, the ILINK linker produces “an absolute object file containing the executable image in the ELF (including DWARF for debug information) format”. It produces no other formats; HEX, S-record or BIN for the flash are made from it with ielftool.

FileWhat it contains
.outThe image as ELF with symbols and DWARF debug information. The file for the analysis.
.mapLinker version, command line, the contribution of each module and library to the image, all public symbols with their origin.
.hex .srec .binMade from the .out with ielftool. Only the bytes for the flash, without symbols.

Step 1: With which toolchain and for which target was it built?

The .comment section carries the linker version and the full linker command line with all object files and libraries. This puts the compiler in the SBOM as a build tool.

File type
file ITAT_RNDIS.out

Output

ITAT_RNDIS.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
Linker version
strings -a ITAT_RNDIS.out | grep -m1 "IAR ELF Linker"

Output

IAR ELF Linker V9.10.1.308/W64 for ARM
How often the compiler names itself in the image
strings -a ITAT_RNDIS.out | grep -c "IAR ANSI C/C++ Compiler V9.10.1.308/W64 for ARM$"
Output
713

Step 2: What is linked?

The symbol table shows which functions are in the image: here the FreeRTOS kernel, the CMSIS-RTOS2 layer and the FreeRTOS+TCP TCP/IP stack.

A function name alone is no proof. tcpip_init sounds like lwIP, but in this project it is a function of the demo itself: not a single symbol with lwip_ is in the image. A component belongs in the SBOM only when several pieces of evidence agree.

Linked functions from FreeRTOS, CMSIS-RTOS2 and FreeRTOS+TCP
nm ITAT_RNDIS.out | grep -E " T (FreeRTOS_IPInit|FreeRTOS_socket|vTaskStartScheduler|xTaskCreate|osKernelStart|tcpip_init)$"

Output

08004797T FreeRTOS_IPInit0800272bT FreeRTOS_socket08007f31T osKernelStart0800656dT tcpip_init08005305T vTaskStartScheduler08004fffT xTaskCreate
Symbols from lwIP or mbedTLS
nm ITAT_RNDIS.out | grep -c -E "lwip_|mbedtls_"
Output
0

Step 3: Which versions are in the .out?

Here the FreeRTOS version is in the image itself, in the flash area between the HTTP server's text. With IAR the source paths in the DWARF name the project folders, for example Middlewares\Third_Party\FreeRTOS-Plus-TCP, but no version in the path.

Because the version sits in flash, it is in the BIN too. There it sits 0x34 bytes earlier, at 0x890c: the BIN starts with the first flash section, while the .out has the 52-byte ELF header in front of it. In the Keil example the version was only in the debug information and missing from the BIN.

For FreeRTOS+TCP and the HAL there is no version in the image. It comes from the project headers: FreeRTOS+TCP V2.3.2 LTS Patch 1 in FreeRTOS_IP.c and HAL 1.7.13 in stm32f4xx_hal.c. In the SBOM these versions belong to the component, with a note on where they come from.

FreeRTOS version with file offset
strings -a -t x ITAT_RNDIS.out | grep -m1 "V10.3.1"

Output

   8940 V10.3.1
The same version in the BIN of the same build
strings -a -t x ITAT_RNDIS.bin | grep "V10.3.1"

Output

   890c V10.3.1
Source path to FreeRTOS+TCP in the DWARF (first match)
strings -a ITAT_RNDIS.out | grep -m1 -i "FreeRTOS-Plus-TCP"

Output

D:\GitHub\STM32F4XX_RNDIS_DEMO\Middlewares\Third_Party\FreeRTOS-Plus-TCP\portable\BufferManagement\BufferAllocation_2.c

Step 4: What does the map file show?

According to IAR, ILINK loads only the library modules the application needs and eliminates sections that are not required. The map file shows the result. It is written with --map, in the IDE under Project > Options > Linker > List. Its header names linker version, date and command line, the MODULE SUMMARY the contribution of each module to the image, sorted by directory and library.

In the test subject, 18 object files are on the linker command line but missing from the MODULE SUMMARY. Among them are FreeRTOS_DNS.o and FreeRTOS_DHCP.o. The DNS and DHCP parts of FreeRTOS+TCP have no code in this image. A vulnerability that affects only these parts does not affect this device.

The four libraries at the end of the list are IAR's runtime. Their name encodes the variant: dl7M_tlf.a is the C library for Armv7-M in Thumb mode, little-endian, Full configuration. m7M_tls.a is the math library, s meaning VFP for single precision only. Their version is the toolchain's version.

Header of the map file
grep -m1 "IAR ELF Linker" ITAT_RNDIS.map

Output

# IAR ELF Linker V9.10.1.308/W64 for ARM                  27/Nov/2021  23:47:44
FreeRTOS+TCP in the MODULE SUMMARY
sed -n '/MODULE SUMMARY/,/Grand Total/p' ITAT_RNDIS.map | grep -A10 "FreeRTOS_TCP: \[8\]"

Output

D:\GitHub\STM32F4XX_RNDIS_DEMO\EWARM\ITAT_RNDIS\Obj\Middlewares\FreeRTOS_TCP: [8]
    BufferAllocation_2.o              348        4      508
    FreeRTOS_ARP.o                  1'068       40       76
    FreeRTOS_IP.o                   3'412               110
    FreeRTOS_Sockets.o              4'212                44
    FreeRTOS_Stream_Buffer.o          308
    FreeRTOS_TCP_IP.o               9'228
    FreeRTOS_TCP_WIN.o              1'986                24
    FreeRTOS_UDP_IP.o                 344        7       24
    NetworkInterface.o                 36
    -------------------------------------------------------
The runtime libraries in the image
sed -n '/MODULE SUMMARY/,/Grand Total/p' ITAT_RNDIS.map | grep -E "^[A-Za-z0-9_]+\.a: "

Output

dl7M_tlf.a: [12]
m7M_tls.a: [13]
rt7M_tl.a: [14]
shb_l.a: [15]

What does this mean for the SBOM?

FreeRTOS V10.3.1 is in the version range of CVE-2021-31571, CVE-2021-31572 and CVE-2021-32020, which NVD lists for FreeRTOS before 10.4.3. Whether one of them can be exploited in the device depends on the use of the affected functions.

ComponentVersion and evidence
FreeRTOS kernelV10.3.1, in the image at offset 0x8940, confirmed by task.h
FreeRTOS+TCPV2.3.2 LTS Patch 1, from FreeRTOS_IP.c; in the image only the name
STM32F4 HAL1.7.13, from stm32f4xx_hal.c; in the image only functions
IAR runtime librariesdl7M_tlf.a, m7M_tls.a, rt7M_tl.a, shb_l.a per the map file, version of the toolchain
IAR compiler and linkerV9.10.1.308, from .comment, as build tool

Can this run automatically?

LegacyMind reads the linked libraries and the toolchain with its version from .out, .elf and .axf files, and from Keil and GNU Arm builds also the library versions. It adds the hardening (stack protection, MPU, privilege separation). If the file evidences no version, the field stays blank. You export the SBOM as CycloneDX or SPDX.

Questions

Which IAR file should I use?

The .out from your project's Exe folder, plus the .map from the List folder. A HEX or BIN from ielftool holds only the bytes for the flash, without symbols and debug information.

Is every library's version in the .out?

No. Some libraries write their version into the image, others do not. Then the project headers or release notes supply the version, and the SBOM notes where it comes from.

Does the map file help?

Yes. It lists per module and library what ends up in the image, and where each symbol comes from. Next to the .out it is the best source for whether a library is really linked.

Why are files that were built missing from the MODULE SUMMARY?

Because ILINK takes in only what the program needs. In the example, 18 object files are on the command line and contribute nothing to the image, among them DNS and DHCP of FreeRTOS+TCP. --no_remove turns off the removal of unused sections.

How do I generate the map file in IAR Embedded Workbench?

With the linker option --map, in the IDE under Project > Options > Linker > List, Generate linker map file. In the example it sits in the project's List folder.

Is it different with Keil?

Keil writes an .axf, also an ELF file. In the public Keil example the FreeRTOS version is also in the source path, third_party/FreeRTOSv10.1.1; in the IAR example it is not.

Sources

  1. [1]IAR: Linker overview (EWARM 9.7x)
  2. [2]IAR: The IAR ELF Tool, ielftool
  3. [3]IAR: Linker option --map
  4. [4]IAR: Linker option --no_remove
  5. [5]IAR: Prebuilt runtime libraries, library filename syntax
  6. [6]Test subject: nicokorn/STM32F4XX_RNDIS_DEMO, commit 1fd48f2
  7. [7]NVD: CVE-2021-31571

Check your own image

Upload one firmware image, an AXF or a supplier SBOM in your own LegacyMind account. Report and SBOM within three working days, NDA on request. The app and the reports are in German; questions in English are welcome.