map文件简介
内容
配置
概念
map文件内容详解
Section Cross References—模块、段(入口)交叉引用
Removing Unused input sections from the image—移除未调用模块
Image Symbol Table—映射符号表
Memory Map of the image—内存(映射)分布
Image component sizes—存储组成大小
map文件简介
内容
首先我们需要了解map文件是什么,map文件是通过编译器编译之后,集程序、数据及IO空间的一种映射文件;一般出现内存越界或溢出,又或者是代码优化的情况,首先想到的就是分析map文件,通过map文件可以知道函数大小,入口地址等一些重要信息,总共分为五大类
Section Cross References:模块、段(入口)交叉引用
Removing Unused input sections from the image:移除未调用模块
Image Symbol Table:映射符号表
Memory Map of the image:内存(映射)分布
Image component sizes:存储组成大小
配置
其次就是配置,由于笔者这里大多数是使用keil,所有就展示的keil的配置(虽然大概率就是已经配置好的);路径是先点击魔法棒,然后Listing选项卡中,最后在Linker Listing:map.map勾选即可
Memory Map:内存映射
Callgraph:图像映射
Symbols:符号
Cross Reference:交叉引用
Size Info:大小信息
Totals Info:统计信息
Unused Section Info:未调用模块信息
Veneers Info:装饰信息
最后的map文件可以在~\xxx\MDK-ARM\xxx中找到
概念
最后是关于map文件基本概念
段(section):描述映像文件的代码和数据块
RO:Read-Only的缩写,包括RO-data(只读数据)和RO-code(代码)
RW:Read-Write的缩写,主要是RW-data,RW-data由程序初始化初始值
ZI:Zero-initialized的缩写,主要是ZI-data,由编译器初始化为0
.text:与RO-code同义
.constdata:与RO-data同义
.bss:与ZI-data同义
.data:与RW-data同义
map文件内容详解
Section Cross References—模块、段(入口)交叉引用
当我们打开map文件的时候,第一大块就是Section Cross References,主要内容是是各个源文件生成的模块、段(定义的入口)之间相互引用的关系
例如: main.o(i.SystemClock_Config) refers to stm32f1xx_hal_rcc.o(i.HAL_RCC_OscConfig) for HAL_RCC_OscConfig,意思是main模块中SystemClock_Config引用了 stm32f1xx_hal_rcc模块中HAL_RCC_OscConfig函数
需要注意的是,在map文件中i指的是独立函数,是一种编译器优化编译的一种方式,可以精确地控制每个函数的位置,或者删除没用的函数,通俗来讲也就是可以在map文件看到更多信息以及更精准的定位
Removing Unused input sections from the image—移除未调用模块
在代码中没有被调用的模块会在map文件生成列表,最后会在这部分显现出来
例如:Removing stm32f1xx_hal_rcc_ex.o(i.HAL_RCCEx_GetPeriphCLKConfig), (44 bytes).,意思是删除了stm32f1xx_hal_rcc_ex模块的HAL_RCCEx_GetPeriphCLKConfig函数,大小是44字节
除此以外,最后会有一个汇总,删除了180个模块,共计7710字节
Image Symbol Table—映射符号表
这部分分为两块,一块是Local Symbols,主要静态函数,变量以及常量;另外一块是Global Symbols,主要是外部函数和全局变量
Symbol Name:符号的名称以及路径
Value:地址
Type:符号的类型,常见的大概是四种
Number
Section
Thumb Code
Data
Size:大小,单位是字节
Object(Section):表示符号所在的目标文件及其对应的段
我们从这部分可以看出一些函数或变量的地址
Memory Map of the image—内存(映射)分布
在执行映像之前,必须将已初始化的RW数据从ROM中复制到RAM中的执行地址并创建ZI Section(初始化为0的变量区)
这里引用rtthread文档中的内存分布图
STM32 在上电启动之后默认从 Flash 启动,启动之后会将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中,但不会搬运 RO 段,即 CPU 的执行代码从 Flash 中读取,另外根据编译器给出的 ZI 地址和大小分配出 ZI 段,并将这块 RAM 区域清零
Exec Addr:执行地址,即当程序运行时,该段在内存中将被加载到的地址
Load Addr:加载地址,即当程序从存储器(如 Flash)加载到内存时,该段最初加载到的地址,由上图可以知道,启动之后RO是不会变的,但RW是会移动到RAM里面,所以在RO中Exec Addr和Load Addr是一致的,但RW会不一样且Load Addr比Exec Addr大
Size:段的大小,以字节为单位
Type:段的类型
Code:表示可执行代码
Data:表示数据段,包括已初始化的全局变量等
RO Data:只读数据,如常量、字符串字面值等
Attr:段的属性,在RO中Attr都是RO,在RW中Attr都是RW
Idx:索引号,表示该段在符号表中的索引位置,通常用于区分符号表中的不同段
E Section Name:段的名称
Object:目标文件
Image component sizes—存储组成大小
Code (inc. data):代码部分(即可执行指令)及其包含的任何初始化数据的总大小,包括.text段和任何被标记为只读的初始化数据(如.rodata段)
RO Data:只读数据的总大小。这部分通常包括常量字符串、枚举、常量数组等,存储在.rodata段中
RW Data:可读可写数据的总大小。这部分包含已初始化的全局变量和静态变量,存储在.data段中
ZI Data:零初始化数据的总大小。这部分通常包含未初始化的全局变量和静态变量,存储在.bss段中
Debug:表示与调试相关的数据占用空间,包括调试符号、调试信息
Object Name:目标文件的名称
RAM=RW=1.62KB
ROM=ROM = 2.44KB