MAP文件分析

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同义

 

Total RO Size (Code + RO Data) 4540 ( 4.43kB)

Total RW Size (RW Data + ZI Data) 1928 ( 1.88kB)

Total ROM Size (Code + RO Data + RW Data) 4572 ( 4.46kB)

Section Cross References(模块、段的交叉引用关系)

主要是各个源文件生成的模块之间相互引用的关系。“refer to”是引用的意思,比如:

 

main.o(i.main) refers to stm32f4xx_hal.o(i.HAL_Init) for HAL_Init

表示main.c里的main()函数引用了stm32f4xx_hal.c的HAL_Init()函数。

Removing Unused input sections from the image(移除未使用的段)

将没有用到的函数从可执行映像中删除,减小程序体积。最后一栏显示总共移除了多少空间。

216 unused section(s) (total 11434 bytes) removed from the image.

Image Symbol Table(映射符号表,列出了各个段所存储的对应地址)

分为Local Symbols局部 和 Global Symbols全局。

Local Symbols记录了用static声明的全局变量地址和大小,C文件中函数的地址和用static声明的函数代码大小,汇编文件中的标号地址(作用域限本文件)

例如:

static int a会位于Local Symbols

Global Symbols记录了全局变量的地址和大小,C文件中函数的地址及其代码大小,汇编文件中的标号地址(作用域全工程)

int b 会位于Global Symbols。

a会位于0x20000000

b会位于0x20000004

 

Image Symbol Table

Local Symbols

Symbol Name Value Ov Type Size Object(Section)

1、Symbol Name:符号名称

2、Value:存储对应的地址;

大家会发现有0x0800xxxx、0x2000xxxx这样的地址。

0x0800xxxx指存储在FLASH里面的代码、变量等。

0x2000xxxx指存储在内存RAM中的变量Data等。

3、Ov Type:符号对应的类型

符号类型大概有几种:Number、Section、Thumb Code、Data等;

细心的朋友会发现:全局、静态变量等位于0x2000xxxx的内存RAM中。

4、Size:存储大小

这个容易理解,我们怀疑内存溢出,可以查看代码存储大小来分析。

5、Object(Section):当前符号所在段名

这里一般指所在模块(所在源文件)。

Memory Map of the image(映像的内存分布)

映像文件可以分为加载域(Load Region)和运行域(Execution Region):加载域反映了ARM可执行映像文件的各个段存放在存储器中的位置关系。下面是部分截图,另外映像中的入口点就是程序开始执行的位置。

 

Memory Map of the image

Image Entry point : 0x080001ad

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x000011f0, Max: 0x00100000, ABSOLUTE)

Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x000011c8, Max: 0x00100000, ABSOLUTE)

Exec Addr Load Addr Size Type Attr Idx E Section Name Object

0x08000000 0x08000000 0x000001ac Data RO 473 RESET startup_stm32f429xx.o

1、Exec Addr:运行域地址

2、Load Addr:加载域地址

3、Size:存储大小

4、Type:类型

Data:数据类型

Code:代码类型

Zero:未初始化变量类型

PAD:这个类型在map文件中放在这个位置,其实它不能算这里的类型。要翻译的话,只能说的“补充类型”。

ARM处理器是32位的,如果定义一个8位或者16位变量就会剩余一部分,这里就是指的“补充”的那部分,会发现后面的其他几个选项都没有对应的值。

运行域反映了ARM可执行映像文件各个段真正执行时在存储器中的位置关系:

 

Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x080011c8, Size: 0x00000790, Max: 0x00030000, ABSOLUTE)

Exec Addr Load Addr Size Type Attr Idx E Section Name Object

0x20000000 0x080011c8 0x00000008 Data RW 5 .data main.o

0x20000008 0x080011d0 0x00000014 Data RW 340 .data system_stm32f4xx.o

0x2000001c 0x080011e4 0x00000004 Data RW 504 .data stm32f4xx_hal.o

0x20000020 0x080011e8 0x00000004 Data RW 1743 .data delay.o

0x20000024 0x080011ec 0x00000004 Data RW 1813 .data usart.o

0x20000028 - 0x00000108 Zero RW 1812 .bss usart.o

加载域就是程序在Flash中的实际存储,而运行域是芯片上电后的运行状态,因为MCU没上电时RAM中没有数据,所以此时所有的东西(包括代码、变量、初始值等)都是存放在flash中的,当上电后又要把变量等复制到RAM中才能正常运行。

uploading.4e448015.gif

