【ARM 嵌入式 编译系列 6 -- GCC objcopy, objdump, readelf, nm 介绍】

文章目录

    • GCC objcopy 简介
      • objcopy 常用参数
    • GCC objdump 简介
    • GCC readelf 介绍
    • GCC nm 介绍

GCC objcopy 简介

objcopy 是 GNU二进制工具集(binutils)的一部分,主要用于复制和转换目标文件。

在ARM GCC中,arm-none-eabi-objcopy通常用于从链接后的ELF格式文件中提取出二进制文件或其他格式的内容,这对于嵌入式开发特别有用,因为这样的文件可以直接烧写到微控制器的闪存中。

objcopy 常用参数

下面是一些常用的参数:

-O:表示输出文件的格式。常见的格式有:binary(二进制文件)、ihex(Intel HEX文件)、srec(Motorola SREC文件)、elf32-littlearm(小端字节序的ELF文件)等;

-S(或 --strip-all):去除所有的符号信息和重定位信息,使得输出文件更小;

-j:仅复制指定的section。例如,-j .text 表示只复制.text段的内容;
-R (或--remove-section),输出文件中不要重定位信息和符号信息,缩小了文件尺寸。

下面是一个使用示例:

arm-none-eabi-objcopy -O binary -S -j .text -j .data myprogram.elf myprogram.bin

这行命令的意思是:从myprogram.elf中提取出.text段和.data段的内容,并将它们转换为二进制文件myprogram.bin。同时,所有的符号信息和重定位信息都会被去除。

注意:在使用arm-none-eabi-objcopy时,你应当确保输入的ELF文件已经正确链接。否则,你可能会得到一个无法在硬件上运行的二进制文件,此外,使用objcopy不能够改变大/小端。

$ arm-linux-objcopy -O binary -R .note -R .comment -S boot.elf boot.bin

GCC objdump 简介

GCC objdump 用于显示关于目标文件的信息。这些信息包括文件的头部信息、节区内容、符号表、重定位入口点等。使用 objdump 可以对二进制文件进行深入分析,这对于调试和理解程序的工作原理非常有用。

Objdump 支持大量的命令行选项,可以用来控制显示的信息的数量和类型。以下是一些主要的选项:

-a, --archive-header: 显示存档的头部信息;
-d, --disassemble: 反汇编代码段;
-h, --section-headers: 显示节区头部;
-r, --reloc: 显示重定位入口点;
-s, --full-contents: 显示所有节区的完全内容;
-t, --syms: 显示符号表。

一个简单的使用例子如下,假设我们编译出一个名为 soc.o 的 文件:

arm-none-eabi-objdump -h soc.o

soc.o:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000000  00000000  00000000  00000034  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000034  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000034  2**0
                  ALLOC
  3 .text.__NVIC_SetPriority 00000054  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .text.SCB_EnableICache 0000004c  00000000  00000000  00000088  2**2
....

上面的命令显示了 soc 文件中各个节区的信息,包括名称、大小、虚拟地址、加载地址和文件偏移量等。

另一个例子是反汇编代码段

arm-none-eabi-objdump -d soc.o

soc.o:     file format elf32-littlearm


Disassembly of section .text.__NVIC_SetPriority:

