以下内容源于网络资源的学习与整理,如有侵权请告知删除。
参考内容
(1)objcopy命令介绍_weixin_34236497的博客-CSDN博客
(2)GCC 各工具简介_bert_qing的博客-CSDN博客
(3)linux下反汇编命令_linux反汇编_烫手的热山药的博客-CSDN博客
(4)man手册
(5)目标文件格式分析工具: ar,nm,objdump,objcopy,readelf_51CTO博客_目标文件的格式
(6)objcopy命令_Linux objcopy命令使用详解:实现目标文件的格式转换
(7)binutils工具集 - 简书
在GCC编译器编译C/C++程序中提到,利用gcc命令并配合一些选项参数,可以实现分步编译。
gcc命令会根据这些选项参数,调用特定的工具来完成对应的步骤。
- 添加选项-E表示预处理操作,则gcc会调用cpp这个预处理工具;
- 添加选项-S表示编译,则gcc会调用ccl这个编译工具;
- 添加选项-c选项表示汇编,则gcc会调用as这个汇编工具;
- 如果gcc命令参数是.o形式的文件,则调用ld这个链接工具进行链接操作。
除了上面提到的工具,gnu工具链还包括其他工具,比如ar、gdb、nm、readelf、string、strip等工具,如下所示:
xjh@ubuntu:/usr/local/arm/arm-2009q3/bin$ ls arm-linux-*
arm-linux-addr2line arm-linux-c++ arm-linux-g++ arm-linux-gcov arm-linux-gprof arm-linux-objcopy arm-linux-readelf arm-linux-strings
arm-linux-ar arm-linux-c++filt arm-linux-gcc arm-linux-gdb arm-linux-ld arm-linux-objdump arm-linux-size arm-linux-strip
arm-linux-as arm-linux-cpp arm-linux-gcc-4.4.1 arm-linux-gdbtui arm-linux-nm arm-linux-ranlib arm-linux-sprite
xjh@ubuntu:/usr/local/arm/arm-2009q3/bin$
我们也可以不通过gcc命令而直接调用这些工具,比如下面的Makefile文件。
all:test_adr.S#汇编:将汇编文件test_adr.S转换成目标文件test_adr.o@ arm-linux-gcc -c -o test_adr.o test_adr.S #链接:将目标文件的集合,组合成可执行程序test_adr.elf@ arm-linux-ld -Ttext 0x00000000 -g test_adr.o -o test_adr.elf#复制:将可执行程序test_adr.elf从一种二进制格式(elf)转换成另外一种格式(bin)@ arm-linux-objcopy -O binary -S test_adr.elf test_adr.bin #反汇编:将可执行文件test_adr.elf反汇编,并将结果输出到test_adr.dis文件(否则输出至终端)@ arm-linux-objdump -D -m arm test_adr.elf > test_adr.disclean:@ rm -f test_adr.dis test_adr.bin test_adr.elf *.o
那么这些工具的作用是什么?它们的选项参数表示什么含义?接下来将简单进行说明。
该工具的作用与用法见博客GCC编译器编译C/C++程序。
其实也可以在gcc命令后面直接添加其他工具的选项,gcc命令在调用其他工具时,会将这些选项传递给这些工具。
objcopy主要用来转换目标文件的格式。在实际开发中,我们会用该工具进行格式转换与内容删除。
(1)在链接完成后,将elf格式的.out文件转化为bin格式的文件,因为有些平台不支持elf格式。
#复制:将可执行程序test_adr.elf从一种二进制格式(elf)转换成另外一种格式(bin)
arm-linux-objcopy -O binary -S test_adr.elf test_adr.bin
(2)(通过-g、-S等选项来表示)删除文件正常运行时不需要的内容,比如符号表、重定位表、调试信息等。裁剪后其体积比原来小很多,可以节省flash资源。当flash空间不足时,我们可以先查看可执行文件中是否存在运行时非必需的内容,并利用objcopy工具删除。
arm-linux-objcopy -g -S -O elf32-littlearm test_adr.elf test_adr2.elf
#或者写成
arm-linux-objcopy -g -S test_adr.elf -O elf32-littlearm test_adr2.elf
该工具使用格式如下。其中options表示选项,可以在命令行输入“man 1 objcopy”查看,这里摘录一些常用的选项。
objcopy [options] infile [outfile] #[ ]表示可选(可写可无)
(1)[-O bfdname|--output-target=bfdname]
(2)[-S|--strip-all]
(3)[-F bfdname|--target=bfdname]
(4)[-R sectionpattern|--remove-section=sectionpattern]
(5)[-I bfdname|--input-target=bfdname]
(6) [-g|--strip-debug]
[root@localhost test]# objcopy -O srec main main.srec #将文件转换成S-record格式
[root@localhost test]# objcopy -O binary main main.bin #将文件转换成rawbinary 格式
[root@localhost test]# objcopy -S main main.stripall #生成一个不含重定位以及标号目标文件
[root@localhost test]# objcopy -R .comment main main.remove #去掉指定名称的节
[root@localhost test]# objcopy --add-section mysection=hello_text main main.add #添加一个自定义的节到可执行文件并将一个文件内容添加到其中
[root@localhost test]# objcopy -j mysection main.add section_hello #将指定的段拷贝出来
[root@localhost test]# objcopy --only-keep-debug main.debug main.debuginfo # 生成调试信息文件
[root@localhost test]# objcopy --strip-debug main.debug main.stripdebug #生成 不含调试信息的可执行文件
[root@localhost test]# objcopy --add-gnu-debuglink=main.debuginfo main.stripdebug #为不含调试信息的可执行文件添加调试信息
objdump主要用来显示目标文件的内容或者反汇编。
比如本文开头的Makefile中有下面这一条代码:
#反汇编:将可执行文件test_adr.elf反汇编,并将结果输出到test_adr.dis文件(否则输出至终端)
@ arm-linux-objdump -D -m arm test_adr.elf > test_adr.dis
执行make之后生成的test_adr.dis文件内容如下:
xjh@ubuntu:~/iot/tmp$ cat test_adr.dis test_adr.elf: file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0: e59f0008 ldr r0, [pc, #8] ; 10 4: e28f0004 add r0, pc, #48: e59f0004 ldr r0, [pc, #4] ; 14 c: e1a00000 nop ; (mov r0, r0)00000010 :10: e1a00000 nop ; (mov r0, r0)14: 00000010 andeq r0, r0, r0, lsl r0Disassembly of section .ARM.attributes:00000000 <.ARM.attributes>:0: 00001a41 andeq r1, r0, r1, asr #204: 61656100 cmnvs r5, r0, lsl #28: 01006962 tsteq r0, r2, ror #18c: 00000010 andeq r0, r0, r0, lsl r010: 45543505 ldrbmi r3, [r4, #-1285] ; 0x50514: 08040600 stmdaeq r4, {r9, sl}18: Address 0x00000018 is out of bounds.xjh@ubuntu:~/iot/tmp$
我们一般利用该工具对目标文件进行反汇编,以解决一些问题。比如,当我们利用addr2line也无法定位死机地址具体在哪行代码时,我们可以用objdump就程序进行反汇编,然后在反汇编文件中查找死机地址在哪个函数范围内,这样可以把问题缩小范围,一定程度上提高解决问题的效率。
该工具使用格式如下。其中options表示选项,可以在命令行输入“man 1 objdump”查看。
objdump [options] obj_file #[]表示可选,obj_file表示目标文件
(1)[-D|--disassemble-all]
(2)[-m machine|--architecture=machine]
(3)[-S|--source]
(4)[-i|--info]
(5)[-j section|--section=section]
(6)[-d|--disassemble]
暂无。
arm-linux-ld -Ttext 0X87800000 led.o -o led.elf
相关参数: