天外有天,人外有人。
分类: LINUX
2012-07-15 18:05:02
GNU Binutils练习
GNU Binutils是一组处理二进制文件的工具。
练习需要用到的代码
[chenojun@localhost compiler]$ cat >> filt_test.cpp int fun(int i){} int fun(float f){} int fun(double d){} int main(void) { fun(1); return 0; } ^Z [2]+ Stopped cat >> filt_test.cpp chenojun@localhost compiler]$ g++ -g filt_test.cpp -o filt_test
[chenojun@localhost compiler]$ nm filt_test |grep main U __libc_start_main@@GLIBC_2.0 08048462 T main
-f: 除文件名和行号显示出来外,将函数名也显示出来。
-e filename: 指定需要解析的可执行文件。
[chenojun@localhost compiler]$ addr2line -f -e filt_test 0x08048462 main /home/chenojun/test/compiler/filt_test.cpp:5
-d 反汇编
-S 将源码连同汇编一起显示
[chenojun@localhost compiler]$ objdump -dS filt_test filt_test: file format elf32-i386 08048462 int main(void) { 8048462: 55 push %ebp 8048463: 89 e5 mov %esp,%ebp 8048465: 83 ec 04 sub $0x4,%esp fun(1); 8048468: c7 04 24 01 00 00 00 movl $0x1,(%esp) 804846f: e8 d0 ff ff ff call 8048444 <_Z3funi> return 0; 8048474: b8 00 00 00 00 mov $0x0,%eax }
[chenojun@localhost compiler]$ size filt_test text data bss dec hex filename 1383 276 8 1667 683 filt_test |
[chenojun@localhost compiler]$ readelf -h filt_test 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: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048390 Start of program headers: 52 (bytes into file) Start of section headers: 2940 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 8 Size of section headers: 40 (bytes) Number of section headers: 36 Section header string table index: 33 |
[chenojun@localhost compiler]$ strings -f string string: /lib/ld-linux.so.2 string: {d+t string: __gmon_start__ string: libc.so.6 string: _IO_stdin_used string: puts string: __libc_start_main string: GLIBC_2.0 string: PTRh string: [^_] string: Hello! |
下例中,去除符号表文件大小由4636减小到2992。
[chenojun@localhost compiler]$ ls string -l -rwxrwxr-x. 1 chenojun chenojun 4636 Jul 15 12:56 string [chenojun@localhost compiler]$ objdump -t string |grep main 00000000 F *UND* 00000000 __libc_start_main@@GLIBC_2.0 080483b4 g F .text 0000001c main [chenojun@localhost compiler]$ strip string [chenojun@localhost compiler]$ ls string -l -rwxrwxr-x. 1 chenojun chenojun 2992 Jul 15 13:07 string [chenojun@localhost compiler]$ objdump -t string |grep main [chenojun@localhost compiler]$
[chenojun@localhost compiler]$ nm filt_test |grep fun 0804844e T _Z3fund 08048449 T _Z3funf 08048444 T _Z3funi [chenojun@localhost compiler]$ c++filt -n _Z3funf fun(float) [chenojun@localhost compiler]$ c++filt -n _Z3funi fun(int) [chenojun@localhost compiler]$ c++filt -n -s gnu-v3 _Z3funi fun(int) |
[chenojun@localhost compiler]$ cat >> gprof_test.c #include void p() { printf("test\n"); } int main() { int i[100]; for(int j=0;j<100;j++) { for(int k=0;k<100;k++) p(); } return 0; } ^Z [4]+ Stopped cat >> gprof_test.c [chenojun@localhost compiler]$ gcc -pg gprof_test.c -o gprof_test -std=c99 [chenojun@localhost compiler]$ ./gprof [chenojun@localhost compiler]$ gprof gprof_test Flat profile: Each sample counts as 0.01 seconds. no time accumulated % cumulative self self total time seconds seconds calls Ts/call Ts/call name 0.00 0.00 0.00 10000 0.00 0.00 p
Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) no time propagated index % time self children called name 0.00 0.00 10000/10000 main [5] [1] 0.0 0.00 0.00 10000 p [1] ----------------------------------------------- This table describes the call tree of the program, and was sorted by the total amount of time spent in each function and its children. |
1. 在没有文件系统的小型嵌入式系统中,图片通常以二进制数据存在flash上,objcopy可用于将jpg文件转换成binary.
[chenojun@localhost test]$ objcopy -I binary -O elf32-i386 -B i386 1271325202104_000.jpg image.o [chenojun@localhost test]$ objdump -ht image.o image.o: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn 0 .data 0001bbf3 00000000 00000000 00000034 2**0 CONTENTS, ALLOC, LOAD, DATA SYMBOL TABLE: 00000000 l d .data 00000000 .data 00000000 g .data 00000000 _binary_1271325202104_000_jpg_start 0001bbf3 g .data 00000000 _binary_1271325202104_000_jpg_end 0001bbf3 g *ABS* 00000000 _binary_1271325202104_000_jpg_size [chenojun@localhost test]$ cat objcopy_test.c #include extern _binary_1271325202104_000_jpg_end; extern _binary_1271325202104_000_jpg_size; extern _binary_1271325202104_000_jpg_start; int main() { printf("end=%p,size=%p,start=%p\n",&_binary_1271325202104_000_jpg_end,&_binary_1271325202104_000_jpg_size,&_binary_1271325202104_000_jpg_start); return 0; } [chenojun@localhost test]$ rm objcopy_test [chenojun@localhost test]$ gcc objcopy_test.c image.o -o objcopy_test [chenojun@localhost test]$ ./objcopy_test end=0x8064cef,size=0x1bbf3,start=0x80490fc
2. 在linux OS上运行的应用程序通常采用ELF格式, 但对于嵌入式系统来说,loader将程序导如内存,然后跳转到开始点(比如bootloader加载zImage到RAM,然后跳转到zImage开始地址),开始点就必须是程序指令而不是ELF头这样的信息,因此在编译好执行文件后需要用arm-linux-objcopy这样的objcopy将执行文件转换成binary文件(只包含.data, .text等执行时需要的段)。
$(LinuxSrcRoot)/arch/arm/boot/Makefile: $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @echo ' Kernel: $@ is ready'