00000000 <__NVIC_SetPriority>:
   0:   b480            push    {r7}
   2:   b083            sub     sp, #12
   4:   af00            add     r7, sp, #0
   6:   4603            mov     r3, r0
   8:   6039            str     r1, [r7, #0]
   a:   80fb            strh    r3, [r7, #6]
   c:   f9b7 3006       ldrsh.w r3, [r7, #6]
  10:   2b00            cmp     r3, #0
  12:   db0a            blt.n   2a <__NVIC_SetPriority+0x2a>
  14:   683b            ldr     r3, [r7, #0]

上面的命令显示了 soc 文件中.text. 段的反汇编代码。

GCC readelf 介绍

readelf 是一个用于显示 ELF 格式文件信息的命令行工具, objdump 类似,readelf 也可以显示文件的头部信息、节区内容、符号表、重定位入口点等。但是,readelf 是专门针对 ELF 格式文件的工具,因此它可以显示更加详细的信息。

以下是一些主要的 readelf 选项:
-a, --all: 显示所有信息;
-h, --file-header: 显示 ELF 头部;
-l, --program-headers, --segments: 显示程序头部或段;
-S, --section-headers, --sections: 显示节区头部;
-s, --syms, --symbols: 显示符号表;
-r, --relocs: 显示重定位入口点。

一个简单的使用例子如下,假设我们有一个名为 soc.o 的文件:

arm-none-eabi-readelf -h soc.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          25652 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         61
  Section header string table index: 60

上面的命令显示了 soc.o 文件的头部信息。

另一个例子是显示节区头部:

arm-none-eabi-readelf -S soc.o
There are 61 section headers, starting at offset 0x6434:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  2
  [ 2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  1
  [ 3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  1
  [ 4] .text.__NVIC[...] PROGBITS        00000000 000034 000054 00  AX  0   0  4
  [ 5] .text.SCB_En[...] PROGBITS        00000000 000088 00004c 00  AX  0   0  4
  [ 6] .text.SCB_En[...] PROGBITS        00000000 0000d4 000088 00  AX  0   0  4
  [ 7] .text.SysTic[...] PROGBITS        00000000 00015c 000044 00  AX  0   0  4
  [ 8] .rel.text.Sy[...] REL             00000000 0047b8 000008 08   I 58   7  4
  [ 9] .text.crg_key_en  PROGBITS        00000000 0001a0 000028 00  AX  0   0  4
  [10] .text.crg_key_dis PROGBITS        00000000 0001c8 000028 00  AX  0   0  4
  [11] .text.unlock[...] PROGBITS        00000000 0001f0 000028 00  AX  0   0  4
  [12] .text.lock_c[...] PROGBITS        00000000 000218 000024 00  AX  0   0  4
  [13] .text.reboot      PROGBITS        00000000 00023c 000030 00  AX  0   0  4
  [14] .rodata.name      PROGBITS        00000000 00026c 00001e 00   A  0   0  4
  [15] FSymTab           PROGBITS        00000000 00028c 00000c 00   A  0   0  4
  [16] .relFSymTab       REL             00000000 0047c0 000018 08   I 58  15  4
  [17] .text.get_ref_clk PROGBITS        00000000 000298 000078 00  AX  0   0  4

上面的命令显示了 soc.o 文件中的节区头部信息。

GCC nm 介绍

nm 用于显示目标文件的符号表信息的命令行工具。符号表包含了程序中函数和变量的符号信息,这对于定位问题和理解程序的工作原理非常有用。

以下是一些主要的 nm 选项:

-a, --debug-syms: 显示调试符号;
-g, --external-only: 只显示外部符号;
-n, --numeric-sort: 按照地址排序符号;
-r, --reverse-sort: 反向排序符号;
-S, --print-size: 显示符号的大小;
-u, --undefined-only: 只显示未定义的符号。

一个简单的使用例子如下,假设我们有一个名为 soc.o 文件:

arm-none-eabi-nm -u soc.o
         U __bss_end
         U __bss_start
         U clock_framework_init
         U console_uart_init
         U _edata
         U enable_syscnt
         U _estack
         U _etext
         U _heap_end
         U _heap_start
         U power_domain_framework_init
         U reset_framework_init
         U rt_components_board_init
         U rt_console_set_device
         U rt_hw_interrupt_init
         U rt_interrupt_enter
         U rt_interrupt_leave
         U rt_kprintf
         U rt_system_heap_init
         U rt_tick_increase
         U _sdata
         U _sstack
         U _stext

上面的命令只显示soc.o文件未定义的符号 。每行的输出包含了符号的类型和名字。类型是一个字符,指示了符号的类型和属性。

你可能感兴趣的:(#,ARM,GCC,编译系列介绍,objcopy,objdump,readelf,nm)