Understanding Map Files in Cortex-M Development

Hello everyone, I am Pi Zi Heng, a serious techie. Today, I will talk to you about map files in embedded development.

In the fourth lesson, I introduced the first type of output file – relocatable files. This article continues to discuss the second type of output file generated by the project – map files. Map files record a lot of important information, which is very helpful for subsequent debugging.

File relationships: Linker file (.icf) + Project file (.ewp) + Relocatable files (.o/.a) -> Map file (.map)

In the fourth lesson, when analyzing the symbol list in the object files (.o/.a), I mentioned that since object files have not been linked, all symbol address information is invalid (to be allocated). The map file is generated after all relocatable files are linked together by the linker, and it records the linking information. The map file can show the specific allocated addresses of all symbols in memory. Without further ado, let’s directly embark on the journey of analyzing map files, using the demo project in the third lesson’s project file (.ewp) as an example.

1. Analyzing the Map File

In IAR software, under options settings options->Linker->List, select Generate linker map file. After compiling and linking the demo project, you can find the demo.map file at the path D:\myProject\bsp\builds\demo\Release\List. Let’s analyze the content step by step:

1.1 Project File Information

The first part of the map file records information related to the project files, including the software version used, compilation time, project file directory, and output file information.

###############################################################################
#
# IAR ELF Linker V8.11.2.13589/W32 for ARM                12/Jan/2018  17:37:39
# Copyright 2007-2017 IAR Systems AB.
#
#    Output file  =  D:\myProject\bsp\builds\demo\Release\Exe\demo.elf
#    Map file     =  D:\myProject\bsp\builds\demo\Release\List\demo.map
#    Command line =
#        -f C:\Users\Baoge\AppData\Local\Temp\EW5D86.tmp
#        (D:\myProject\bsp\builds\demo\Release\Obj\main.o
#        D:\myProject\bsp\builds\demo\Release\Obj\reset.o
#        D:\myProject\bsp\builds\demo\Release\Obj\startup.o
#        D:\myProject\bsp\builds\demo\Release\Obj\startup_MKL25Z4.o
#        D:\myProject\bsp\builds\demo\Release\Obj\system_MKL25Z4.o
#        D:\myProject\bsp\builds\demo\Release\Obj\task.o -o
#        D:\myProject\bsp\builds\demo\Release\Exe\demo.elf --map
#        D:\myProject\bsp\builds\demo\Release\List\demo.map --config
#        D:\myProject\bsp\builds\demo/../../linker/iar/KL25Z128xxx4_flash.icf
#        --entry Reset_Handler --inline --vfe --text_out locale)
#
###############################################################################

1.2 System Library Usage Information

The second part of the map file records the usage of system libraries in the project. Since task.c calls APIs related to HEAP operations such as malloc() and free(), we naturally use HEAP-related system libraries when compiling and linking the project. Here, it tells us that we are using DLMalloc from the DLib library. DLMalloc has many different HEAP implementation strategies, which we can specify in options->General Options->Library Option 2->Heap selection. Since the demo project selected Automatic, allowing the IDE to choose automatically, it tells us that the final strategy used is the advanced heap.

*******************************************************************************
*** RUNTIME MODEL ATTRIBUTES
***

CppFlavor       = *
__Heap_Handler  = DLMalloc
__SystemLibrary = DLib
__dlib_version  = 6


*******************************************************************************
*** HEAP SELECTION
***

The advanced heap was selected because the application calls memory
allocation functions outside of system library functions, and there
are calls to deallocation functions in the application.

1.3 Section Placement Information of Each Object

Starting from the third part of the map file, we enter a very useful section of information. The first important piece of information is the section placement information. We analyzed the individual relocatable file task.o in the fourth lesson, where each basic section exists but does not have valid addresses allocated. Here, it lists the unified storage and address allocation information for all relocatable files. From this, we can see that the linker consolidates sections based on object files, meaning that objects (variables/functions) in the same section of the same object file are also located close together in memory.

