目录
1.4 SECTION-ALLOCATION SECTION字段
1.5 VECTOR-ALLOCATION SECTION字段
1.6 OBJECT-ALLOCATION SECTION字段
1.8 SECTION USE IN OBJECT-ALLOCATION SECTION字段
1.9 OBJECT LIST SORTED BY ADDRESS字段
1.13 OBJECT-DEPENDENCIES SECTION字段
优质博文推荐阅读(单击下方链接,即可跳转):
map文件是linker链接器生成的一种文本文件,用于描述目标文件和可执行文件中包含的符号(函数,全局变量…)和地址信息。它包含了代码和数据在memory中的分布情况,以及它们在可执行文件中的位置和大小等信息。
map文件在嵌入式系统开发中非常有用,可以提供许多与程序有关的详细信息,帮助开发人员更好地理解程序的结构和内存使用情况,进而进行程序优化和调试。
map文件的格式和结构没有标准化,其内容与使用的微控制器开发工具强相关:不同的编译器和链接器生成的内容,存在不小的差异。
本文以芯片NXP MM9Z1J638,在CodeWarrior Development Studio Version: 10.6.4工具中编译生成的MAP文件为例。
1 Map文件格式
下表描述了Map File中包含的字段。
下面根据一个具体的MM9Z1J638工程,给大家详细介绍一下CodeWarrior 10.6.4工程的map文件内容。
1.1 TARGET SECTION字段
摘录:
*********************************************************************************************
TARGET SECTION
---------------------------------------------------------------------------------------------
Processor : Freescale S12Z
Memory Model: SMALL
File Format : ELF\DWARF 2.0
Linker : SmartLinker V-5.0.50 Build 13206, Jul 26 2013
Processor: 表示代码正在被编译的处理器架构。在本例中,它是Freescale S12Z处理器。
Memory Model: 表示代码所使用的memory model。memory model决定了代码在目标处理器上的存储和执行方式。Memory Model通常是指一种对内存地址空间的划分方式和地址空间中各个区域的使用规则。在嵌入式系统中,Memory Model的选择通常受限于处理器的架构、内存大小、应用程序的需求等因素。不同的嵌入式系统可能支持不同的Memory Model,一般而言,Memory Model可以分为以下几类:TINY,SMALL,MEDIUM,LARGE,COMMON和BANKED。
- Memory Model = SMALL:编译器会生成对全局非常量数据的14位访问。所有全局非常量数据必须适合16KB的RAM。
- Memory Model = MEDIUM:编译器会生成对全局非常量数据的18位访问。所有全局非常量数据必须适合256KB的RAM。
- Memory Model = LARGE:编译器会生成对全局非常量数据的24位访问。
- Memory Model = BANKED:Banked memory model默认使用banked函数调用,但默认的数据访问仍然是16位(即使用16位访问,页号在高字节,偏移在低字节)。因为far函数调用的开销不是很大,这种memory model适合所有代码量超过64KB的应用程序。可以使用数据分页,然而所有的far对象和指向它们的指针都必须特别声明。
- Memory Model = TINY: 在TINY memory model中,所有的数据包括堆栈都必须适合在zero page中。这个memory model假定数据指针有8位地址,除非用关键字__far明确指定。代码地址空间为64KB,函数指针大小为16位。
File Format: 这一行表示编译后的代码所使用的文件格式。在本例中,代码使用ELF/DWARF 2.0格式,这是一种可执行文件和目标文件的标准格式。
Linker: 这一行表示用于生成映射文件的Linker链接器工具。在本例中,它是SmartLinker V-5.0.50 Build 13206,它是NXP提供的链接器工具。
1.2 FILE SECTION字段
摘录:
*********************************************************************************************
FILE SECTION
---------------------------------------------------------------------------------------------
ecu_c.obj Model: SMALL, Lang: ANSI-C
nvm_c.obj Model: COMMON, Lang: Assembler
在这个Map文件中,FILE SECTION关键字给出了编译生成的每个目标文件的信息。每个目标文件的名称和使用的Memory Model都在这里列出。
与之前的例子不同的是,第一个目标文件名为ecu.obj,使用的Memory Model为SMALL,编写语言为ANSI-C;而第二个目标文件名为nvm_c.obj,使用的Memory Model为COMMON,编写语言为汇编语言(Assembler)。
COMMON Memory Model也是一种适用于16位微控制器的Memory Model,它允许不同模块之间共享同一段内存。在COMMON模型下,所有模块都可以访问共享内存段,这些段的大小和位置可以由用户定义。这种模型适用于一些需要在多个模块之间传递数据的应用场景。
1.3 STARTUP SECTION字段
摘录:
*********************************************************************************************
STARTUP SECTION
---------------------------------------------------------------------------------------------
Entry point: 0xFE0834 (_Startup)
_startupData is allocated at 0xFE0860 and uses 20 Bytes
extern struct _tagStartup {
unsigned nofZeroOut 2
_Range pZeroOut 0x1000 14
0x1210 5717
_Copy *toCopyDownBeg 0xFF8C65
int nofInitBodies 0
_Cpp *initBodies 0xFE0882
int nofFiniBodies 0
_Cpp *finiBodies 0xFE0882
} _startupData;
在这个Map文件中,STARTUP SECTION关键字给出了启动代码的相关信息。从这个例子中可以看出,这个启动代码的入口点(Entry point)是0xFE0834,也就是在程序运行时,系统将从这个地址开始执行启动代码。
_startupData结构体是一个用于存储启动代码的相关信息的变量,其中包括了需要进行清零操作的内存区域以及需要进行拷贝操作的内存区域的起始地址和大小。它在内存中的地址为0xFE0860,使用了20个字节。结构体包含以下信息:
- nofZeroOut:启动时用零字节填充的READ_WRITE段的数量,本例中为2。如果你没有任何需要在启动时初始化的RAM内存区,则不需要。在启动结构中不存在时,pZeroOut也不能存在。
- pZeroOut:指向一个元素类型为_Range的向量的指针。它正好有nofZeroOuts元素,每个元素描述一个要清除的内存区域。如果你没有任何RAM内存区域,则不需要,这需要在启动时进行初始化。在启动结构中不存在时,nofZeroOuts也不能存在。本例中有两个范围:0x1000到0x1210和0x1210到0xFF8C65。
- toCopyDownBeg:包含运行时必须从ROM拷贝到RAM的第一个项目的地址,本例中为0xFF8C65。所有要复制的数据都存储在一块连续的ROM memory中,其格式如下:CopyData = {Size[t] TargetAddr {Byte}Size} 0x0[t]),Size是一个二进制数,其最重要的字节被存储在前面。如果你没有任何RAM内存区,则不需要,这需要在启动时进行初始化。对齐是用来对齐下一个Size和TargetAddr字段。对齐字节的数量取决于处理器访问未对齐数据的能力。对于小型处理器,通常不需要对齐。Size[t]和0x0[t]的大小t取决于目标处理器和内存模型。
- nofInitBodies:在调用应用程序根函数之前必须执行的C++全局构造函数的数量。如果应用程序不包含C++模块,则不需要。在startup structure中不存在时,initBodies必须不存在,本例中为0。
- initBodies:指向一个函数指针的向量,包含应用程序中全局C++构造函数的地址,按调用顺序排序。确切地包含nofInitBodies元素。如果应用程序不包含任何C++模块,该向量为空。如果应用程序不包含任何C++模块,则不需要。当startup structure中不存在时,nofInitBodies也必须不存在。
- nofFiniBodies:在调用应用程序根函数后必须执行的C++全局destructor的数量。如果应用程序不包含一个C++模块,则不需要。当startup structure中不存在时,finiBodies也必须不存在。如果应用程序根函数不返回,nofFiniBodies和finiBodies都可以被省略。
- finiBodies:指向一个函数指针的向量,包含应用程序中全局C++ destructor的地址,按调用顺序排序。确切地包含nofFiniBodies元素。如果一个应用程序不包含任何C++模块,该向量为空。如果应用程序不包含C++模块,则不需要。当启动结构中不存在时,nofFiniBodies也不能存在。如果应用程序根函数不返回,nofFiniBodies和finiBodies都可以被省略。
1.4 SECTION-ALLOCATION SECTION字段
摘录:
*********************************************************************************************
SECTION-ALLOCATION SECTION
Section Name Size Type From To Segment
---------------------------------------------------------------------------------------------
.init 15 R 0xC000 0xC00E ROM_C000
.startData 46 R 0xC00F 0xC03C ROM_C000
SHARED_DATA 2 R/W 0x26BA 0x26BB RAM
PAGED_RAM 3606 R/W 0xFD1000 0xFD1E15 RAM_FD
XGATE_STK_L 2 N/I 0xF8107E 0xF8107F RAM_XGATE_STK_L
……
Summary of section sizes per section type:
READ_ONLY (R): 1D543 (dec: 120131)
READ_WRITE (R/W): 4C0A (dec: 19466)
NO_INIT (N/I): 303 (dec: 771)
在这个Map文件中,SECTION-ALLOCATION SECTION关键字表示了各个段类型的汇总信息,包括只读段(READ_ONLY)、读写段(READ_WRITE)和未初始化段(NO_INIT)的大小,以十六进制和十进制表示。通过最后的Summary可以看出,每个section类型的大小:(READ_ONLY(R)为Flash的大小,而READ_WRITE(R/W)为RAM大小)
- READ_ONLY (R):只读区段,其大小为120131字节。
- READ_WRITE (R/W):读写区段,其大小为19466字节。
- NO_INIT (N/I):未初始化区段,其大小为771字节。
注:
READ_ONLY (R):只读段,该段内存内容在程序执行期间不可修改,通常用于存放程序代码和只读数据,如常量和只读配置数据等;
READ_WRITE (R/W):读写段,该段内存内容可被程序读取和修改,通常用于存放可读写的变量和数据,如全局变量、堆和栈等;
NO_INIT (N/I):未初始化段,该段内存的初值为未知或者未被定义,通常用于存放全局变量和静态变量的内存空间,这些变量在程序运行前没有被初始化过。程序执行期间需要手动初始化这些变量,否则它们的值将是未知的。
这个汇总信息可以帮助开发人员了解代码中不同类型段的占用情况,以便更好地进行内存优化和管理。
1.5 VECTOR-ALLOCATION SECTION字段
摘录:
*********************************************************************************************
VECTOR-ALLOCATION SECTION
Address InitValue InitFunction
---------------------------------------------------------------------------------------------
0xFFFE 0xC000 _Startup
在这个Map文件中,VECTOR-ALLOCATION SECTION关键字表示中断向量表的分配情况,其中:
- Address列指示了中断向量表在内存中的起始地址;
- InitValue列指示了对应位置上的初始值,通常为0或其他特定的值;
- InitFunction列则指示了对应位置上的中断处理函数的入口地址。如果该位置没有对应的中断处理函数,则该列通常为空。
这意味着当系统出现中断事件时,程序将跳转到0xFFFE的地址处执行"_Startup"函数中的代码。这也是整个系统的启动入口。
需要注意的是,由于不同的嵌入式系统或编译工具可能采用不同的中断向量表分配策略,因此在具体的开发中,需要查阅相关的文档或者参考示例代码,以确定中断向量表的具体分配情况。
1.6 OBJECT-ALLOCATION SECTION字段
摘录:
*********************************************************************************************
OBJECT-ALLOCATION SECTION
Name Module Addr hSize dSize Ref Section RLIB
---------------------------------------------------------------------------------------------
MODULE: -- util_c.obj --
- PROCEDURES:
CircBufGetRollingAvg FE4EB2 2A 42 3 .text
CircBufInit FE4EDC 28 40 4 .text
CircBufInsert FE4F04 D5 213 3 .text
CircBufReset FE4FD9 16 22 7 .text
UTIL_Copy FE4FEF 4A 74 31 .text
InterpU16 FE5039 F9 249 14 .text
UTIL_StateExec FE5132 21 33 6 .text
UTIL_init FE5153 4 4 1 .text
binSearchU16 FE5157 AD 173 3 .text
BilinearInterpU32 FE5204 658 1624 1 .text
calcInd FE585C 1B 27 16 .text
LinearInterpU32 FE5877 83 131 4 .text
CalcStackUsage FE58FA 67 103 1 .text
GetNumberofBytesUsed FE5961 A 10 1 .text
convUInt16To2BytesArray FE596B 35 53 15 .text
satConvUInt32To3BytesArray FE59A0 54 84 17 .text
convUInt32To4BytesArray FE59F4 102 258 2 .text
- VARIABLES:
number_of_unused_bytes 1E62 2 2 5 .common
time 1E64 4 4 1 .common
- LABELS:
__SEG_START_SSTACK 1010 0 0 2
__SEG_SIZE_SSTACK 200 0 0 3
在这个Map文件中,OBJECT-ALLOCATION SECTION关键字用于显示每个目标文件所分配的内存中的符号和变量信息,这些目标文件可以是C语言、汇编语言等不同的语言编写的。其中,该部分包括了以下几个信息:
- Name:符号或变量的名称
- Module:符号或变量所在的目标文件名称
- Addr:符号或变量的地址
- hSize:符号或变量在RAM中分配的空间大小
- dSize:符号或变量在ROM中分配的空间大小
- Ref:符号或变量的引用次数
- Section:符号或变量所在的段名
- RLIB:符号或变量是否是从库文件中引用的
从这些信息中,我们可以了解到每个目标文件中包含了哪些函数和全局变量,它们分别被分配到了哪些地址上,以及它们在RAM和ROM中所占用的空间大小等。
这个部分展示了模块ecu_c.obj中包含的函数和全局变量的地址、Size和Ref情况。具体解释如下:
- PROCEDURES:列出了模块(C文件)中包含的所有函数。每个函数在内存中的地址、Size(指函数所占的代码段大小)、数据大小(指函数所占的数据段大小)、引用数(指其他部分引用该函数的次数)、以及该函数所在的段名称(这里是.text)都会显示出来。
- VARIABLES:列出了模块中包含的所有全局变量。每个全局变量在内存中的地址、Size、引用数(Ref)、以及该全局变量所在的段名称都会显示出来。
- LABELS:列出了模块中的标签(通常是程序中的标记点,如函数入口、跳转目标等)的信息,包括标签名(如 __SEG_START_SSTACK、__SEG_SIZE_SSTACK)、地址(Addr)、Size和引用数(Ref)信息。
1.7 MODULE STATISTIC字段
摘录:
*********************************************************************************************
MODULE STATISTIC
Name Data Code Const
---------------------------------------------------------------------------------------------
ecu_c.obj 21 360 32
nvm_c.obj 2647 13205 0
os_c.obj 120 464 95
在这个Map文件中,MODULE STATISTIC关键字用来展示每个模块(object文件)所占用的内存大小统计,以数据、代码、常量三种类型来区分。
这段内容显示了两个源文件(object file)的代码和数据的统计信息,包括数据、代码和常量的大小。具体来说,这些数字表示:
- Data:指的是RAM,已初始化的全局变量和静态变量的总大小(以字节为单位)。
- Code:指的是Flash,所有函数的总代码大小(以字节为单位)。
- Const:指的是Flash,程序中使用的所有常量的总大小(以字节为单位)。
以ecu_c.obj模块为例,该模块占用了21 bytes的数据段空间,360 bytes的代码段空间和32 bytes的常量段空间。同样的,nvm_c.obj模块占用了2647 bytes的数据段空间,13205 bytes的代码段空间,而没有常量段。
1.8 SECTION USE IN OBJECT-ALLOCATION SECTION字段
摘录:
*********************************************************************************************
SECTION USE IN OBJECT-ALLOCATION SECTION
---------------------------------------------------------------------------------------------
SECTION: ".text"
ECU_GetMd ECU_Init ECU_SetMd byteCmp byteCopy NVM_CmdEraseAndWrite
NVM_CompInit NVM_EraseSector
SECTION: ".data"
nvm_configuration comp_vals_p num_skip_samples
这段是对OBJECT-ALLOCATION SECTION关键字中的段(如".text"代码段)的使用情况进行列举,其中涉及了函数和变量的名称。
1.9 OBJECT LIST SORTED BY ADDRESS字段
摘录:
*********************************************************************************************
OBJECT LIST SORTED BY ADDRESS
Name Addr hSize dSize Ref Section RLIB
---------------------------------------------------------------------------------------------
UTIL_CircBufGetRollingAvg FE4EB2 2A 42 3 .text
UTIL_CircBufInit FE4EDC 28 40 4 .text
UTIL_CircBufInsert FE4F04 D5 213 3 .text
UTIL_CircBufReset FE4FD9 16 22 7 .text
UTIL_Copy FE4FEF 4A 74 31 .text
UTIL_InterpU16 FE5039 F9 249 14 .text
UTIL_StateExec FE5132 21 33 6 .text
UTIL_init FE5153 4 4 1 .text
在这个Map文件中,OBJECT LIST SORTED BY ADDRESS关键字展示了一个对象(函数,全局变量)列表,按地址排序,每个对象具有以下属性:
- Name:对象名称。
- Addr:对象在内存中的起始地址。
- hSize:对象头大小(如果有)。
- dSize:对象数据大小。
- Ref:对象被其他模块引用的次数。
- Section:对象所属的段。
- RLIB:对象是否来自于一个库文件。
1.10 UNUSED-OBJECTS SECTION字段
摘录:
*********************************************************************************************
UNUSED-OBJECTS SECTION
---------------------------------------------------------------------------------------------
NOT USED PROCEDURES
nvm_c.obj:
NVM_GetDiagFltStatus NVM_GetDrec_LifeTimeMinutes_Data
NVM_GetDrec_AgePrediction_Data NVM_GetDrec_FltSnapShot_Data
NVM_SetCriticalLowCellVltgFault NVM_GetCriticalLowCellVltgFault
NOT USED VARIABLES
ecu_c.obj:
.dwarf.fbl_prog_pattern .dwarf.cbl_prog_pattern .dwarf.app_norm_pattern
.dwarf.app_dev_pattern .dwarf.clear_pattern .dwarf.current_md
在这个Map文件中,UNUSED-OBJECTS SECTION关键字展示的是在代码中定义但从未被使用的程序(函数)和全局变量列表,这里展示了nvm_c.obj和ecu_c.obj中的一些函数和全局变量,它们被列为“NOT USED PROCEDURES”和“NOT USED VARIABLES”。
1.11 COPYDOWN SECTION字段
摘录:
*********************************************************************************************
COPYDOWN SECTION
---------------------------------------------------------------------------------------------
------- ROM-ADDRESS: 0xFF8C65 ---- SIZE 7 ---
Filling bytes inserted
0000006700 1210
------- ROM-ADDRESS: 0xFF8C6C ---- RAM-ADDRESS: 0x1210 ---- SIZE 87 ---
Name of initialized Object : nvm_configuration
0C00000C00 0C08001804 0020040024
0400280400 2C0C003004 003C0C0040
1C004C0400 6804006C04 00700C0074
0400800C00 840C009004 009C0400A0
1400A40C00 B80400C404 00C80400CC
0800D00400 D80C00DC18 00E8
在这个Map文件中,COPYDOWN SECTION关键字是在程序启动时需要从ROM复制到RAM中的数据段。这通常包括初始化全局变量和静态变量。具体来说,这个部分列出了从ROM到RAM要复制的数据块的地址和大小。
在这个例子中,从ROM-ADDRESS:0xFF8C65到ROM-ADDRESS:0xFF8C6C之间的7字节是填充字节;然后从ROM-ADDRESS:0xFF8C6C处开始,大小为87字节的数据块被复制到RAM-ADDRESS:0x1210处,这个数据块名字为 "nvm_configuration"。
1.12 CHECKSUM SECTION字段
摘录:
*********************************************************************************************
CHECKSUM SECTION
---------------------------------------------------------------------------------------------
Checksum 0 from code FE0410 to FFBFEF with METHOD_CRC32 init FFFFFFFF polynom 4C11DB7 written to FE040C size 4 is "F0 77 79 15"
Checksum 1 from code FE0010 to FE03FF with METHOD_CRC32 init FFFFFFFF polynom 4C11DB7 written to FE000C size 4 is "7D 95 5D CD"
在这个Map文件中,CHECKSUM SECTION关键字显示了为代码的两个不同内存区域计算的校验和值。校验和是通过对内存区域的数据用算法计算出来的值,以验证其完整性或检测其是否被破坏。
第一个校验值"F0 77 79 15 ",是针对从代码地址"FE0410"到"FFBFEF"的内存区域,它是用CRC32算法计算的,初始值为"FFFFFFF",多项式为"4C11DB7";
第二个校验值,"7D 95 5D CD",是针对从代码地址"FE0010"到"FE03FF"的内存区域,它也是用CRC32算法计算的,初始值为"FFFFFFF",多项式为"4C11DB7"。
1.13 OBJECT-DEPENDENCIES SECTION字段
摘录:
*********************************************************************************************
OBJECT-DEPENDENCIES SECTION
---------------------------------------------------------------------------------------------
VAR00003 USES Cal_Ftr
App_Hdr_end_addr_p USES App_Ftr
App_Hdr_start_addr_p USES _Startup
ISR_001_unused USES ISR_Dummy
ISR_002_unused USES ISR_Dummy
在这个Map文件中,OBJECT-DEPENDENCIES SECTION关键字中列出了一些对象(函数)以及它们使用的其他对象。例如,“VAR00003 USES Cal_Ftr”,意味着VAR00003对象需要Cal_Ftr对象才能工作。其他列出的对象和它们使用的对象包括App_Hdr_end_addr_p(App_Ftr)、App_Hdr_start_addr_p(_Startup)、ISR_001_unused(ISR_Dummy)、ISR_002_unused(ISR_Dummy)和ISR_003_unused(ISR_Dummy)。
1.14 DEPENDENCY TREE字段
摘录:
*********************************************************************************************
DEPENDENCY TREE
*********************************************************************************************
main and _Startup Group
|
+- main
| |
| +- CAL_Init
| |
| +- ECU_Init
| | |
| | +- byteCopy
| |
| +- HWIO_Init
这是一个依赖树,它描述了程序中各个函数之间的依赖关系。树的根节点是"main and _Startup Group",代表main和_Startup Group。接下来是"main"函数,它依赖于"CAL_Init"和"ECU_Init"函数。"ECU_Init"又依赖于和"byteCopy"函数。这个依赖树可以帮助开发人员了解程序的结构和各个函数之间的关系,方便代码的维护和优化。
1.15 STATISTIC SECTION字段
摘录:
*********************************************************************************************
STATISTIC SECTION
---------------------------------------------------------------------------------------------
ExeFile:
--------
Number of blocks to be downloaded: 11
Total size of all blocks to be downloaded: 113702
该段是统计信息部分,其中包含两个指标:
- Number of blocks to be downloaded: 11:需要下载的block数量,这个值对于固件烧录很重要,它表示需要烧录多少个block;
- Total size of all blocks to be downloaded: 113702:需要下载的所有block的总大小,单位为字节(byte)。这个指标也非常关键,因为它决定了固件烧录的时间和烧录器的存储容量是否足够。
以上部分内容摘自“CodeWarrior Development Studio的Help文件”。
结尾
获取更多“汽车电子资讯”和“工具链使用”,
请关注优快云博客“汽车电子助手”,做您的好助手。