bin、hex、exe、elf文件类型到底有何区别?如何解读hex文件和elf文件?...相关内容都在这里!

快速学习嵌入式开发其他基础知识?>>>>>>>>> 返回专栏总目录 《嵌入式工程师自我修养/C语言》<<<<<<<<<

Tip📌:鼠标悬停双虚线关键词/句,可获得更详细的描述

一、常见文件类型之:bin、hex、elf、exe

1.1 bin、hex、exe、elf文件类型到底有何区别?

  在嵌入式软件开发中,不同的文件格式承载着不同的信息和用途。了解这些文件格式的差异对于开发人员来说是非常重要的,特别是对于那些处理固件编写、调试和程序部署的开发者。以下是几种常见文件格式(bin、hex、elf、exe)的详细描述和它们之间的主要区别:

类型定义用途特点
BIN二进制格式文件,直接存储二进制数据,没有结构或头信息,仅包含裸数据。常用于嵌入式系统,用于存储固件镜像,直接烧录到闪存。大小较小,只包含代码和数据,但缺少调试信息,调试困难。
HEX十六进制格式文件,以文本形式表示的二进制数据文件,使用ASCII字符。用于嵌入式系统固件的存储和传输,易于阅读和编辑。通常比BIN文件大,因ASCII字符表示,可包含地址信息,方便定位烧录。
ELF可执行链接格式,通用的标准文件格式。用于嵌入式Linux和UNIX-like系统,适用于可执行程序和调试。灵活可扩展,包含代码和数据以及调试和配置信息,支持静态和动态链接。
EXEWindows系统中的可执行文件格式。存储Windows环境下的可执行程序代码。为Windows设计,包含运行程序所需的所有信息,不适用于嵌入式系统。

  综上,这几种文件有以下几方面的区别:
a. 适用环境不同:
  BIN和HEX文件通常用于嵌入式系统中固件的烧录;ELF文件广泛用于UNIX-like系统的可执行文件和调试;EXE文件是Windows环境下的可执行文件。
b. 内容和结构不同:
  BIN是裸二进制文件,HEX是文本形式的二进制数据,ELF文件具有高度的灵活性,支持复杂的程序结构和调试信息,而EXE是Windows可执行文件格式,包含了运行所需的全部信息。
c. 调试信息不同:
  BIN文件和HEX文件通常不包含调试信息;而EXE和ELF文件可以包含丰富的调试信息,有助于开发和调试过程。

1.2 如何读懂一份hex文件?(hex文件格式详细解读)

  十六进制(HEX)文件格式通常用于在编程过程中传输二进制信息。这种文件格式常见于微控制器和小型嵌入式系统的固件更新中。Intel HEX是其中最常见的一种HEX文件格式,我们将以此为例来解释。

Tip📌:Intel HEX文件格式是一种以文本形式存储二进制数据的文件格式,它的每一行代表了在特定内存地址上的数据记录。这种格式使得数据易于人类阅读和机器解析,并且可以被许多程序编程工具所接受。

  一个标准的Intel HEX文件由多行构成,每行代表一个数据记录(Record)。下面是一个例子:

:020000040000FA
:10010000214601360121470136007EFE09D2190140
:100110002146017E17C20001FF5F16002148011928
:0C012000FFFFFFFFFFFFFFFF0200000000FA
:00000001FF

1.2.1 每行的结构

每一行数据记录有以下顺序和结构:

字段说明
开始码
(Start code)
一个冒号(:),表明这是一行新的记录。
字节计数
(Byte count)
两个十六进制数字,表示这一行中数据字段的字节数,不包括本身这个字段和其他字段
(通常为10或者20,分别表示这行有16个字节或者32个字节的数据)。
地址
(Address)
接着是四个十六进制数字,表示数据将要被写入的起始地址。
记录类型
(Record type)
两个十六进制数字,00到05之间,定义了数据记录的类型。
00代表数据记录;01代表文件结束记录;02代表扩展段地址记录;04代表扩展线性地址记录;05代表开始线性地址记录。
数据
(Data)
数据本身,长度由字节计数字段确定,可以是任意数量的字节(最多255个)。
校验和
(Checksum)
两个十六进制数字,是前面所有字节的反码加1(即二进制求和后取反加1)。

1.2.2 记录类型(Record type)

Intel HEX文件中最常见的几种记录类型如下:

记录类型代码记录类型描述
00数据记录(Data Record):包含了在一个指定地址开始的二进制数据。
01文件结束记录(End Of File Record):文件的结尾,表明没有更多的记录。
02扩展段地址记录(Extended Segment Address Record):用来标识接下来的数据记录的段地址。
04扩展线性地址记录(Extended Linear Address Record):用来标识接下来的数据记录的高位地址。
05开始线性地址记录(Start Linear Address Record):定义了程序的起始执行地址。

1.2.3 校验和的计算

  校验和的计算是对一行中的所有字节进行二进制求和(不包括开始冒号和校验和自身),然后取反加1。简化这种计算逻辑后可以按照下面的方法计算校验和:

  1. 将字节计数、地址、记录类型、和数据字段的所有值相加。
  2. 取这个总和的最低字节。
  3. 用0xFF减去这个最低字节,再加1。

  这样得到的结果就是校验和。校验和的目的是为了确保数据的完整性,在接收端可以通过重新计算校验和来确认数据是否在传输过程中被篡改。例如,我们计算上面第一行数据:020000040000FA的校验和:

02 + 00 + 00 + 04 + 00 + 00 = 06
0xFF - 0x06 + 0x01 = 0xFA

1.2.4 实例解析

以上述示例中的第二行为例:

:10010000214601360121470136007EFE09D2190140
  • : 是开始码。
  • 10 说明接下来有16个数据字节。
  • 0100 是这一行数据的起始地址。
  • 00 是数据记录类型,表示这是一个数据记录。
  • 接下来的214601360121470136007EFE09D21901是数据本身,共16个字节。
  • 最后的40是校验和。

Tip📌:hex文件每行记录数字很多,还是很难阅读的,博主工作中使用vscode比较多,推荐个vscode中的插件,每行记录的结构有不同的色彩区分,阅读起来相对友好一些:

在这里插入图片描述

1.3 如何实现bin文件和hex文件的相互转换?

1.3.1 linux环境下

  在Linux环境下,可以使用一些工具和命令行程序来实现二进制文件(bin)和十六进制文件(hex)之间的相互转换。下面是使用objcopy工具来实现这两种文件格式之间转换的方法,objcopy是GNU二进制工具集(Binutils)的一部分,通常在大多数Linux发行版中可用。

Bin文件 ------> Hex文件

objcopy -I binary -O ihex input_file.bin output_file.hex
  • -I 指定输入文件的格式,这里是binary
  • -O 指定输出文件的格式,这里是ihex,即Intel Hex格式。
  • input_file.bin 是要转换的二进制文件。
  • output_file.hex 是转换后生成的十六进制文件。

Hex文件 ------> Bin文件

objcopy -I ihex -O binary input_file.hex output_file.bin
  • -I 指定输入文件的格式,这里是ihex
  • -O 指定输出文件的格式,这里是binary
  • input_file.hex 是要转换的十六进制文件。
  • output_file.bin 是转换后生成的二进制文件。

Tips📌:

  • 在使用这些命令之前,需要确保系统中已经安装了GNU二进制工具集(Binutils)。如果没有安装,可以使用sudo apt-get install binutils来安装。
  • 这些命令不需要特殊的运行权限,但是需要对输入文件有读取权限,同时对输出文件的目录有写入权限。
  • 使用objcopy命令将bin文件转换为hex文件时,直接通过objcopy命令参数指定起始地址的功能是不支持的。objcopy工具主要用于格式转换,而不直接提供在转换过程中设置起始地址的选项。

1.3.2 linux环境下bin转hex如何指定起始地址?

  如果想要bin文件转hex文件的时候指定hex文件的起始地址,可以通过其他方式间接实现。一种常见的方法是先将bin文件转换为其他格式(如ELF),在这个过程中指定起始地址,然后再从该中间格式转换为hex格式。下面是一个示例流程:

步骤1:Bin转ELF,指定起始地址

ld --oformat=elf32-littlearm -Ttext=起始地址(如0x08000000) -o output_file.elf input_file.bin
  • --oformat=elf32-littlearm 指定输出格式为ELF,具体的格式根据目标架构而定。
  • -Ttext=起始地址 指定section的起始地址。
  • output_file.elf 是转换后的ELF文件。
  • input_file.bin 是原始的二进制文件。

步骤2:ELF转Hex

objcopy -O ihex output_file.elf output_file.hex

output_file.elf是上一步生成的ELF文件,而output_file.hex则是最终的hex文件。

Tips📌:

  • 这个方法需要ldobjcopy工具,这两个工具都属于GNU Binutils工具集,通常在大多数Linux系统中都是预安装的。
  • 指定起始地址时,需要确保它适用于目标平台和应用场景。

1.3.2 Windows环境下

  windows环境下直接推荐给大家两个工具,我工作中用起来还是比较顺手的:第一个工具比较简洁,但功能有限,主要就是用来完成bin和hex文件的转换,hex和bin互转工具(点击获取)
在这里插入图片描述
  第二个工具极其强大并高端,它甚至能完成文件的签名校验等功能,格式转换就更不在话下了:一个强大的hex工具(点击获取)

二、readelf常见用法解读

2.1 elf文件及其组成结构

  为了更好的了解elf文件的组成结构,为后续readelf的学习做准备,首先我们来自己制作一个elf文件。需要你有一台可以运行Linux操作系统的计算机或虚拟机,并且在Linux环境下已经安装了GCC编译器和gcc-arm-linux-gnueabi交叉编译器,Ubuntu环境下交叉编译器可以用下面的指令安装:apt-get install gcc-arm-linux-gnueabi gcc

先编写一个很简单的c文件:

/********* File: sub.h *********/
int add(int a, int b);
int sub(int a, int b);

/********* File: sub.c *********/
int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

/********* File: main.c *********/
#include <stdio.h>
#include "sub.h"

int global_val = 1;
int uninit_val;

int main(void)
{
    int a, b;
    static int local_val = 2;
    static int uninit_local_val;
    a = add(2, 3);
    b = sub(5, 4);
    printf("a = %d\n", a);
    printf("b = %d\n", b);
    return 0;
}

  如果我们想让上面的程序在ARM平台上运行,则要使用ARM交叉编译器将C源程序编译生成ARM格式的二进制可执行文件,执行编译指令arm-linux-gnueabi-gcc -o a.out main.c sub.c。将生成的二进制文件a.out复制到ARM平台上就可以直接运行了。不考虑这个编译生成的过程,先来研究下在这个可执行文件。

——section header、ELF header以及节头表的概念

  一个可执行文件通常由不同的段(section)构成:代码段、数据段、BSS段、只读数据段等。每个section会有一个section header来描述这个段的段名、段的类型、段的起始地址、段的偏移和段的大小等信息,将这些section headers集中放到一起,就是节头表(section header table)。

  此外,可执行文件还会有一个文件头ELF header,用来描述文件类型、要运行的处理器平台、入口地址等信息。当程序运行时,加载器会根据此文件头来获取可执行文件的一些信息。

Tips📌:section header table自身也是以一个section的形式存储在可执行文件中的。

——温故常说的代码段、数据段、BSS段

  C程序中定义的函数、变量、未初始化的全局变量经过编译后会放置在不同的段中:

  • 函数翻译成二进制指令放在代码段中;
  • 初始化的全局变量和静态局部变量放在数据段中;
  • 未初始化的全局变量和静态变量放在BSS段中,但是因为它们未初始化,默认值全部是0,其实没有必要再单独开辟空间存储,为了节省存储空间,所以在可执行文件中BSS段是不占用空间的。但是BSS段的大小、起始地址和各个变量的地址信息会分别保存在节头表和符号表.symtab里,当程序运行时,加载器会根据这些信息在内存中紧挨着数据段的后面为BSS段开辟一片存储空间,为各个变量分配存储单元。

  程序编译的过程实际上就是将程序代码中定义的函数、变量等加以分类,分别放置在可执行文件的代码段、数据段和BSS段中。程序中定义的一些字符串、printf函数打印的字符串常量则放置在只读数据段.rodata中。如果程序在编译时设置为debug模式,则可执行文件中还会有一个专门的.debug section,用来保存可执行文件中每一条二进制指令对应的源码位置信息。根据这些信息,GDB调试器就可以支持源码级的单步调试,否则你单步执行的都是二进制指令,可读性不高,不方便调试。在最后环节,编译器还会在可执行文件中添加一些其他section,如.init section,这些代码来自C语言运行库的一些汇编代码,用来初始化C程序运行所依赖的环境,如内存堆栈的初始化等。

2.2 readelf常见用法详解

  readelf是GNU Binutils包中的一个工具(通常各个linux发行版中都会默认包含这个工具包),用于展示ELF文件的结构信息,包括段头表、节头表、符号表等。实际上,不必大费周章的搜它的用法,readelf -H指令将详细展示各个选项参数的作用。

Tips📌:除了-v和-H之外,其它的选项必须有一个指定参数(即选项后面要加一个待读取信息的文件),-v用来显示readelf的版本信息。

我们这里将列举最常用的几个参数,如下所示:
  如果对程序的编译链接过程不是很清楚的,这里可以先简单认识下前两个选项-h-S即可,阅读《程序的编译、链接过程分析(简洁浓缩版)!》后,再回过头来看其他选项的作用会容易理解一些,不然可能还是不清楚每个选项罗列出来的信息具体有什么用。

在这里插入图片描述

  1. 选项 -h(elf header)
      主要用来获取可执行文件的头部信息,主要包括可执行文件运行的平台、软件版本、程序入口地址, 以及programheaders、section header等信息。通过文件的头部信息,我们可以知道在a.out可执行文件里一共有多少个section headers。
    在这里插入图片描述

  2. 选项 -S(section headers)大写的S
      通过上面-h选项我们看到a.out中总共有29个section header,将这些section header集中放到一起,就是section header table-节头表。可以使用readelf-S命令来查看一个可执行文件的节头表。section header table里的各个section header用来描述各个section的名称、类型、起始地址、大小等信息。
    在这里插入图片描述

  3. 选项 -l(program headers)
      用于显示ELF文件中的程序段(segments)信息。这些信息包括每个段的类型(如LOAD, DYNAMIC等)、地址、偏移、大小等,这对于理解程序如何被操作系统加载到内存中非常有用。建议先阅读《编译链接(待更新)》
    在这里插入图片描述

  4. 选项 -s(symbols)
      可以列出ELF文件中的所有符号,包括函数、变量等。这些符号信息包括它们的名称、位置、大小、类型(如函数、对象等),对于调试程序和理解程序结构非常重要。

westen@westen-ubuntu:/mnt/hgfs/code/build$ readelf -s a.out 

Symbol table '.dynsym' contains 5 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     2: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.4 (2)
     3: 00000000     0 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.4 (2)
     4: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.4 (2)

Symbol table '.symtab' contains 112 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00010154     0 SECTION LOCAL  DEFAULT    1 
     2: 00010168     0 SECTION LOCAL  DEFAULT    2 
     3: 00010188     0 SECTION LOCAL  DEFAULT    3 
     4: 000101ac     0 SECTION LOCAL  DEFAULT    4 
     5: 000101d8     0 SECTION LOCAL  DEFAULT    5 
     6: 00010228     0 SECTION LOCAL  DEFAULT    6 
     7: 0001026c     0 SECTION LOCAL  DEFAULT    7 
     8: 00010278     0 SECTION LOCAL  DEFAULT    8 
     9: 00010298     0 SECTION LOCAL  DEFAULT    9 
    10: 000102a0     0 SECTION LOCAL  DEFAULT   10 
    11: 000102c0     0 SECTION LOCAL  DEFAULT   11 
    12: 000102cc     0 SECTION LOCAL  DEFAULT   12 
    13: 00010310     0 SECTION LOCAL  DEFAULT   13 
    14: 00010520     0 SECTION LOCAL  DEFAULT   14 
    15: 00010528     0 SECTION LOCAL  DEFAULT   15 
    16: 0001053c     0 SECTION LOCAL  DEFAULT   16 
    17: 00010544     0 SECTION LOCAL  DEFAULT   17 
    18: 00020f10     0 SECTION LOCAL  DEFAULT   18 
    19: 00020f14     0 SECTION LOCAL  DEFAULT   19 
    20: 00020f18     0 SECTION LOCAL  DEFAULT   20 
    21: 00021000     0 SECTION LOCAL  DEFAULT   21 
    22: 00021020     0 SECTION LOCAL  DEFAULT   22 
    23: 00021030     0 SECTION LOCAL  DEFAULT   23 
    24: 00000000     0 SECTION LOCAL  DEFAULT   24 
    25: 00000000     0 SECTION LOCAL  DEFAULT   25 
    26: 00000000     0 FILE    LOCAL  DEFAULT  ABS /usr/lib/gcc-cross/arm-li
    27: 00010168     0 NOTYPE  LOCAL  DEFAULT    2 $d
    28: 00010310     0 NOTYPE  LOCAL  DEFAULT   13 $a
    29: 0001053c     0 NOTYPE  LOCAL  DEFAULT   16 $d
    30: 00010340     0 NOTYPE  LOCAL  DEFAULT   13 $d
    31: 00010528     0 NOTYPE  LOCAL  DEFAULT   15 $d
    32: 00021020     0 NOTYPE  LOCAL  DEFAULT   22 $d
    33: 00000000     0 FILE    LOCAL  DEFAULT  ABS /usr/lib/gcc-cross/arm-li
    34: 0001034c     0 NOTYPE  LOCAL  DEFAULT   13 $a
    35: 0001034c     0 FUNC    LOCAL  DEFAULT   13 call_weak_fn
    36: 00010368     0 NOTYPE  LOCAL  DEFAULT   13 $d
    37: 000102c0     0 NOTYPE  LOCAL  DEFAULT   11 $a
    38: 00010520     0 NOTYPE  LOCAL  DEFAULT   14 $a
    39: 00000000     0 FILE    LOCAL  DEFAULT  ABS /usr/lib/gcc-cross/arm-li
    40: 000102c8     0 NOTYPE  LOCAL  DEFAULT   11 $a
    41: 00010524     0 NOTYPE  LOCAL  DEFAULT   14 $a
    42: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    43: 00010370     0 NOTYPE  LOCAL  DEFAULT   13 $a
    44: 00010370     0 FUNC    LOCAL  DEFAULT   13 deregister_tm_clones
    45: 00010390     0 NOTYPE  LOCAL  DEFAULT   13 $d
    46: 0001039c     0 NOTYPE  LOCAL  DEFAULT   13 $a
    47: 0001039c     0 FUNC    LOCAL  DEFAULT   13 register_tm_clones
    48: 000103c8     0 NOTYPE  LOCAL  DEFAULT   13 $d
    49: 00021024     0 NOTYPE  LOCAL  DEFAULT   22 $d
    50: 000103d4     0 NOTYPE  LOCAL  DEFAULT   13 $a
    51: 000103d4     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux
    52: 000103f8     0 NOTYPE  LOCAL  DEFAULT   13 $d
    53: 00021030     1 OBJECT  LOCAL  DEFAULT   23 completed.9929
    54: 00020f14     0 NOTYPE  LOCAL  DEFAULT   19 $d
    55: 00020f14     0 OBJECT  LOCAL  DEFAULT   19 __do_global_dtors_aux_fin
    56: 000103fc     0 NOTYPE  LOCAL  DEFAULT   13 $a
    57: 000103fc     0 FUNC    LOCAL  DEFAULT   13 frame_dummy
    58: 00020f10     0 NOTYPE  LOCAL  DEFAULT   18 $d
    59: 00020f10     0 OBJECT  LOCAL  DEFAULT   18 __frame_dummy_init_array_
    60: 00021030     0 NOTYPE  LOCAL  DEFAULT   23 $d
    61: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
    62: 00021028     0 NOTYPE  LOCAL  DEFAULT   22 $d
    63: 0001052c     0 NOTYPE  LOCAL  DEFAULT   15 $d
    64: 00010400     0 NOTYPE  LOCAL  DEFAULT   13 $a
    65: 00010454     0 NOTYPE  LOCAL  DEFAULT   13 $d
    66: 00021034     4 OBJECT  LOCAL  DEFAULT   23 uninit_local_val.4621
    67: 00021034     0 NOTYPE  LOCAL  DEFAULT   23 $d
    68: 0002102c     4 OBJECT  LOCAL  DEFAULT   22 local_val.4620
    69: 00000000     0 FILE    LOCAL  DEFAULT  ABS sub.c
    70: 0001045c     0 NOTYPE  LOCAL  DEFAULT   13 $a
    71: 00000000     0 FILE    LOCAL  DEFAULT  ABS elf-init.oS
    72: 000104bc     0 NOTYPE  LOCAL  DEFAULT   13 $a
    73: 00010514     0 NOTYPE  LOCAL  DEFAULT   13 $d
    74: 0001051c     0 NOTYPE  LOCAL  DEFAULT   13 $a
    75: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    76: 00010544     0 NOTYPE  LOCAL  DEFAULT   17 $d
    77: 00010544     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__
    78: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
    79: 00020f14     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end
    80: 00020f18     0 OBJECT  LOCAL  DEFAULT   20 _DYNAMIC
    81: 00020f10     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start
    82: 00021000     0 OBJECT  LOCAL  DEFAULT   21 _GLOBAL_OFFSET_TABLE_
    83: 000102cc     0 NOTYPE  LOCAL  DEFAULT   12 $a
    84: 000102dc     0 NOTYPE  LOCAL  DEFAULT   12 $d
    85: 000102e0     0 NOTYPE  LOCAL  DEFAULT   12 $a
    86: 0001051c     4 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    87: 00021038     4 OBJECT  GLOBAL DEFAULT   23 uninit_val
    88: 00021020     0 NOTYPE  WEAK   DEFAULT   22 data_start
    89: 0001045c    48 FUNC    GLOBAL DEFAULT   13 add
    90: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.4
    91: 00021030     0 NOTYPE  GLOBAL DEFAULT   23 __bss_start__
    92: 0002103c     0 NOTYPE  GLOBAL DEFAULT   23 _bss_end__
    93: 00021030     0 NOTYPE  GLOBAL DEFAULT   22 _edata
    94: 00010520     0 FUNC    GLOBAL DEFAULT   14 _fini
    95: 0002103c     0 NOTYPE  GLOBAL DEFAULT   23 __bss_end__
    96: 00021028     4 OBJECT  GLOBAL DEFAULT   22 global_val
    97: 00021020     0 NOTYPE  GLOBAL DEFAULT   22 __data_start
    98: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    99: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
   100: 00021024     0 OBJECT  GLOBAL HIDDEN    22 __dso_handle
   101: 00010528     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
   102: 000104bc    96 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
   103: 0002103c     0 NOTYPE  GLOBAL DEFAULT   23 _end
   104: 00010310     0 FUNC    GLOBAL DEFAULT   13 _start
   105: 0002103c     0 NOTYPE  GLOBAL DEFAULT   23 __end__
   106: 00021030     0 NOTYPE  GLOBAL DEFAULT   23 __bss_start
   107: 00010400    92 FUNC    GLOBAL DEFAULT   13 main
   108: 00021030     0 OBJECT  GLOBAL HIDDEN    22 __TMC_END__
   109: 0001048c    48 FUNC    GLOBAL DEFAULT   13 sub
   110: 00000000     0 FUNC    GLOBAL DEFAULT  UND abort@@GLIBC_2.4
   111: 000102c0     0 FUNC    GLOBAL DEFAULT   11 _init
  1. 选项 -r(relocs)
      用于显示ELF文件中的重定位表信息。重定位表包含了程序在运行时需要修改的地址信息,这对于理解动态链接和地址修正过程至关重要。
    在这里插入图片描述

  2. 选项 -d(dynamic)
      可以查看ELF文件的动态段信息,这对于动态链接的ELF文件(如共享库)特别有用。它显示了动态链接器需要的信息,如所需的共享库、动态符号表等。
    在这里插入图片描述

  3. 选项 -A(arch-specific)
      显示CPU构架信息,这个其实也是不常用的,偶尔用来看一下enum类型。
    在这里插入图片描述

  4. 选项-x, hex-dump=<number or name>
      以16进制方式显示指定段内内容,通过-x选项后跟节(section)名称或者索引号,可以将指定节的内容以十六进制形式转储出来。这对于直接查看节中的原始数据非常有用,特别是在分析程序行为或调试时。
    在这里插入图片描述

  再次提醒,如果对程序的编译链接过程不是很清楚的,建议阅读《程序的编译、链接过程分析(简洁浓缩版)!》后,再回过头来看这些选项的作用,不然可能还是不清楚每个选项罗列出来的信息具体有什么用。

>>>>>>>>> 返回专栏总目录 《嵌入式工程师自我修养/C语言》<<<<<<<<<

  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

车载系统攻城狮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值