Another interesting piece of information is in the linker file (.icf) from the second lesson, where we have four block placement statements. Here, sections are also divided into four blocks: A0, P1, P2, P3. The IDE has renamed each block, and this renaming information will be mentioned in the executable file (.out/.elf) in the sixth lesson.

*******************************************************************************
*** PLACEMENT SUMMARY
***

define block Vectors with alignment = 256 { ro section .intvec };
"A0":  place at start of [0x00000000-0x0001ffff] { block Vectors };
define block CodeRelocate { section .textrw_init };
define block ApplicationFlash { ro, block CodeRelocate };
"P1":  place in [from 0x00000000 to 0x0001ffff] { block ApplicationFlash };
define block CodeRelocateRam { section .textrw };
define block HEAP with size = 1K, alignment = 8 { };
define block ApplicationRam { rw, block CodeRelocateRam, block HEAP };
"P2":  place in [from 0x10002000 to 0x1000ffff] { block ApplicationRam };
define block CSTACK with size = 8K, alignment = 8 { };
"P3":  place in [from 0x10000000 to 0x10001fff] { block CSTACK };
initialize manually with packing = copy, complex ranges { section .data };
initialize manually with packing = copy, complex ranges { section .textrw };

  Section                Kind        Address    Size  Object
  -------                ----        -------    ----  ------
"A0":                                           0x40
  Vectors                         0x00000000    0x40  <Block>
    .intvec              ro code  0x00000000    0x40  startup_MKL25Z4.o [1]
                                - 0x00000040    0x40

"P1":                                         0x1a3c
  ApplicationFlash                0x00000040  0x1a3c  <Block>
    .noinit              ro code  0x00000040    0x58  reset.o [1]
    .rodata              const    0x00000098     0x4  main.o [1]
    Veneer               ro code  0x0000009c    0x10  - Linker created -
    .text                ro code  0x000000ac    0x20  main.o [1]
    .text                ro code  0x000000cc    0x58  task.o [1]
    .text                ro code  0x00000124  0x16f8  dlmalloc.o [3]
    .text                ro code  0x0000181c    0x50  ABImemset.o [4]
    .text                ro code  0x0000186c    0x5c  ABImemcpy.o [4]
    .text                ro code  0x000018c8     0x8  heaptramp0.o [3]
    .text                ro code  0x000018d0     0xa  abort.o [3]
    .text                ro code  0x000018da     0x2  startup_MKL25Z4.o [1]
    .text                ro code  0x000018dc    0x2c  xgetmemchunk.o [3]
    .text                ro code  0x00001908     0xc  XXexit.o [4]
    .text                ro code  0x00001914    0x90  startup.o [1]
    .text                ro code  0x000019a4     0xc  system_MKL25Z4.o [1]
    .text                ro code  0x000019b0    0x1a  cmain.o [4]
    .text                ro code  0x000019ca     0x2  startup_MKL25Z4.o [1]
    .text                ro code  0x000019cc    0x28  data_init.o [4]
    .text                ro code  0x000019f4     0x8  exit.o [3]
    .text                ro code  0x000019fc     0xa  cexit.o [4]
    .text                ro code  0x00001a06     0x2  startup_MKL25Z4.o [1]
    CodeRelocate                  0x00001a08    0x10  <Block>
      Initializer bytes  const    0x00001a08    0x10  <for CodeRelocateRam-1>
    .data_init                    0x00001a18     0x4  <Block>
      Initializer bytes  const    0x00001a18     0x4  <for .data-1>
    .text                ro code  0x00001a1c     0x2  startup_MKL25Z4.o [1]
    .text                ro code  0x00001a1e     0x2  startup_MKL25Z4.o [1]
    .text                ro code  0x00001a20     0xc  cstartup_M.o [4]
    .text                ro code  0x00001a2c    0x40  zero_init3.o [4]
    .iar.init_table      const    0x00001a6c    0x10  - Linker created -
    .rodata              const    0x00001a7c     0x0  zero_init3.o [4]
                                - 0x00001a7c  0x1a3c

"P3":                                         0x2000
  CSTACK                          0x10000000  0x2000  <Block>
    CSTACK               uninit   0x10000000  0x2000  <Block tail>
                                - 0x10002000  0x2000

