objdump、ld、ldd、readelf

objdump

打印二进制目标文件信息

-d   反汇编包含机器指令的段
-D   对所有的段进行反汇编
-h   显示段表

-p   显示专有头信息,内容取决于文件格式

-r    显示重定位信息
-R    显示动态链接的重定位信息

-s    显示所有段内容(二进制+内容)

-t    显示符号表
-T    显示动态链接符号表
-x    显示文件的所有文件头
root@DESKTOP-MBTVBV7:~/ccc# objdump -d main.o
main.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0: 55                    push   %rbp
   1: 48 89 e5              mov    %rsp,%rbp
   4: c7 45 f4 01 00 00 00  movl   $0x1,-0xc(%rbp)
   b: 48 8d 05 00 00 00 00  lea    0x0(%rip),%rax        # 12 <main+0x12>
  12: 48 89 45 f8           mov    %rax,-0x8(%rbp)
  16: 8b 45 f4              mov    -0xc(%rbp),%eax
  19: 5d                    pop    %rbp
  1a: c3                    retq
root@DESKTOP-MBTVBV7:~/ccc# objdump -h main.o
main.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000001b  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  0000005b  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  0000005b  2**0
                  ALLOC
  3 .rodata       00000006  0000000000000000  0000000000000000  0000005b  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      0000002c  0000000000000000  0000000000000000  00000061  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  0000008d  2**0
                  CONTENTS, READONLY
  6 .eh_frame     00000038  0000000000000000  0000000000000000  00000090  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

从上面的显示可以看出,代码段(.text)长度为 0x1b,文件的偏移地址为 0x40

 

ldd

打印共享对象依赖,即依赖于哪些动态库(会打印所有的依赖树)

objdump -p a.out | grep NEEDED 只会打印直接依赖

ldd 是一个shell脚本,它是通过调用运行时动态链接器,然后设置 LD_TRACE_LOADED_OBJECTS = 1

root@DESKTOP-MBTVBV7:~/ccc# ldd a.out 
  linux-vdso.so.1 (0x00007fffccf18000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fff34350000)
  /lib64/ld-linux-x86-64.so.2 (0x00007fff34a00000)
root@DESKTOP-MBTVBV7:~/ccc# objdump -p a.out | grep NEEDED
  NEEDED               libc.so.6

 

ld

GNU链接器

-static      静态链接
-l<libname>  指定链接某个库
-e name      指定name为程序入口(一般默认为_start)
-r            合并目标文件,不进行最终链接
-L            指定链接时查找路径,多个路径用冒号(:)隔开
-o            指定输出文件名

-s   清除输出文件的符号信息
-S   清除输出文件的调试信息

-T   指定链接脚本文件
-soname<name>   指定输出共享库的 SONAME

-export-dynamic   将全局符号全部导出
-verbose          链接时输出详细信息
-rpath=<path>     指定运行时库搜索路径

下面是打印hello world例子

main.asm

section .data
    msg db 'hello world!',0xa

section .text
    global eeee

eeee:
    ;write(1,msg,13)
    mov eax,1
    mov edi,1
    mov esi,msg
    mov edx,13
    syscall

    ;exit(0)
    mov eax,60
    mov edi,0
    syscall

调用了2个系统调用,一个是 write,一个是 exit

nasm -f elf64 main.asm -o main.o

首先将汇编代码汇编成机器代码,此时还不是可执行文件,只是elf格式的目标对象文件

ld main.o -e eeee

调用链接器,指定程序入口为 eee,即第一条指令开始执行的位置,生成最终的可执行文件

root@DESKTOP-MBTVBV7:~/ccc# ./a.out 
hello world!

我们通过ldd查看,没有任何的动态库

root@DESKTOP-MBTVBV7:~/ccc# ldd a.out 
  not a dynamic executable

 

readelf

打印 elf 文件的信息

-a    显示全部信息,等价于 -h -l -S -s -r -d -V -A -I

-h    显示elf文件头信息
-l    显示程序头信息
-S    显示section头信息
-e    显示上面全部头信息

-s    打印符号信息

-r    显示可重定位段(.rela.dyn)信息
-d    显示动态段(.dynamic)信息
-W    打印不裁剪,默认值打印80列

-x <name,number> 打印特定段的内容

假设 main 为可执行程序

readelf -S main
There are 21 section headers, starting at offset 0x14c8:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.build-i NOTE             0000000000400254  00000254
       0000000000000024  0000000000000000   A       0     0     4
  [ 3] .gnu.hash         GNU_HASH         0000000000400278  00000278
       000000000000003c  0000000000000000   A       4     0     8
  [ 4] .dynsym           DYNSYM           00000000004002b8  000002b8
       00000000000000d8  0000000000000018   A       5     1     8
  [ 5] .dynstr           STRTAB           0000000000400390  00000390
       0000000000000037  0000000000000000   A       0     0     1
  ....

假设要查看 .dynstr 段的具体内容,下面两条等价

readelf -x '.dynstr' main
readelf -x 5 main
Hex dump of section '.dynstr':
  0x00400390 006c6962 6f757473 796d2e73 6f006733 .liboutsym.so.g3
  0x004003a0 00616464 00673100 67320073 7562005f .add.g1.g2.sub._
  0x004003b0 65646174 61005f5f 6273735f 73746172 edata.__bss_star
  0x004003c0 74005f65 6e6400                     t._end.

如果想查看全部的段,可以使用

objdump -D main

你可能感兴趣的