找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5939

积分

0

好友

752

主题
发表于 4 天前 | 查看: 5| 回复: 0

近期有网友问:如何分析 Keil 中的 map 文件?这个文件主要有哪些内容,都代表什么意思?

什么是 map 文件?

简单地说:map 文件是经过 编译器 编译之后,集程序、数据及 IO 空间的一种映射文件。很多经验丰富的工程师在遇到内存越界或溢出时,首先想到的就是分析 map 文件。通过 map 文件可以知道函数大小、入口地址等重要信息。

在 Keil 中最常见的是编译之后,编译窗口会显示类似下面一段关于程序和数据大小的信息:

Program Size: Code=1112 RO-data=320 RW-data=0 ZI-data=1632

这一段提示信息汇总了程序和数据的信息,而这些信息由单个模块汇总而来,在 map 文件里有详细列表。

关于 Keil 中的 map 文件

Keil 软件中的 map 文件,对分析项目中的 bug 很重要,很多内存相关的 bug 都能通过 map 文件进行分析。

如何打开 map 文件

最直接也最简单的办法:双击工程目标,出现 map 文件(注意双击的是工程目标,不是工程或文件组)。如下图:

STM32F103ZE Keil 工程构建与 map 文件生成过程

当然,也可以找到 map 文件的位置(Listings 文件夹),用编辑器打开。

map 文件输出内容配置

map 文件输出信息的配置位于:Project -> Options for Target -> Listing,如下图:

Keil Options for Target Listing 页 Linker Listing 配置

主要包含配置:

  • Memory Map:内存映射
  • Callgraph:调用图
  • Symbols:符号
  • Cross Reference:交叉引用
  • Size Info:大小信息
  • Totals Info:统计信息
  • Unused Section Info:未调用模块信息
  • Veneers Info:Veneer 信息

可以根据自己的情况,需要输出什么信息就勾选对应的选项。

提示:

  • 默认情况下输出所有信息;
  • 这些配置是组合关系。

map 文件内容分类

从上面的输出配置可以看出 map 文件大概包含哪些信息。map 文件将其分为如下五大类:

  1. Section Cross References:模块、段(入口)交叉引用
  2. Removing Unused input sections from the image:移除未调用模块
  3. Image Symbol Table:映射符号表
  4. Memory Map of the image:内存(映射)分布
  5. Image component sizes:存储组成大小

下面针对 Keil MDK、ARM Compiler 5 组件生成的 map 文件五大类内容展开说明。

各个模块说明

1、Section Cross References:模块、段(入口)交叉引用

配置中需勾选 Cross Reference

Keil map 文件 Section Cross References 交叉引用列表

Section Cross References 指各个源文件生成的模块、段(定义的入口)之间相互引用的关系。

比如:

main.o(i.System_Initializes) refers to bsp.o(i.BSP_Initializes) for BSP_Initializes

意思是:main 模块(main.o)中的 System_Initializes 函数(i.System_Initializes)引用(或者说调用)了 bsp 模块(bsp.o)中的 BSP_Initializes 函数。

提示:

  • main.omain.c 源文件生成的目标文件模块;
  • i.System_InitializesSystem_Initializes 函数的入口。

2、Removing Unused input sections from the image:移除未调用模块

配置中需勾选 Unused Sections Info

Keil map 文件中被移除的未使用段列表

这一类很好理解:代码中未被调用的模块(或者说函数)会在 map 文件中生成一个列表。

比如:

Removing stm32f10x_gpio.o(i.GPIO_AFIODeInit), (20 bytes).

意思是:stm32f10x_gpio.c 文件中的 GPIO_AFIODeInit 模块(函数)未被调用,其代码大小为 20 字节。

最后还有一个统计信息:

52 unused section(s) (total 2356 bytes) removed from the image.

表示总共有 52 段没有被调用,未调用部分大小为 2356 字节。

3、Image Symbol Table:映射符号表

配置中需勾选 Symbols

Keil map 文件 Image Symbol Table 符号表

Image Symbol Table 即映射符号表,也就是各个段所存储对应地址的表(上图中删除了中间部分内容)。