"P2":                                          0x620
  ApplicationRam                  0x10002000   0x620  <Block>
    CodeRelocateRam               0x10002000    0x10  <Block>
      CodeRelocateRam-1           0x10002000    0x10  <Init block>
        .textrw          inited   0x10002000    0x10  task.o [1]
    .data                         0x10002010     0x4  <Block>
      .data-1                     0x10002010     0x4  <Init block>
        .data            inited   0x10002010     0x4  task.o [1]
    .bss                          0x10002014   0x208  <Block>
      .bss               zero     0x10002014     0x4  task.o [1]
      .bss               zero     0x10002018    0x10  task.o [1]
      .bss               zero     0x10002028    0x18  dlmalloc.o [3]
      .bss               zero     0x10002040   0x1d8  dlmalloc.o [3]
      .bss               zero     0x10002218     0x4  xgetmemchunk.o [3]
    .noinit              uninit   0x1000221c     0x4  task.o [1]
    HEAP                          0x10002220   0x400  <Block>
      HEAP               uninit   0x10002220   0x400  <Block tail>
                                - 0x10002620   0x620

1.4 System Initialization Table Information

The fourth part of the map file lists the system initialization table, which only includes the bss section (i.e., all global variables defined but not initialized in the code). Since there is some uncertainty in the data stored in SRAM, the system must zero out all data in the bss section at startup to ensure the program runs correctly.

*******************************************************************************
*** INIT TABLE
***

          Address     Size
          -------     ----
Zero (__iar_zero_init3)
    1 destination range, total size 0x208:
          0x10002014  0x208

1.5 Storage Resource Information for Each Object File

The fifth part of the map file lists specific information about the storage resources occupied by each object file. With this information, we can identify which object file (functional module) occupies the most resources. If there is a need for code size optimization, we can choose to optimize the code in the object file that occupies more resources.

*******************************************************************************
*** MODULE SUMMARY
***

    Module             ro code  rw code  ro data  rw data
    ------             -------  -------  -------  -------
D:\myProject\bsp\builds\demo\Release\Obj: [1]
    main.o                  32                 4
    reset.o                 88
    startup.o              144
    startup_MKL25Z4.o       74
    system_MKL25Z4.o        12
    task.o                  88       16       20       28
    -----------------------------------------------------
    Total:                 438       16       24       28

command line: [2]
    -----------------------------------------------------
    Total:

dl6M_tln.a: [3]
    abort.o                 10
    dlmalloc.o           5 880                        496
    exit.o                   8
    heaptramp0.o             8
    xgetmemchunk.o          44                          4
    -----------------------------------------------------
    Total:               5 950                        500

rt6M_tl.a: [4]
    ABImemcpy.o             92
    ABImemset.o             80
    XXexit.o                12
    cexit.o                 10
    cmain.o                 26
    cstartup_M.o            12
    data_init.o             40
    zero_init3.o             64
    -----------------------------------------------------
    Total:                 336

    Linker created          16                16    9 216
---------------------------------------------------------
    Grand Total:         6 740       16       40    9 744

1.6 Specific Allocation Information for Each Object

The sixth part of the map file records the specific allocation of each object file’s objects (variables, functions, etc.) in memory. This information is crucial for debugging. During debugging, in addition to step execution and breakpoints, we often check the real-time situation of memory. Sometimes, due to compiler optimizations, logical issues may not be apparent from the code perspective (for example, we assign the variable s_variable0 a value of 1), but the memory (0x10002014) may not be updated to 1. In this case, there is definitely a problem with the project, and we can locate the specific issue and then consider how to resolve it.

*******************************************************************************
*** ENTRY LIST
***

Entry                      Address   Size  Type      Object
-----                      -------   ----  ----      ------
.bss$$Base              0x10002014          --   Gb  - Linker created -
.bss$$Limit             0x1000221c          --   Gb  - Linker created -
.data$$Base             0x10002010          --   Gb  - Linker created -
.data$$Limit            0x10002014          --   Gb  - Linker created -
.data_init$$Base        0x00001a18          --   Gb  - Linker created -
.data_init$$Limit       0x00001a1c          --   Gb  - Linker created -
.iar.init_table$$Base   0x00001a6c          --   Gb  - Linker created -
.iar.init_table$$Limit  0x00001a7c          --   Gb  - Linker created -
?main                   0x000019b1         Code  Gb  cmain.o [4]
ApplicationFlash$$Base  0x00000040          --   Gb  - Linker created -
ApplicationFlash$$Limit
                        0x00001a7c          --   Gb  - Linker created -
ApplicationRam$$Base    0x10002000          --   Gb  - Linker created -
ApplicationRam$$Limit   0x10002620          --   Gb  - Linker created -
CSTACK$$Base            0x10000000          --   Gb  - Linker created -
CSTACK$$Limit           0x10002000          --   Gb  - Linker created -
CodeRelocate$$Base      0x00001a08          --   Gb  - Linker created -
CodeRelocate$$Limit     0x00001a18          --   Gb  - Linker created -
CodeRelocateRam$$Base   0x10002000          --   Gb  - Linker created -
CodeRelocateRam$$Limit  0x10002010          --   Gb  - Linker created -
HEAP$$Base              0x10002220          --   Gb  - Linker created -
HEAP$$Limit             0x10002620          --   Gb  - Linker created -
Region$$Table$$Base     0x00001a6c          --   Gb  - Linker created -
Region$$Table$$Limit    0x00001a7c          --   Gb  - Linker created -
Reset_Handler           0x00000041         Code  Gb  reset.o [1]
SystemInit              0x000019a5    0xc  Code  Gb  system_MKL25Z4.o [1]
Vectors$$Base           0x00000000          --   Gb  - Linker created -
Vectors$$Limit          0x00000040          --   Gb  - Linker created -
__Vectors_End           0x00000040         Data  Gb  startup_MKL25Z4.o [1]
__aeabi_memcpy          0x0000186d         Code  Gb  ABImemcpy.o [4]
__aeabi_memcpy4         0x00001895         Code  Wk  ABImemcpy.o [4]
__aeabi_memset          0x0000181d         Code  Gb  ABImemset.o [4]
__cmain                 0x000019b1         Code  Gb  cmain.o [4]
__data_GetMemChunk      0x000018dd   0x2c  Code  Gb  xgetmemchunk.o [3]
__data_GetMemChunk::start
                        0x10002218    0x4  Data  Lc  xgetmemchunk.o [3]
__exit                  0x00001909         Code  Gb  XXexit.o [4]
__iar_Memset4_word      0x0000183d         Code  Gb  ABImemset.o [4]
__iar_Memset_word       0x00001829         Code  Gb  ABImemset.o [4]
__iar_data_init3        0x000019cd   0x28  Code  Gb  data_init.o [4]
__iar_dlfree            0x00001271  0x5a4  Code  Gb  dlmalloc.o [3]
__iar_dlmalloc          0x00000f77  0x2f6  Code  Gb  dlmalloc.o [3]
__iar_program_start     0x00001a21         Code  Gb  cstartup_M.o [4]
__iar_systems$$module {Abs}
                        0x00000001         Data  Gb  command line/config [2]
