打印二进制目标文件信息
-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
打印共享对象依赖,即依赖于哪些动态库(会打印所有的依赖树)
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
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
打印 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