文章目录
- 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.osoc.o: file format elf32-littlearmSections:
Idx Name Size VMA LMA File off Algn0 .text 00000000 00000000 00000000 00000034 2**1CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data 00000000 00000000 00000000 00000034 2**0CONTENTS, ALLOC, LOAD, DATA2 .bss 00000000 00000000 00000000 00000034 2**0ALLOC3 .text.__NVIC_SetPriority 00000054 00000000 00000000 00000034 2**2CONTENTS, ALLOC, LOAD, READONLY, CODE4 .text.SCB_EnableICache 0000004c 00000000 00000000 00000088 2**2
....
上面的命令显示了 soc 文件中各个节区的信息,包括名称、大小、虚拟地址、加载地址和文件偏移量等。
另一个例子是反汇编代码段:
arm-none-eabi-objdump -d soc.osoc.o: file format elf32-littlearmDisassembly of section .text.__NVIC_SetPriority:00000000 <__NVIC_SetPriority>:0: b480 push {r7}2: b083 sub sp, #124: af00 add r7, sp, #06: 4603 mov r3, r08: 6039 str r1, [r7, #0]a: 80fb strh r3, [r7, #6]c: f9b7 3006 ldrsh.w r3, [r7, #6]10: 2b00 cmp r3, #012: 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 00Class: ELF32Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: REL (Relocatable file)Machine: ARMVersion: 0x1Entry point address: 0x0Start of program headers: 0 (bytes into file)Start of section headers: 25652 (bytes into file)Flags: 0x5000000, Version5 EABISize of this header: 52 (bytes)Size of program headers: 0 (bytes)Number of program headers: 0Size of section headers: 40 (bytes)Number of section headers: 61Section 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.oU __bss_endU __bss_startU clock_framework_initU console_uart_initU _edataU enable_syscntU _estackU _etextU _heap_endU _heap_startU power_domain_framework_initU reset_framework_initU rt_components_board_initU rt_console_set_deviceU rt_hw_interrupt_initU rt_interrupt_enterU rt_interrupt_leaveU rt_kprintfU rt_system_heap_initU rt_tick_increaseU _sdataU _sstackU _stext
上面的命令只显示soc.o文件未定义的符号 。每行的输出包含了符号的类型和名字。类型是一个字符,指示了符号的类型和属性。