MAP文件分析

MAP文件分析描述映像文件的代码和数据块

大家好,欢迎来到IT知识分享网。

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会位于0x

b会位于0x


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: 0x0, Size: 0x000011f0, Max: 0x00, ABSOLUTE)

Execution Region ER_IROM1 (Exec base: 0x0, Load base: 0x0, Size: 0x000011c8, Max: 0x00, ABSOLUTE)

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

0x0 0x0 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: 0x, Load base: 0x080011c8, Size: 0x00000790, Max: 0x00030000, ABSOLUTE)

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

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

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

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

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

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

0x - 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 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[] = “”)。这是除 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 Grand Totals

4074 268 478 40 1896 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 0x0 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: 0x0, Size: 0x000011dc, Max: 0x00, ABSOLUTE)

Execution Region ER_IROM1 (Base: 0x0, Size: 0x000011bc, Max: 0x00, ABSOLUTE)

Base Addr Size Type Attr Idx E Section Name Object

0x0 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)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/116906.html

(0)
上一篇 2025-11-25 13:00
下一篇 2025-11-25 13:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信