转存失败重新上传取消

通过上面的框图可以看出,RW区也是要存储到ROM/Flash里面的。在执行映像之前,必须将已初始化的RW数据从ROM中复制到RAM中的执行地址并创建ZI Section(初始值为0的变量区),这样才算完成了MCU运行的准备。

Image component sizes(映像组成大小

 

Image component sizes

Code (inc. data) RO Data RW Data ZI Data Debug Object Name

98 8 0 4 0 2535 delay.o

76 8 0 0 0 1159 led.o

104 8 0 8 0 376630 main.o

64 26 428 0 1536 932 startup_stm32f429xx.o

122 16 0 4 0 5172 stm32f4xx_hal.o

196 14 0 0 0 31120 stm32f4xx_hal_cortex.o

486 54 0 0 0 3092 stm32f4xx_hal_gpio.o

136 14 0 0 0 1596 stm32f4xx_hal_pwr_ex.o

1484 56 16 0 0 6073 stm32f4xx_hal_rcc.o

626 0 0 0 0 7127 stm32f4xx_hal_uart.o

20 0 0 0 0 5318 stm32f4xx_it.o

132 10 0 0 0 1435 sys.o

84 18 0 20 0 1481 system_stm32f4xx.o

158 24 0 4 264 4470 usart.o

Code (inc. Data) :显示代码占用了多少字节。 在此映像中,有19442字节的代码, 其中包括1832字节的内联数据 (inc. data),例如文字池和短字符串。

RO Data :显示只读数据占用了多少字节(比如const char buf[] = "123456")。这是除 Code (inc. data) 列中包括的内联数据之外的数据。

RW Data :显示读写数据占用了多少字节。

ZI Data :显示零初始化的数据占用了多少字节。

Debug :显示调试数据占用了多少字节,例如,调试输入节以及符号和字符串。

Object Totals :显示链接到一起以生成映像的对象占用了多少字节。

(incl. Generated):链接器会生成的映像内容,例如,交互操作中间代码。 如果 Object Totals 行包含此类型的数据,则会显示在该行中。本例中共有 1016 字节的 RO 数据,其中32字节是链接器生成的 RO 数据。

(incl. Padding) :链接器根据需要插入填充,以强制字节对齐。

下面的Library Totals显示已提取并作为单个对象添加到映像中的库成员占用了多少字节。

 

Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name

8 0 0 0 0 68 __main.o

0 0 0 0 0 0 __rtentry.o

12 0 0 0 0 0 __rtentry2.o

6 0 0 0 0 0 __rtentry4.o

52 8 0 0 0 0 __scatter.o

26 0 0 0 0 0 __scatter_copy.o

28 0 0 0 0 0 __scatter_zi.o

18 0 0 0 0 80 exit.o

6 0 0 0 0 152 heapauxi.o

2 0 0 0 0 0 libinit.o

6 0 0 0 0 0 libinit2.o

2 0 0 0 0 0 libshutdown.o

2 0 0 0 0 0 libshutdown2.o

8 4 0 0 96 68 libspace.o

2 0 0 0 0 0 rtexit.o

10 0 0 0 0 0 rtexit2.o

74 0 0 0 0 80 sys_stackheap_outer.o

2 0 0 0 0 68 use_no_semi.o

2 0 0 0 0 68 use_no_semi_2.o

10 0 0 0 0 116 fpinit.o

----------------------------------------------------------------------

282 12 0 0 96 700 Library Totals

6 0 0 0 0 0 (incl. Padding)

下面是整个映像文件的总结说明:

 

Code (inc. data) RO Data RW Data ZI Data Debug

4074 268 478 40 1896 445084 Grand Totals

4074 268 478 40 1896 445084 ELF Image Totals

4074 268 478 40 0 0 ROM Totals

==============================================================================

Total RO Size (Code + RO Data) 4552 ( 4.45kB)

Total RW Size (RW Data + ZI Data) 1936 ( 1.89kB)

Total ROM Size (Code + RO Data + RW Data) 4592 ( 4.48kB)

Grand Totals:显示映像的真实大小。

ELF Image Totals:ELF(Executable and Linking Format)可执行链接格式映像文件大小。

ROM Totals:显示包含映像所需的 ROM的最小大小。这不包括 ZI数据和存储在ROM 中的调试信息。

1)RO Size 包含了 Code 及 RO-data,表示程序占用 Flash 空间的大小;

2)RW Size 包含了 RW-data 及 ZI-data,表示运行时占用的 RAM 的大小;

3)ROM Size 包含了 Code、RO Data 以及 RW Data,表示烧写程序所占用的 Flash 空间的大小。

程序运行之前,需要有文件实体被烧录到 STM32 的 Flash 中,一般是 bin 或者 hex 文件,该被烧录文件称为可执行映像文件。如下面左图中所示,是可执行映像文件烧录到 STM32 后的内存分布,它包含 RO 段和 RW 段两个部分:其中 RO 段中保存了 Code、RO-data 的数据,RW 段保存了 RW-data 的数据,由于 ZI-data 都是 0,所以未包含在映像文件中。

STM32 在上电启动之后默认从 Flash 启动,启动之后会将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中,但不会搬运 RO 段,即 CPU 的执行代码从 Flash 中读取,另外根据编译器给出的 ZI 地址和大小分配出 ZI 段,并将这块 RAM 区域清零,如下右图所示;其余RAM空间作为动态内存堆使用。

uploading.4e448015.gif

转存失败重新上传取消

什么时候将RW数据拷贝到RAM的?

首先代码分为加载域和执行域,我们(烧录)加载代码后,代码及 RW 都被保存在 ROM 区(也就是stm32的nor flash)。当程序开始运行时,内核直接从 ROM 中读取代码,并且在执行主体代码前,会先执行一段加载代码,它

把 RW 节数据从 ROM 复制到 RAM, 并且在 RAM 加入 ZI 节,ZI 节的数据都被初始化为0。加载完后 RAM 区准备完毕,正式开始执行主程序。

.s启动文件上代码如下:

Reset_Handler PROC

EXPORT Reset_Handler [WEAK]

IMPORT SystemInit

IMPORT __main

 

LDR R0, =SystemInit

BLX R0

LDR R0, =__main

BX R0

ENDP

SystemInit()代码无非是一些寄存器初始化和配置向量表偏移,我们仍然没有看到关于RW和ZI的一段,因此我们怀疑是不是__main这个调用的C库函数除了执行对堆栈的初始化还执行了这个操作,接下来我们对某工程进行反汇编,程序中具有一段名为“__scatterload”的分散加载代码,需要注意的是,这段代码它是由 armlink 链接器自动生成的!

uploading.4e448015.gif

转存失败重新上传取消

这段分散加载代码包含了拷贝过程(LDM 复制指令),而 LDM 指令的操作数中包含了加载的源地址,这些地址中包含了内部 FLASH 存储的 RW-data 数据。而 “__scatterload ”的代码会被“__main”函数调用,__main 在启动文件中的“Reset_Handler”会被调用,因而,在main()函数执行前,已经完成了分散加载过程,随后进入我们熟悉的世界~~

附:我们查看map文件:

符号映像表(Image Symbol Table)中有 __scatterload 指令在flash的存储位置。

 

Global Symbols

Symbol Name Value Ov Type Size Object(Section)

__Vectors_Size 0x000001ac Number 0 startup_stm32f429xx.o ABSOLUTE

__Vectors 0x08000000 Data 4 startup_stm32f429xx.o(RESET)

__Vectors_End 0x080001ac Data 0 startup_stm32f429xx.o(RESET)

__main 0x080001ad Thumb Code 8 __main.o(!!!main)

__scatterload 0x080001b5 Thumb Code 0 __scatter.o(!!!scatter)

__scatterload_rt2 0x080001b5 Thumb Code 44 __scatter.o(!!!scatter)

__scatterload_rt2_thumb_only 0x080001b5 Thumb Code 0 __scatter.o(!!!scatter)

__scatterload_null 0x080001c3 Thumb Code 0 __scatter.o(!!!scatter)

__scatterload_copy 0x080001e9 Thumb Code 26 __scatter_copy.o

在存储器映射索引中,scatter 在flash的位置。

Memory Map of the image

 

Image Entry point : 0x080001ad

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x000011dc, Max: 0x00100000, ABSOLUTE)

Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x000011bc, Max: 0x00100000, ABSOLUTE)

Base Addr Size Type Attr Idx E Section Name Object

0x08000000 0x000001ac Data RO 470 RESET startup_stm32f429xx.o

0x080001ac 0x00000008 Code RO 1896 * !!!main c_w.l(__main.o)

0x080001b4 0x00000034 Code RO 2051 !!!scatter c_w.l(__scatter.o)

0x080001e8 0x0000001a Code RO 2053 !!handler_copy c_w.l(__scatter_copy.o)

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王涛的专栏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值