痞子衡嵌入式:ARM Cortex-M文件那些事(5)- 映射文件(.map)



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式開發里的map文件

  第四節課里,痞子衡給大家介紹了第一種output文件-relocatable文件,本文繼續給大家講project生成的第二種output文件-map文件,map文件記錄了很多重要的信息,這對於后續調試有很大幫助。

  文件關系:鏈接文件(.icf) + 工程文件(.ewp) + 可重定向文件(.o/.a) -> 映射文件(.map)

  痞子衡在第四節課可重定向文件(.o/.a)里分析object文件里的symbol list時講到由於object文件並沒有經過鏈接,所以所有symbol地址信息是無效的(待分配的),而map文件就是所有relocatable文件經過鏈接器統一鏈接后生成的記錄鏈接信息的文件,map文件里可以查到所有symbol在存儲器中具體分配地址。話不多說,讓我們直接開啟map文件分析之旅,以第三節課工程文件(.ewp)里demo工程為例。

一、解析map文件

  在IAR軟件選項設置options->Linker->List里選中Generate linker map file,編譯鏈接demo工程可在D:\myProject\bsp\builds\demo\Release\List路徑下得到demo.map文件。讓我們從頭到尾逐一分析里面內容:

1.1 工程文件信息

  map文件里第一部分信息記錄的是工程文件相關信息,包括工程使用的軟件版本,工程編譯時間,工程文件目錄,工程文件生成文件信息。

###############################################################################
#
# 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 系統庫使用信息

  map文件里第二部分信息記錄的是工程系統庫使用情況,由於task.c里調用了malloc()、free()等HEAP相關操作的API,所以自然我們在編譯鏈接工程時會使用到HEAP相關系統庫,這里告訴我們用的是DLib里的DLMalloc,而DLMalloc有很多種不同的HEAP實現策略,我們可在options->General Options->Library Option 2->Heap selection指定具體策略,由於demo工程選的是Automatic,也就是讓IDE自動選擇,這里告訴我們最終用的策略是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 各object中Section放置信息

  從map文件第三部分開始,就進入非常有用的信息環節了。第一個重要信息就是section放置信息。我們在第四節課可重定向文件(.o/.a)里分析過單個relocatable文件task.o,task.o里各個基本section都有,但是都並沒有分配有效地址,而這里列出了所有relocatable文件統一存儲和地址分配信息,從這里我們可以看到,鏈接器在整合各section的時候,都是以object文件為單位的,這意味着同一個object文件里的同一個section里的對象(變量/函數)在存儲空間里的位置也是靠在一起的。
  另外一個有意思的信息是在第二節課鏈接文件(.icf)里,我們一共有四句block放置語句,在這里section也被分成了四個block:A0,P1,P2,P3。IDE給每個block重命名了,這些重命名的信息將會在第六節課可執行文件(.out/.elf)里被提到。

*******************************************************************************
*** 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 系統初始化表信息

  map文件第四部分列出了經由系統初始化的表,這里只有bss段(即代碼中所有僅定義但沒有賦初值的全局變量),由於SRAM中數據存有一定不確定性,所以系統必須要在啟動時將bss段內所有數據全部清零,以保證程序能正常運行。

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

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

1.5 各object文件所占存儲資源信息

  map文件第五部分會列出各object文件所占存儲資源具體信息,有了這部分信息,我們便知道工程具體是哪個object文件(功能模塊)占用資源最多,如果有代碼size方面優化的需求,可以選擇占用資源較多的object文件里的代碼進行針對性地優化。

*******************************************************************************
*** 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 各object具體分配信息

  map文件第六部分記錄的是各object文件里的具體對象(變量,函數等)在存儲空間里的具體分配,這里的信息對於調試來說非常重要。平時調試時我們除了單步執行、打斷點之外,還會配合看內存的實時情況,有時候因為編譯器優化的原因,從代碼角度看不出邏輯問題(比如我們給變量s_variable0賦值為1),但是內存里(0x10002014)卻並沒有被更新為1,這時候工程肯定是有問題的,定位到了具體問題,然后我們再考慮解決問題的方法。

*******************************************************************************
*** 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占用存儲資源信息

  map文件第七部分會給出整個工程占用存儲資源情況的總結,這里我們可以看到工程占用ROM資源6780bytes,RAM資源9760bytes,所以我們在選擇芯片時必須保證ROM(FLASH),RAM要大於工程所需。

  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

二、代碼對象與section的關系

  痞子衡在第二節課鏈接文件(.icf)里的講過section的概念,並且列出了IAR系統里默認的各section的含義。經過上面對map文件的分析,現在讓我們直接用demo工程里的main.c和task.c源文件來實例分析section:

Section Description Region Object
.bss 未賦初值的全局/靜態變量 RAM(0x10002014 - 0x1000221b) s_variable0 (0x10002014 - 0x10002017)
s_array[16] (0x10002018 - 0x10002027)
CSTACK 棧:函數調用返回地址、函數傳遞實參、局部變量 RAM(0x10000000 - 0x10001fff) normal_task/ram_task/heap_task地址、l_variable、*heap
.data 賦初值的全局/靜態變量 RAM(0x10002010 - 0x10002013) s_variable2
.data_init 賦初值的全局/靜態變量的初值 ROM(0x00001a18 - 0x00001a1b) 0x5a(s_variable2)
HEAP 堆:動態內存分配 RAM(0x10002220 - 0x1000261f) *heap = (uint8_t *)malloc(16 * sizeof(uint8_t))
.intvec 中斷向量表 ROM(0x00000000 - 0x0000003f) startup_MKL25Z4.s里DCD指定的ISR表
.noinit 指明不初始化的全局/靜態變量 RAM(0x1000221c - 0x1000221f) n_variable1
.rodata 常量 ROM(0x00000098 - 0x0000009b) s_constant
.text ROM中執行的函數代碼 ROM(0x000000ac - 0x00001a07) main函數體 (0x000000ad - 0x000000cc)
normal_task函數體 (0x000000cd - 0x000000da)
heap_task函數體 (0x000000db - 0x00000116)
.textrw RAM中執行的函數代碼 RAM(0x10002000 - 0x1000200f) ram_task函數體
.textrw_init RAM中執行的函數代碼的數據 ROM(0x00001a08 - 0x00001a17) ram_task函數體

  至此,嵌入式開發里的map文件痞子衡便介紹完畢了,掌聲在哪里~~~

歡迎訂閱

文章會同時發布到我的 博客園主頁CSDN主頁微信公眾號 平台上。

微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM