打印
[通用8051核FLASH系列]

Map文件解析

[复制链接]
155|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
rosemoore|  楼主 | 2024-6-26 08:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DA, TI, mb, ST, ma, ap
一、什么是Map文件

        简单来说,Map文件是编译器编译工程后生成的一个文件,这个文件反映了各个源文件生成的模块间的交叉引用、移除的未使用模块、符合映射表、内存映射以及各个模块的大小和汇总数据等。

       所以说,当你在遇到或怀疑存在内存越界或溢出的情况时,首先想到的应该就是分析Map文件,确认嫌疑分子、构建RAM的分布图,还原问题发生的过程,才能从根本上解决问题。

       那,我们就一起来看下怎么看Map文件这个问题吧~

二、如何生成Map文件

        根据设置的不同,生成的Map文件包含的内容也不同。如图1所示,在“Options for Target ‘XXX’”窗口的Listing页面,通过勾选不同的项目可以定制Map文件中的记录的内容。

图1

        PS:点击快捷工具栏的魔法棒按钮 或 菜单Project->“Options for Target ‘XXX’...”可以打开“Options for Target ‘XXX’”窗口。

        设置完,代码编译成功后,在指定目录就可以找到生成的Map文件。

三、Map文件解析

        Map文件已经生成了,那么接下来我们一起看下Map是何方神圣。既然要看,就需要先打开Map文件,那么Map文件怎么打开呢?

        很简单,打开Map文件的方式有多种,在KEIL的左侧的Project窗口中目标工程上双击即可打开;或者,直接找到Map文件,用文本编辑器等方式都可以打开查看这里就不再赘述。      

       按照最全的配置,Map文件包括以下几个部分:

1. Section Cross References

      主要是指各源文件生成的模块间的相互引用关系。

      比如,下面这句表示:

      spi.c文件编译生成的模块spi.o中调用了stm32f4xx_rcc.c文件编译生成的模块stm32f4xx_rcc.o z中的函数RCC_AHB1PeriphClockCmd。 剩下的也差不多都是这个意思。

Section Cross References……spi.o(.text) refers to stm32f4xx_rcc.o(.text) for RCC_AHB1PeriphClockCmd……2. Removing Unused input sections from the image

      将未使用的函数之类的删除,以减少image映像的大小。

Removing Unused input sections from the image.……Removing data_quk.o(.rev16_text), (4 bytes).……

      这个从我个人目前接触的内容看,没用到过,如果XDJM在调试程序的过程中有用到这些信息的场景也希望不吝赐教,我也开阔下视野,多谢~

3. Image Symbol Table

     映像中涉及的符号表,包括局部符号(Local Symbols)和全局符号(Global Symbols)。

Image Symbol Table    // 局部符号    Local Symbols    // 符号名                                // 地址    // 类型        // 大小    Symbol Name                              Value     Ov Type        Size  Object(Section)    ../clib/angel/boardlib.s                 0x00000000   Number         0  boardinit1.o ABSOLUTE    ..\TASKS\alm_task.c                     0x00000000   Number         0  alm_task.o ABSOLUTE    ......    HEAP                                     0x20006248   Section      512  startup_stm32f40_41xxx.o(HEAP)    Heap_Mem                                 0x20006248   Data         512  startup_stm32f40_41xxx.o(HEAP)    STACK                                    0x20006448   Section     2048  startup_stm32f40_41xxx.o(STACK)    Stack_Mem                                0x20006448   Data        2048  startup_stm32f40_41xxx.o(STACK)    __initial_sp                             0x20006c48   Data           0  startup_stm32f40_41xxx.o(STACK)    // 全局符号    Global Symbols    // 符号名                                // 地址    // 类型        // 大小    Symbol Name                              Value     Ov Type        Size  Object(Section)    ......    limit_check                              0x0800d27d   Thumb Code   566  alm_task.o(.text)    aaaaa_err                                0x20000089   Data           1  global.o(.data)    play_cnt                                 0x2000008a   Data           1  global.o(.data)    lock_cnt                                 0x2000008b   Data           1  global.o(.data)    ......    Region$$Table$$Base                      0x0801bf24   Number         0  anon$$obj.o(Region$$Table)    Region$$Table$$Limit                     0x0801bf44   Number         0  anon$$obj.o(Region$$Table)    ......

     注意,这里的符号包括函数名,变量名。局部的static变量和全局变量在这里都可以找到,如果疑似存在内存越界的变量属于这两种类型,那么可以从这里找到他们的地址,看看他上下左右的小伙伴儿都是谁,就能确定嫌疑分子了。

     另外,类型包括Number、Section、Thumb Code、Data。其中,Number是指它并不占据程序空间,而只是具有一定数值的符号,类似于程序中用宏定义define和EQU。

4. Memory Map of the image

      映像的内存分布,顾名思义,这部分内容主要记录了映像的加载域和运行域的起始地址、大小和最大Size以及各个段的起始地址。

      在说介绍之前,我们先了解下这几个段的意义,方便理解:

段名说明
.constdata只读常量数据段,属于RO-data。
.text

代码段。

用来存放程序执行代码的内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(当然也有些架构允许代码段为可写,即允许修改程序)。也有可能包含一些只读的常数变量,例如字符串常量等。

.data

数据段。

data 段用于存储已经赋初值(非零)的全局变量,且变量占有实际的内存空间。本段的内容由程序初始化,因此会占用exe文件空间。

.bss

数据段,Block Started by Symbol。

bss段用于存储未赋初值的全局变量和静态局部变量,这些变量在程序运行前会被初始化为0或NULL。

另外,初始化为零的全局变量和静态局部变量也会存储在bss中的数据不分配实际的空间,只体现为一个占位符,只记录数据所需空间的大小,因此不会占用exe文件空间。

bss段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在data段后面。

heap

堆。

用于存放运行中被动态分配的内存段,可动态扩张或缩减。

例如,malloc分配的内存就在堆上。

stack

栈。

用于存放程序临时创建的局部变量,即:函数括弧“{}”中定义的临时变量。注意,不包括用static声明的变量,static声明的变量存储在data段中。当函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。



使用特权

评论回复
沙发
LEDyyds| | 2024-6-27 16:14 | 只看该作者
我只会用MAP看代码的内存占用

使用特权

评论回复
板凳
黑心单片机| | 2024-6-27 16:52 | 只看该作者
我也是只会看代码占用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

1197

帖子

2

粉丝