Chinaunix首页 | 论坛 | 博客
  • 博客访问: 75498
  • 博文数量: 11
  • 博客积分: 140
  • 博客等级: 入伍新兵
  • 技术积分: 208
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-22 00:51
个人简介

天外有天,人外有人。

文章分类

全部博文(11)

文章存档

2013年(10)

2012年(1)

我的朋友

分类: 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

  • ld – 连接工具 (略过)
  •  as – 工具(略过)
  •  ar –archieve处理工具,常用于创建、修改库和从库里提取文件(略过)
  • nm – 列举目标文件里的所有symbol

[chenojun@localhost compiler]$ nm filt_test |grep main

         U __libc_start_main@@GLIBC_2.0

08048462 T main

  •  addr2line – 将执行文件里symbol的地址转换为该symbol在源文件名和行号

-f: 除文件名和行号显示出来外,将函数名也显示出来。

-e filename: 指定需要解析的可执行文件。

[chenojun@localhost compiler]$ addr2line -f -e filt_test 0x08048462

main

/home/chenojun/test/compiler/filt_test.cpp:5

  •  objdump – 显示目标文件的信息,功能非常强大的目标文件分析工具。如:反汇编,符号表。

-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

}

  •  size显示文件的大小和各section的大小

[chenojun@localhost compiler]$ size filt_test

   text       data       bss       dec       hex   filename

   1383      276         8       1667      683   filt_test

  • readelf – ELF文件分析工具,显示ELF目标文件信息。如:EFL文件头信息,符号表,section信息,重定位信息

[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

  • strings 显示文件里的可打印字符串。注意:不只是printf()里的字串。

[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!

  •  strip 去除目标文件里的符号表,减少文件大小,但不便于调试。

下例中,去除符号表文件大小由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]$

  • c++filt  --为了支持函数重载,C++编译器将源码里的函数名根据参数进行重新命名,这使得符号表里的函数名的可读性降低。C++filt可以将符号表的的函数名字转换回函数在源码里的名字。

 [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)

  •  gprof 显示程序运行时函数调用情况,如:函数调用关系,调用次数,函数执行所消耗的时间等。主要用于分析和改进程序的性能。使用时需要使用gcc -pg 选项以便于gcc加入一些处理用于gprof分析。

[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.

 

  •  objcopy 对二进制文件进行格式转换。

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加载zImageRAM,然后跳转到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'

 

 

 

 

 

 

阅读(1445) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:对比学习2.4与2.6之系统调用

给主人留下些什么吧!~~