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首頁、微信公衆号 平台上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。
衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。
專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。