__iar_zero_init3        0x00001a2d   0x40  Code  Gb  zero_init3.o [4]
__vector_table          0x00000000         Data  Gb  startup_MKL25Z4.o [1]
_call_main              0x000019bd         Code  Gb  cmain.o [4]
_exit                   0x000019fd         Code  Gb  cexit.o [4]
_gm_                    0x10002040  0x1d8  Data  Lc  dlmalloc.o [3]
_main                   0x000019c7         Code  Gb  cmain.o [4]
abort                   0x000018d1    0xa  Code  Gb  abort.o [3]
add_segment             0x00000539  0x208  Code  Lc  dlmalloc.o [3]
exit                    0x000019f5    0x8  Code  Gb  exit.o [3]
free                    0x000018c9    0x8  Code  Gb  heaptramp0.o [3]
heap_task               0x000000db   0x3c  Code  Gb  task.o [1]
init_data_bss           0x00001915   0x54  Code  Gb  startup.o [1]
init_interrupts         0x00001969   0x12  Code  Gb  startup.o [1]
init_mparams            0x00000145   0x2a  Code  Lc  dlmalloc.o [3]
init_top                0x0000016f   0x38  Code  Lc  dlmalloc.o [3]
main                    0x000000ad   0x20  Code  Gb  main.o [1]
mparams                 0x10002028   0x18  Data  Lc  dlmalloc.o [3]
n_variable1             0x1000221c    0x4  Data  Gb  task.o [1]
normal_task             0x000000cd    0xe  Code  Gb  task.o [1]
prepend_alloc           0x000001b5  0x384  Code  Lc  dlmalloc.o [3]
ram_task                0x10002001   0x10  Code  Gb  task.o [1]
s_array                 0x10002018   0x10  Data  Lc  task.o [1]
s_constant              0x00000098    0x4  Data  Gb  main.o [1]
s_variable0             0x10002014    0x4  Data  Lc  task.o [1]
s_variable2             0x10002010    0x4  Data  Lc  task.o [1]
segment_holding         0x00000125   0x20  Code  Lc  dlmalloc.o [3]
sys_alloc               0x00000749  0x16c  Code  Lc  dlmalloc.o [3]
sys_trim                0x000008b5   0x6a  Code  Lc  dlmalloc.o [3]
tmalloc_large           0x00000931  0x3fe  Code  Lc  dlmalloc.o [3]
tmalloc_small           0x00000d35  0x242  Code  Lc  dlmalloc.o [3]

[1] = D:\myProject\bsp\builds\demo\Release\Obj
[2] = command line
[3] = dl6M_tln.a
[4] = rt6M_tl.a

1.7 Image Storage Resource Usage Information

The seventh part of the map file provides a summary of the storage resources used by the entire project. Here, we can see that the project occupies 6780 bytes of ROM resources and 9760 bytes of RAM resources, so when selecting a chip, we must ensure that the ROM (FLASH) and RAM are greater than what the project requires.

  6 740 bytes of readonly  code memory
     16 bytes of readwrite code memory
     40 bytes of readonly  data memory
  9 744 bytes of readwrite data memory

2. Relationship Between Code Objects and Sections

In the second lesson, I discussed the concept of sections in the linker file (.icf) and listed the meanings of the default sections in the IAR system. After analyzing the map file above, let’s directly use the source files main.c and task.c from the demo project to analyze the sections:

Section Description Region Object
.bss Uninitialized global/static variables RAM(0x10002014 – 0x1000221b) s_variable0 (0x10002014 – 0x10002017)
s_array[16] (0x10002018 – 0x10002027)
CSTACK Stack: function call return addresses, function parameter passing, local variables RAM(0x10000000 – 0x10001fff) normal_task/ram_task/heap_task addresses, l_variable, *heap
.data Initialized global/static variables RAM(0x10002010 – 0x10002013) s_variable2
.data_init Initial values of initialized global/static variables ROM(0x00001a18 – 0x00001a1b) 0x5a(s_variable2)
HEAP Heap: dynamic memory allocation RAM(0x10002220 – 0x1000261f) *heap = (uint8_t *)malloc(16 * sizeof(uint8_t))
.intvec Interrupt vector table ROM(0x00000000 – 0x0000003f) ISR table specified in startup_MKL25Z4.s by DCD
.noinit Indicates uninitialized global/static variables RAM(0x1000221c – 0x1000221f) n_variable1
.rodata Constants ROM(0x00000098 – 0x0000009b) s_constant
.text Function code executed in ROM ROM(0x000000ac – 0x00001a07) main function body (0x000000ad – 0x000000cc)
normal_task function body (0x000000cd – 0x000000da)
heap_task function body (0x000000db – 0x00000116)
.textrw Function code executed in RAM RAM(0x10002000 – 0x1000200f) ram_task function body
.textrw_init Function code data executed in RAM ROM(0x00001a08 – 0x00001a17) ram_task function body

Thus, I have introduced the map file in embedded development. Where’s the applause~~~

Leave a Comment