Keil Map文件分析

以前查看map,基本就是看一下Flash大小、和RAM总大小,或者是debug时确认下 函数编译地址。

最近心血来潮,想用C#做个上位机来解一下这个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
    镜像分配大小

        是指STM32等嵌入式系统编译后生成的映像文件(Image)中各个组成部分所占用的存储空间大小。这些信息对于理解程序的内存使用情况、优化代码和内存布局至关重要。

        

具体各个模块的格式解析:

Section Cross References

实例:
system_stm32f4xx.o(i.SystemCoreClockUpdate) refers to system_stm32f4xx.o(.data) for SystemCoreClock
system_stm32f4xx.c的函数SystemCoreClockUpdate 引用了 system_stm32f4xx.c 的函数SystemCoreClock

startup_stm32f429xx.o(RESET) refers to stm32f4xx_it.o(i.HardFault_Handler) for HardFault_Handler
startup_stm32f429xx.c(RESET段) 引用了 stm32f4xx_it.c 的函数HardFault_Handler

总结: XX.c 引用了 YY.c 的 ZZ (函数或全局变量)
衍生:
    1)基于XX,可以筛选一个c文件引用了哪些函数或变量
    2)基于YY,可以筛选一个c文件被哪些文件引用了
    3)基于ZZ,可以筛选一个函数或变量被哪些文件引用了
说明:
    i.FF 通常表示一个函数
    (.data) 表示内存中的data段 初始化了的全局变量或静态变量
        类似的还有 (.text)/(.code) 代码段  (.bss) 未初始化的全局变量或静态变量 (.heap) (.stack)
        其中, (RESET)是一个特殊段 它是STM32控制器复位向量的地址

Removing Unused input sections from the image


实例:
Removing system_stm32f4xx.o(.rev16_text), (4 bytes).
移除了system_stm32f4xx.c的rev16_text端的代码 共4字节

Removing stm32f4xx_hal_msp.o(i.HAL_ADC_MspDeInit), (100 bytes)
移除了stm32f4xx_hal_msp.c的HAL_ADC_MspDeInit函数 共100字节

总结: 移除了XX.c的YY代码 共Z个字节
衍生:
    1)基于XX和Z,可以筛选一个c文件的多于代码量
    2)基于XX和YY,可以明确哪些函数未用到

Image Symbol Table

实例:
    Symbol Name                              Value     Ov Type        Size  Object(Section)
    ../Core/Src/main.c                       0x00000000   Number         0  main.o ABSOLUTE
    ../USB_DEVICE/App/usb_device.c           0x00000000   Number         0  usb_device.o ABSOLUTE
    ..\VciModle\App\VciModleApp.c            0x00000000   Number         0  vcimodleapp.o ABSOLUTE
    i.ArkCan1_Task                           0x08011e20   Section        0  arkcantask.o(i.ArkCan1_Task)
    i.ArkCan2_Task                           0x08011f60   Section        0  arkcantask.o(i.ArkCan2_Task)
    i.ArkCanBaudRangeCheck                   0x08012068   Section        0  arkcmdintelligent.o(i.ArkCanBaudRangeCheck)
    ArkCanBaudRangeCheck                     0x08012069   Thumb Code    84  arkcmdintelligent.o(i.ArkCanBaudRangeCheck)
    i.ArkCanCmdSendFinish                    0x080120c8   Section        0  arkcantask.o(i.ArkCanCmdSendFinish)
    依次是符号名称、符号的地址、符号类型、符号大小和地址空间

总结:可以找到单个函数的地址和代码量大小

Memory Map of the image

实例:
  Image Entry point : 0x080101ad
  Load Region LR_IROM1 (Base: 0x08010000, Size: 0x0006c0c8, Max: 0x00100000, ABSOLUTE, COMPRESSED[0x0006bc98])
    Execution Region ER_IROM1 (Exec base: 0x08010000, Load base: 0x08010000, Size: 0x0006b548, Max: 0x00100000, ABSOLUTE)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    
    0x0801bf84   0x0801bf84   0x00000038   Code   RO         2322    i.CRC32_Add         vcicommonfun.o
    0x0801bfbc   0x0801bfbc   0x0000000c   Code   RO         2323    i.CRC32_Get         vcicommonfun.o
    0x0801bfc8   0x0801bfc8   0x00000010   Code   RO         2324    i.CRC32_Init        vcicommonfun.o
    依次是 执行地址、加载地址、大小、类型、属性、索引 名称和所属的对象
    类型见段交叉引用中的“说明”、属性表示读写属性、名称即函数名

总结:可以找到单个函数的地址和代码量大小,以及属性等信息

Image component sizes

实例:
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
      3870        272        180          2        264      18242   arkcantask.o

总结:用于统计整个文件的RAM和ROM占用量
说明:可基于上位机工具,计算每个文件的RAM和ROM占用量,转成表格文件进行进一步分析
 

C# 解析Image component sizes

public static string FileAnalyzing(string path)
{
    StreamReader sr = new StreamReader(path);
    string line, tempStr, retStr = null, content = null;
    int line_status = 0, index = 0, temp;

    line = sr.ReadLine();
    while (line != null)
    {
        if (line.Contains("Component"))
        {
            retStr += "编译器版本" + line.Substring(10) + "\r\n";
        }
        else if (line.Contains("Image component sizes"))
        {
            retStr += "\r\n内存分配表\r\n==============================================================================\r\n";

            line_status = 1;
        }
        else if (line.Contains("----------------------------------------------------------------------"))
        {
            line_status = 0;
        }
        else if (line.Contains("Total ROM Size"))
        {
            retStr += line.Replace("Total ROM Size (Code + RO Data + RW Data)", "Flash:") + "\r\n";
        }
        else if (line.Contains("Total RW  Size"))
        {
            retStr += "==============================================================================\r\n";
            retStr += line.Replace("Total RW  Size (RW Data + ZI Data)       ", "ROM:  ") + "\r\n";
        }

        if (line_status == 1)
        {
            if (line.Contains("Code (inc. data)"))
            {
                retStr += "Index  RAM    ROM  code  data  RO   RW     ZI  Debug Object Name\r\n";
                content += "Index RAM ROM code data RO RW ZI Debug ObjectName\r\n";
                line_status = 2;
                index = 0;
            }
        }
        else if (line_status == 2)
        {
            string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (parts.Length == 7)
            {
                /*
                    3870            Code 
                    272             (inc. data)
                    180             RO Data
                    2               RW Data
                    264             ZI Data
                    18242           Debug
                    arkcantask.o    Object Name

                    Total ROM Size (Code + RO Data + RW Data)
                    Total RW  Size (RW Data + ZI Data)
                 */
                index++;

                tempStr = index.ToString().PadLeft(4);//索引
                temp = Convert.ToInt32(parts[0]) + Convert.ToInt32(parts[2]) + Convert.ToInt32(parts[3]);
                tempStr += temp.ToString().PadLeft(6);//RAM
                temp = Convert.ToInt32(parts[3]) + Convert.ToInt32(parts[4]);
                tempStr += temp.ToString().PadLeft(7);//ROM

                tempStr += parts[0].PadLeft(6);
                tempStr += parts[1].PadLeft(5);
                tempStr += parts[2].PadLeft(5);
                tempStr += parts[3].PadLeft(5);
                tempStr += parts[4].PadLeft(7);
                tempStr += parts[5].PadLeft(7) + " ";
                tempStr += parts[6].Replace(".o", ".c") + "\r\n";

                retStr += tempStr;

                tempStr = index.ToString() + " ";//索引
                temp = Convert.ToInt32(parts[0]) + Convert.ToInt32(parts[2]) + Convert.ToInt32(parts[3]);
                tempStr += temp.ToString() + " ";//RAM
                temp = Convert.ToInt32(parts[3]) + Convert.ToInt32(parts[4]);
                tempStr += temp.ToString() + " ";//ROM

                tempStr += parts[0] + " ";
                tempStr += parts[1] + " ";
                tempStr += parts[2] + " ";
                tempStr += parts[3] + " ";
                tempStr += parts[4] + " ";
                tempStr += parts[5] + " ";
                tempStr += parts[6].Replace(".o", ".c") + "\r\n";
                content += tempStr;
            }
        }

        line = sr.ReadLine();
    }

    sr.Close();

    retStr += "\r\nText文本\r\n==============================================================================\r\n" + content;

    return retStr;
}

主要思路就是,逐行解析文本文件,以空格作为分隔符得到各个元素,再进行展示。

同时再打印一份精简版的文本,可以用于将文本转为execl文件,进行图表分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猪熊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值