Symbol 分为两大类:

  1. Local Symbols:局部符号
  2. Global Symbols:全局符号

Symbol 内容要点:

  1. Symbol Name:符号名称。名称命名及分类请参考官方文档。
  2. Value:存储对应的地址。大家会看到 0x0800xxxx0x2000xxxx 这样的地址。其中 0x0800xxxx 指存储在 FLASH 中的代码、变量等;0x2000xxxx 指存储在 RAM 中的变量 Data 等。
  3. Ov Type:符号对应的类型。符号类型大概有几种:Number、Section、Thumb Code、Data 等。细心的朋友会发现:全局、静态变量等位于 0x2000xxxx 的 RAM 中。
  4. Size:存储大小,即当前行 Symbol 占用的大小。
  5. Object(Section):段目标,这里一般指所在模块(源文件)。

4、Memory Map of the image:内存(映射)分布

配置中需勾选 Memory Map

Keil map 文件 Memory Map 内存映射分布

Memory Map of the image 即内存(映射)分布,内容相对较多,也是比较重要的一项。

主要介绍:

Image Entry point : 0x08000131:指映射入口地址。

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00000598, Max: 0x00080000, ABSOLUTE):指加载区域位于 LR_IROM1,起始地址 0x08000000,大小 0x00000598,该区域最大为 0x00080000

执行区域有两个:

  • Execution Region ER_IROM1
  • Execution Region RW_IRAM1

这个区域其实对应目标配置中的区域,如下图所示:

Keil Target 配置 ROM/RAM 地址范围

内容要点:

  1. Base Addr:存储地址。0x0800xxxx 为 FLASH 地址,0x2000xxxx 为 RAM 地址。
  2. Size:存储大小。
  3. Type:类型。Data 表示数据类型,Code 表示代码类型,Zero 表示未初始化变量类型,PAD 则是“补充类型”。ARM 处理器是 32 位的,如果定义一个 8 位或 16 位变量就会剩余一部分,这里就是指“补充”的那部分,此时后面的其他几个选项都没有对应的值。
  4. Attr:属性。RO 表示存储于 ROM 中的段,RW 表示存储于 RAM 中的段。
  5. Section Name:段名。也可以说是入口分类名,与第一节“Section Cross References”提到的模块、段一样。大概包含:RESET.ARM.texti.data.bssHEAPSTACK 等。
  6. Object:目标。

5、Image component sizes:存储组成大小

配置中需勾选 Size Info

Keil map 文件 Image component sizes 存储组成大小

Image component sizes 即存储组成大小,主要是对模块进行汇总存储大小信息。

这一部分内容很好理解。编译工程后,编译窗口一般会看到类似如下信息:

Program Size: Code=1112 RO-data=320 RW-data=0 ZI-data=1632

其中:

  • Code:指代码的大小;
  • RO-data:指除了内联数据(inline data)之外的常量数据;
  • RW-data:指可读写(RW)、已初始化的变量数据;
  • ZI-data:指未初始化(ZI)的变量数据。

提醒:

  • Code、RO-data 位于 FLASH 中;
  • RW-data、ZI-data 位于 RAM 中;
  • RW-data 已初始化的数据会存储在 Flash 中,上电后从 FLASH 搬移至 RAM。

关系如下:

RO Size = Code + RO Data
RW Size = RW Data + ZI Data
ROM Size = Code + RO Data + RW Data

上面 map 信息是比较全面的汇总。如果不想看模块明细,只想看汇总统计,可以在配置中只勾选 Totals Info,对比信息如下:

Keil map 文件 Totals Info 汇总统计

以上是传统分析 map 文件的方法。对于有时间和精力的同学,可以花时间掌握一些主要内容,方便今后自己能看懂 map 文件。

当然,现在 AI 时代,也可以借助 AI 工具分析 map 文件,请参考:看懂.map文件很难?现在AI一键帮你分析了!




上一篇:Qwen3.8-Max-0902发布:Coding与Cowork强化,Code Arena登顶
下一篇:OpenProcessing 创意编程:三角函数生成艺术四大神级流派与实战复刻
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-9-10 16:02 , Processed in 0.847763 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表