您现在的位置是:首页 >技术杂谈 >Linux---GUN binutils网站首页技术杂谈

Linux---GUN binutils

面朝大海0902 2024-07-01 11:59:55
简介Linux---GUN binutils

在这里插入图片描述

一、GUN binutis概述

什么是GUN binutis?它是一个二进制工具集,默认情况下所有 Linux 发行版中都会安装这些二进制工具。实际大部分人是用过这些工具的,我一说大家就知道了。常用的二进制工具包括nm,size,addr2line,objcopy,objdump,readelf, strip

工具用途
nm列出目标文件中的符号
size列出目标文件中各个段的大小和总大小,如数据段,代码段
addr2line将程序地址翻译成文件名和行号
objcopysection复制和删除
objdump显示目标文件的信息和反汇编
readelf显示有关ELF文件的信息
strip从目标文件中剥离符号

二、工具集详细说明

为了更好的说明工具集的使用,我们写个简单的hello word程序

#include<stdio.h>
void main(int argc,char **argv)
{
  printf("hello word 
");
}

nm指令使用

使用gcc -o hello_word hello.c进行编译,使用nm指令查看hello_word程序的符号:

root@ubuntu:~/temp$ nm hello_word 
0000000000601040 B __bss_start
0000000000601040 b completed.6982
0000000000601030 D __data_start
0000000000601030 W data_start
0000000000400470 t deregister_tm_clones
00000000004004e0 t __do_global_dtors_aux
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000601038 D __dso_handle
0000000000600e28 d _DYNAMIC
0000000000601040 D _edata
0000000000601048 B _end
00000000004005c4 T _fini
0000000000400500 t frame_dummy
0000000000600e10 t __frame_dummy_init_array_entry
0000000000400708 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
00000000004003e0 T _init
0000000000600e18 t __init_array_end
0000000000600e10 t __init_array_start
00000000004005d0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
                 w _Jv_RegisterClasses
00000000004005c0 T __libc_csu_fini
0000000000400550 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
000000000040052d T main
                 U puts@@GLIBC_2.2.5
00000000004004a0 t register_tm_clones
0000000000400440 T _start
0000000000601040 D __TMC_END__

nm指令的详细用法如下图:

Usage: nm [option(s)] [file(s)]
 List symbols in [file(s)] (a.out by default).
 The options are:
  -a, --debug-syms       Display debugger-only symbols
  -A, --print-file-name  Print name of the input file before every symbol
  -B                     Same as --format=bsd
  -C, --demangle[=STYLE] Decode low-level symbol names into user-level names
                          The STYLE, if specified, can be `auto' (the default),
                          `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'
                          or `gnat'
      --no-demangle      Do not demangle low-level symbol names
  -D, --dynamic          Display dynamic symbols instead of normal symbols
      --defined-only     Display only defined symbols
  -e                     (ignored)
  -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',
                           `sysv' or `posix'.  The default is `bsd'
  -g, --extern-only      Display only external symbols
  -l, --line-numbers     Use debugging information to find a filename and
                           line number for each symbol
  -n, --numeric-sort     Sort symbols numerically by address
  -o                     Same as -A
  -p, --no-sort          Do not sort the symbols
  -P, --portability      Same as --format=posix
  -r, --reverse-sort     Reverse the sense of the sort
      --plugin NAME      Load the specified plugin
  -S, --print-size       Print size of defined symbols
  -s, --print-armap      Include index for symbols from archive members
      --size-sort        Sort symbols by size
      --special-syms     Include special symbols in the output
      --synthetic        Display synthetic symbols as well
  -t, --radix=RADIX      Use RADIX for printing symbol values
      --target=BFDNAME   Specify the target object format as BFDNAME
  -u, --undefined-only   Display only undefined symbols
  -X 32_64               (ignored)
  @FILE                  Read options from FILE
  -h, --help             Display this information
  -V, --version          Display this program's version number

size指令使用

对hello_word程序使用size指令,我们可以看到各个段的大小。

root@ubuntu:~/temp$ size hello_word 
   text	   data	    bss	    dec	    hex	filename
   1215	    560	      8	   1783	    6f7	hello_word
   
//size指令的详细用法如下图:
root@ubuntu:~/temp$ size --help
Usage: size [option(s)] [file(s)]
 Displays the sizes of sections inside binary files
 If no input file(s) are specified, a.out is assumed
 The options are:
  -A|-B     --format={sysv|berkeley}  Select output style (default is berkeley)
  -o|-d|-x  --radix={8|10|16}         Display numbers in octal, decimal or hex
  -t        --totals                  Display the total sizes (Berkeley only)
            --common                  Display total size for *COM* syms
            --target=<bfdname>        Set the binary file format
            @<file>                   Read options from <file>
  -h        --help                    Display this information
  -v        --version                 Display the program's version

objdump指令使用

objdump主要用来反汇编,将可执行文件的二进制指令反汇编成汇
编文件,各个参数及详细说明如下:
在这里插入图片描述

root@ubuntu:~/temp$ objdump -d  hello_word 

hello_word:     file format elf64-x86-64


Disassembly of section .init:

00000000004003e0 <_init>:
  4003e0:	48 83 ec 08          	sub    $0x8,%rsp
  4003e4:	48 8b 05 0d 0c 20 00 	mov    0x200c0d(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>
  4003eb:	48 85 c0             	test   %rax,%rax
  4003ee:	74 05                	je     4003f5 <_init+0x15>
  4003f0:	e8 3b 00 00 00       	callq  400430 <__gmon_start__@plt>
  4003f5:	48 83 c4 08          	add    $0x8,%rsp
  4003f9:	c3                   	retq   
... ...

Disassembly of section .text:

... ...

000000000040052d <main>:
  40052d:	55                   	push   %rbp
  40052e:	48 89 e5             	mov    %rsp,%rbp
  400531:	48 83 ec 10          	sub    $0x10,%rsp
  400535:	89 7d fc             	mov    %edi,-0x4(%rbp)
  400538:	48 89 75 f0          	mov    %rsi,-0x10(%rbp)
  40053c:	bf d4 05 40 00       	mov    $0x4005d4,%edi
  400541:	e8 ca fe ff ff       	callq  400410 <puts@plt>
  400546:	c9                   	leaveq 
  400547:	c3                   	retq   
  400548:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
  40054f:	00 
... ...

addr2line指令使用

addr2line 工具可以从二进制文件中的这些地址映射到 C 源代码匹配的地址,注意下面的hello_word程序编译是增加-g调试参数,其中400535地址为上面objdump 反汇编hello_word程序后main函数中的一行 400535: 89 7d fc mov %edi,-0x4(%rbp)

root@ubuntu:~/temp$ addr2line -e hello_word 400535
/fwork/temp/hello.c:3
 
root@ubuntu:~/temp$ addr2line --help
Usage: addr2line [option(s)] [addr(s)]
 Convert addresses into line number/file name pairs.
 If no addresses are specified on the command line, they will be read from stdin
 The options are:
  @<file>                Read options from <file>
  -a --addresses         Show addresses
  -b --target=<bfdname>  Set the binary file format
  -e --exe=<executable>  Set the input file name (default is a.out)
  -i --inlines           Unwind inlined functions
  -j --section=<name>    Read section-relative offsets instead of addresses
  -p --pretty-print      Make the output easier to read for humans
  -s --basenames         Strip directory names
  -f --functions         Show function names
  -C --demangle[=style]  Demangle function names
  -h --help              Display this information
  -v --version           Display the program's version

readelf指令使用

readelf是比较常用的命令,主要用来查看二进制文件的
各个section信息。各个参数详细说明如下:
在这里插入图片描述
我们对hello_word执行程序使用readelf指令查看下:

root@ubuntu:~/temp$ readelf -h  hello_word 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400440
  Start of program headers:          64 (bytes into file)
  Start of section headers:          5104 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         35
  Section header string table index: 32

另外再多提一个ldd 命令它可以列出动态库依赖关系非常有用:

root@ubuntu:~/temp$ ldd hello_word 
	linux-vdso.so.1 =>  (0x00007fff80b59000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6914c73000)
	/lib64/ld-linux-x86-64.so.2 (0x00005563c6986000)

strip指令使用

该命令通常用于将二进制文件中的调试信息等剥离出来,会使得二进制文件大小变小,但不影响二进制文件的实际执行。我们仍然以hello_word为例,编译时第一次加-g参数,然后使用strip指令:

root@ubuntu:~/temp$ gcc -g -o hello_word hello.c
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ file hello_word 
hello_word: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=6c4297ace1dd7a8d76137d4ff272461c459bbb27, not stripped
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ ls -al
-rwxrwxr-x  1 root root      9591 May 28 23:00 hello_word
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ strip hello_word 
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ file hello_word 
hello_word: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=6c4297ace1dd7a8d76137d4ff272461c459bbb27, stripped
root@ubuntu:~/temp$ 
root@ubuntu:~/temp$ ls -al
-rwxrwxr-x  1 root root      6248 May 28 22:56 hello_word

可以看到前后二进制文件大小有3k差异,当程序复杂时这个差异会更加的明显。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。