编译工具链 之四 ARM-MDK、IAR、GCC 的 .MAP 文件、.LST 文件

这篇具有很好参考价值的文章主要介绍了编译工具链 之四 ARM-MDK、IAR、GCC 的 .MAP 文件、.LST 文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  .map 文件和 .lst 文件是嵌入式开发中最有用的俩调试辅助文件。现在主要从事 RISC-V 架构,主要与 GCC 打交道,今天就重点学习一下 GCC 的 .map 文件、.lst 文件,并辅助以 ARMCC 和 IAR 作为对比。

  本文中的 DEMO 主要是使用 https://gitee.com/itexp/STM32_BareMetal 这个代码,其中配置好了 ARM-MDK、IAR、ECLIPSE 等众多常用开发工具的项目工程。

编译

  .map 文件和 .lst 文件就是编译工具链给出的构建过程的一些 LOG 文件。要编译出最终的可执行程序,通常需要编译、链接、转换这三个阶段。其中,编译即编译器将源码翻译成对象文件,链接即链接器将各个对象文件组合成最终可执行程序。现代编译器通常产生一个通用格式(通常是带有调试信息)的最终可执行程序(ELF 文件),然后使用相应的工具从中提取出实际的纯可执行程序。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  能独立提供编译工具链的厂家并不多,嵌入式平台则更少,主要就是 ARM、IAR、GNU、LLVM。其中,ARM、IAR 是收费的专用软件,其支持的架构有限,而 GNU 的 GCC 则是一款支持众多架构的开源编译套件;LLVM 则是后起之秀,同样也支持众多架构,目前用的不如 GCC 广泛!如下是常用编译器:
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

编译工具链及基本概念参见独立博文 编译工具链 之一 基本概念、组成部分、交叉编译工具链、命名规则

.map 文件

  .map 文件对应的中文名应该是映射文件,用来展示(映射)项目构建的链接阶段的细节。通常包含程序的全局符号、交叉引用和内存映射等等信息。目前,常见的编译器套件(实际是其中的链接器),例如, GCC、ARMCC、IAR 都可以生成 .map 文件。

GCC

  GCC 编译工具链中的链接器、汇编器、objdump 等工具都位于 GNU Binutils 中,他们的相关文档可以直接在官网下载。相比于 ARMCC 和 IAR,GCC 的 MAP 文件中的内容比较少!

产生方式

  在 GCC 中,MAP 文件就是由链接器 ld 通过使用命令 -Map=mapfile 来输出 map 文件。需要注意,如果同时使用了 --print-map 则会只将 MAP 内容输出到编译窗口,而不会生成 MAP 文件。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  需要注意的是,如果使用了编译器 gcc 作为入口(通常都是这么做,不会直接调用链接器),则需要使用 -Wl,-Map,FILE 的方式来将参数传递给链接器。编译器参数 -Wl 是专门用来传递参数给链接器的。同样,如果使用了 -Xlinker --print-map 则只会将 MAP 信息输出到编译窗口,而不会再生成 MAP 文件!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  在实际开发中,ECLIPSE 的相关配置如下所示。目前没有该明白,为何它要以 g++ 作为链接器的入口!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内容介绍

  在理解内容之前,有必要先了解一下工具链提供的存档文件(Archive File)。前面说过,工具链提供了 lib 这一部分, lib 中的各个函数的实现是已经进行了预编译的,并且把预编译的各种 .o 文件打包成为存档文件(.a 文件)。编译单元即一个 .o 文件。

GCC 的 MAP 文件相比于 ARMCC 和 IAR 内容少了很多

存档文件引用关系

  MAP 文件的第一部分内容列出了我们项目中所使用的标准库中提供的函数的基本调用情况,基本格式如下:

存档文件 (编译单元)
    			调用存档文件中接口的文件(调用的符号)

  如下图所示的示例,表示 crt0.o 中正在调用 exit 这个接口,而 exit 位于 lib_a-exit.o 这个文件中,而 lib_a-exit.o 这个文件存在于 libg.a 这个存档文件中!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

丢弃的输入段

  MAP 文件的第二部分内容列出了链接器在生成最终可执行文件时丢弃的输入段,每行一个,四列的含义从左到右依次为节区名、地址、节区大小、节区所在的编译单元。注意,如果节区位于存档文件中,则最后一列是存档文件 + (编译单元)。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内存配置

  MAP 文件的第三部分内容列出了我们的内存(存储)配置情况,每行一个,四列的含义从左到右依次为存储的名字、起始地址、大小(字节)、属性(r:读、x:执行、w:写)
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

链接脚本和内存映射

  关于链接脚本我们后面在详细介绍,这部分链接脚本就是一些 MRI 兼容的链接脚本命令,简单来说,使用 MRI 兼容的链接脚本命令引入一些对象文件(.o)。 MRI 兼容的链接脚本命令是用于早期链接器的,在 ld 手册中有说明,现在存在的唯一的目的就是兼容!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  这部分最有用的是紧随其后的内存映射,这部分列出了所有符号在内存(存储)中的物理地址,这部分就是在辅助调试时最常用的!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

ARM

产生方式

  参见博文 ARM 之十 ARMCC(Keil) map 文件(映射文件)详解。

内容介绍

  参见博文 ARM 之十 ARMCC(Keil) map 文件(映射文件)详解。

IAR

产生方式

  由链接器参数 --map 来产生。当启用 MAP 文件后,链接器支持的其他一些参数的输出就会输出到 MAP 文件中。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内容介绍

  暂无,后续有需要再补充!文章来源地址https://www.toymoban.com/news/detail-804912.html

.lst 文件

  .lst 文件全称是 Assembler list file,主要用来存储汇编程序列表数据,它通常会拥有比 .map 文件更详细的信息。借助 .lst 文件,同时通过查看栈帧结构(可以通过查看相应的手册来确定栈帧的组成),通过在 .lst 文件中查找 lr 的地址所在的位置,就能立刻定位到问题。

GCC

  GCC 编译工具链中的链接器、汇编器、objdump 等工具都位于 GNU Binutils 中,他们的相关文档可以直接在官网下载。

产生方式

  .lst 文件通常是由汇编器产生的,对于 GCC 的汇编器 as,通过使用命令 -a[cdghlmns]=[FILE] 来输出 lst 文件。但需要注意的是,-a[cdghlmns]=[FILE] 参数是独立使用汇编器 as 的时候才生效的。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  与上面说的 MAP 文件产生一样,如果使用了编译器 gcc 作为入口(通常都是这么做,不会直接调用汇编器),则需要使用 -Wa,-a,FILE 的方式来将参数传递给汇编器。编译器参数 -Wa 是专门用来传递参数给汇编器的。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  在实际开发中,我们经常写 -Wa,-adhlns="$@.lst",这样,每编译一个源文件就会产生一个对应的 .lst 文件。需要注意的是,如果是高级语言文件(例如 C 语言),我们需要配置编译器的参数,不要以为仅仅配置汇编器 as 就行(在多数工具中编译器和汇编器是独立配置的)!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  注意:在 ECLIPSE 中,它把 objdump 输出文件名也定为了 .lstobjdump 实际是解析 ELF 文件的工具,与 LIST 文件本没啥关系。 在 ECLIPSE 中,通过如下配置就会默认启用命令 objdump --source --all-headers --demangle --line-numbers --wide "xxx.elf" > "xxx.lst" 来生成最终调试文件对应的 lst 文件,以此来辅助调试。
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内容介绍

  在实际开发中,汇编器 as 产生的 LST 文件基本很少使用,使用最多的是使用 objdump 工具产生的最终调试程序对应的 LST 文件。这里我们主要就介绍 objdump 产生的 LST 文件。上面说过了, objdump 输出的实际是 ELF 文件内容,详细介绍见独立博文 Linux 之二十 详解 ELF 文件。

–source、–demangle、 --line-numbers、–wide

  就是将反汇编与 C 源码混合在一起显示出来。并且尽可能的翻译成人能看懂的代码(翻译符号名、对应行号)!

–all-headers

  该命令会输出 Program Header,Sections 以及 SYMBOL TABLE 这个三部分的内容。编译工具产生的最终可执行文件是符合 ELF 规范的二进制文件,这里的输出内容其实都是 ELF 文件的内容,关于 ELF 文件,可以参考 ARM 之一 ELF 文件、镜像(Image)文件、可执行文件、对象文件 详解。

  • Program Header:这个就是 ELF 文件的程序头
    .map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
  • Sections: 这个就是从 ELF 文件中的提取的节区信息,共由 8 列组成,每列的含义说明如下:
    .map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
    • 第一列(Idx):从 0 开始的索引号
    • 第二列(Name): 节的名字
    • 第三列(Size):节的大小(字节)
    • 第四列(VMA):Virtual Memory Address 的缩写,表示该节在运行时的地址
    • 第五列(LMA):Load Memory Address 的缩写,表示该节的加载地址
    • 第六列(File off):该节在文件中的偏移
    • 第七列(Algn):对齐字节数,只能是 2 的正整数次幂,由于纯文本没办法显示幂,这里使用 ** 表示!
    • 第八列(Flags):该节的属性标志
  • SYMBOL TABLE:这个就是从 ELF 文件中的提取的符号表,由 5 列组成,每列的含义说明如下:
    .map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst
    • 第一列:符号的值,通常就是符号的物理地址
    • 第二列:这是一组符号标识,共由 7 个标识符组成,某些标识符可以是空格。
      • 第一个标识符:取值如下
        • l : Local Symbol
        • g: Global Symbol
        • u: Unique global Symbol
        • ! :其他情况
      • 第二个标识符:取值为 w 表示弱符号(Weak),否则为空格表示强符号(Strong)
      • 第三个标识符:取值为 C 表示构造函数(Constructor ),否则为空格表示普通符号
      • 第四个标识符:取值为 W 表示警告符号(Warning),否则为空格表示普通符号。警告符号的名称是一条消息,当警告符号后面的符号被引用时显示出来。
      • 第五个标识符:
        • I: 该符号是对另一个符号的间接引用
        • i: 在 reloc 处理期间计算的函数
        • :空格表示普通符号
      • 第六个标识符:
        • d: 调试符号
        • D: 动态符号
        • :空格表示普通符号
      • 第七个标识符:
        • F : 符号是函数的名称(Function )
        • f: 一个文件(file)
        • O: 一个对象(Object)
        • :空格表示普通符号
    • 第三列:符号对应的节区。如果该节是绝对的(即没有与任何节连接),则是 *ABS*,如果该节在被转储的文件中被引用,但在那里没有定义,则是 *UND*
    • 第四列:对于普通符号是对齐方式,对于其他符号则是大小
    • 第五列:符号名字

ARM

产生方式

  使用编译器 armcc 的参数 -asm 以及汇编器 armasm的参数 --list=file 来输出 lst 文件,两者分别针对 C 语言源文件和汇编源文件生效!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内容介绍

  暂无,后续有需要再补充!

IAR

产生方式

  使用编译器 iccarm 的参数 -l 以及使用汇编器 iasmarm 的参数 -L 来输出 lst 文件,两者分别针对 C 语言源文件和汇编源文件生效!
.map文件,Toolchain,toolchain,gcc,map,MDK,IAR,lst

内容介绍

  暂无,后续有需要再补充!

参考

  1. https://dzone.com/articles/creating-disassembly-listings-with-gnu-tools-and-e
  2. https://interrupt.memfault.com/blog/get-the-most-out-of-the-linker-map-file
  3. https://sourceware.org/binutils/docs-2.40/binutils.html#index-objdump

到了这里,关于编译工具链 之四 ARM-MDK、IAR、GCC 的 .MAP 文件、.LST 文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ARM交叉编译工具链 gcc-arm-none-eabi

    1,交叉编译工具链简介 (1)命令规则 交叉编译工具链的命名规则为:arch [-vendor] [-os] [-(gnu)eabi] arch – 体系架构ÿ

    2024年03月25日
    浏览(59)
  • gcc编译 与交叉编译(x86 to arm) (一)单个文件编译

    源平台: UOS_X86_64 目标平台:UOS_arm 方法:使用现成的交叉编译工具链 参考资料:交叉编译概念 ; 安装交叉编译器 ; 交叉编译入门 ( 步骤1 )去平台下载对应的工具链 https://www.linaro.org/downloads/ https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads 以上两个均可以下载,我下载

    2024年02月06日
    浏览(51)
  • 【ARM 嵌入式 编译系列 10 -- GCC 编译缩减可执行文件 elf 文件大小】

    请阅读 【ARM GCC 编译专栏导读】 上篇文章:ARM 嵌入式 编译系列 9-- GCC 编译符号表(Symbol Table)的详细介绍 下篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小 在开发过程总,总是希望编译出来的可执行文件尽量小,因为这样可以节省更多的磁盘空间

    2024年02月09日
    浏览(55)
  • 下载较老版本或最新版本的ARM Linux gcc 交叉编译工具链

    如果开发的 ARM 平台比较的多,需要多个版本的 arm gcc 交叉编译工具链,那么如何获取较新版本的 arm gcc 交叉编译工具链呢? 速度较快的,也比较新的,就到 ARM 官方网站下载 下载地址: https://developer.arm.com/downloads/-/gnu-a GNU-A Downloads 最新的下载地址: https://developer.arm.com/do

    2024年02月14日
    浏览(54)
  • KEIL MDK arm编译器 添加教程

    1.下载编译器安装文件 arm编译器6.16(适用于windows 64位)安装文件可在如下网址免费下载: arm编译器6.16(适用于Windows64位)-嵌入式文档类资源-CSDN文库 https://download.csdn.net/download/WG_IECAS/87342708 如需其他版本编译器,可到KEIL官网查找下载,快速网址: Arm Compiler downloads index h

    2023年04月08日
    浏览(59)
  • linux下使用gcc编译工具出现“命令未找到”或“没有那个文件或目录”等提示

    在linux系统中使用gcc编译工具对C程序进行编译时,报错显示“gcc命令未找到”或“没有那个文件或目录”,而此时你确定已经安装了gcc编译工具,这大概率是因为系统未能找到gcc命令的安装位置所导致的,需要将gcc的安装路径添加到PATH环境变量中,解决方法如下:        

    2024年02月08日
    浏览(57)
  • arm gcc编译选项

    arm:架构是arm none:不是特定的供应商提供的 eabi:eabi:嵌入式应用二进制接口(Embedded Application Binary Interface) 因为名称里没有“linux”类似的字样,说明不支持操作系统。 libc 是ANSI C 语言函数库,包含了 C 语言最基本的库函数。这个库可以根据头文件划分为 15 个部分,其

    2024年02月03日
    浏览(41)
  • 【ARM 嵌入式 编译系列 2.1 -- GCC 编译参数学习】

    请阅读 【ARM GCC 编译专栏导读】 上篇文章:ARM 嵌入式 编译系列 2 – GCC 编译过程介绍 下篇文章:ARM 嵌入式 C 入门及渐进 3 – GCC attribute ((weak)) 弱符号使用 上篇文章 ARM 嵌入式 编译系列 2 – GCC 编译过程介绍 已经介绍过了具体的编译流程,本篇文章主要介绍变过程中常见的

    2024年02月13日
    浏览(44)
  • Ubuntu上搭建ARM Linux GCC交叉编译环境

    在Ubuntu操作系统上搭建ARM Linux GCC交叉编译环境是为了能够在x86架构的主机上编译运行适用于ARM架构的程序。本文将介绍详细的步骤以及相应的源代码。 安装必要的软件包 首先,我们需要安装一些必要的软件包,包括GCC、GNU Binutils和GDB。打开终端,运行以下命令来安装这些软

    2024年02月02日
    浏览(54)
  • 【ARM 嵌入式 编译系列 3.5 -- gcc 链接参数介绍】

    请阅读 【嵌入式开发学习必备专栏 之 ARM GCC 编译专栏】 上篇文章【ARM 嵌入式 编译系列 3.4 – 查看所依赖库文件的路径 详细介绍】一直在提 链接参数 ,那么链接参数有哪些,它们又有什么作用呢? 如前一篇文章中的的链接参数到底是什么意思呢? -L : 指定了 链接库的路径

    2024年01月17日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包