天天看點

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

map檔案就是所有relocatable檔案經過連結器統一連結後生成的記錄連結資訊的檔案,map檔案裡可以查到所有symbol在存儲器中具體配置設定位址

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式開發裡的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工程為例。

  在IAR軟體選項設定options->Linker->List裡選中Generate linker map file,編譯連結demo工程可在D:\myProject\bsp\builds\demo\Release\List路徑下得到demo.map檔案。讓我們從頭到尾逐一分析裡面内容:

  map檔案裡第一部分資訊記錄的是工程檔案相關資訊,包括工程使用的軟體版本,工程編譯時間,工程檔案目錄,工程檔案生成檔案資訊。

  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。

  從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)裡被提到。

  map檔案第四部分列出了經由系統初始化的表,這裡隻有bss段(即代碼中所有僅定義但沒有賦初值的全局變量),由于SRAM中資料存有一定不确定性,是以系統必須要在啟動時将bss段内所有資料全部清零,以保證程式能正常運作。

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

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

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

  痞子衡在第二節課連結檔案(.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)

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

文章會同時釋出到我的 部落格園首頁、CSDN首頁、微信公衆号 平台上。

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

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

  最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。

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

  衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。

  專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。

ARM