ELF(Executable and Linkable Format)とは
Executable and Linkable Format (ELF) とは、コンパイラが生成するオブジェクト、および、ライブラリとリンクされた実行ファイルのファイルフォーマットである。a.outフォーマット、COFFの後継として広く採用されている。セクション数の制限が緩く、メモリ上で連続していないファイルや、ロードされる場所と実行される場所が違う箇所を含む場合にも対応が可能な柔軟な設計となっている。
System V が採用し、GNUツールチェーンがサポートしていることもあり、今ではBSD派生OSや、LinuxをはじめとするフリーなOSにおける実行ファイルフォーマットそして、ゲーム機等を含む組み込み機器開発に於いても好んで使われている。
by https://ja.wikipedia.org/wiki/Executable_and_Linkable_Format
「Binary Hacks ─ ハッカー秘伝のテクニック100選」あたりが詳しいです。
オブジェクトファイルの情報を表示する
objdump
$ objdump -j .plt -S /bin/ls | head -n 30
/bin/ls: file format elf64-x86-64
Disassembly of section .plt:
0000000000402190 <__ctype_toupper_loc@plt-0x10>:
402190: ff 35 72 7e 21 00 pushq 0x217e72(%rip) # 61a008 <_fini+0x20810c>
402196: ff 25 74 7e 21 00 jmpq *0x217e74(%rip) # 61a010 <_fini+0x208114>
40219c: 0f 1f 40 00 nopl 0x0(%rax)
00000000004021a0 <__ctype_toupper_loc@plt>:
4021a0: ff 25 72 7e 21 00 jmpq *0x217e72(%rip) # 61a018 <_fini+0x20811c>
4021a6: 68 00 00 00 00 pushq $0x0
4021ab: e9 e0 ff ff ff jmpq 402190 <_init+0x28>
00000000004021b0 <__uflow@plt>:
4021b0: ff 25 6a 7e 21 00 jmpq *0x217e6a(%rip) # 61a020 <_fini+0x208124>
4021b6: 68 01 00 00 00 pushq $0x1
4021bb: e9 d0 ff ff ff jmpq 402190 <_init+0x28>
00000000004021c0 <getenv@plt>:
4021c0: ff 25 62 7e 21 00 jmpq *0x217e62(%rip) # 61a028 <_fini+0x20812c>
4021c6: 68 02 00 00 00 pushq $0x2
4021cb: e9 c0 ff ff ff jmpq 402190 <_init+0x28>
00000000004021d0 <sigprocmask@plt>:
4021d0: ff 25 5a 7e 21 00 jmpq *0x217e5a(%rip) # 61a030 <_fini+0x208134>
4021d6: 68 03 00 00 00 pushq $0x3
4021db: e9 b0 ff ff ff jmpq 402190 <_init+0x28>
ELF ファイルに関する情報を表示
readelf
$ readelf -w -a /bin/ls
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
...
オブジェクトファイルのシンボルを表示する
nm
以下をコンパイルした a.out
に対して実行
#include <iostream>
int main(int argc, char const* argv[])
{
std::cout << "test" << std::endl;
return 0;
}
$ nm a.out
0000000000601060 B __bss_start
0000000000601170 b completed.6972
U __cxa_atexit@@GLIBC_2.2.5
0000000000601050 D __data_start
0000000000601050 W data_start
0000000000400790 t deregister_tm_clones
0000000000400800 t __do_global_dtors_aux
0000000000600e08 t __do_global_dtors_aux_fini_array_entry
0000000000601058 D __dso_handle
0000000000600e18 d _DYNAMIC
0000000000601060 D _edata
0000000000601178 B _end
00000000004008c4 T _fini
0000000000400820 t frame_dummy
0000000000600df8 t __frame_dummy_init_array_entry
0000000000400a18 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
0000000000400740 t _GLOBAL__sub_I_main
w __gmon_start__
0000000000400668 T _init
0000000000600e08 t __init_array_end
0000000000600df8 t __init_array_start
00000000004008d0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000600e10 d __JCR_END__
0000000000600e10 d __JCR_LIST__
w _Jv_RegisterClasses
00000000004008c0 T __libc_csu_fini
0000000000400850 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000400710 T main
00000000004007c0 t register_tm_clones
0000000000400766 T _start
0000000000601060 D __TMC_END__
U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
0000000000601060 B _ZSt4cout@@GLIBCXX_3.4
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
0000000000601171 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
オブジェクトのシンボルを削除する
strip
stripを実行してからnmを実行してみる
$ strip a.out
$ nm a.out
nm: a.out: no symbols
参考
共有ライブラリの依存関係を表示
ldd
lsでの実行例
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007ffe96d48000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fef2846a000)
libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007fef28262000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef27e9c000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fef27c5e000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fef27a5a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fef286a7000)
libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007fef27854000)
共有ライブラリの関数呼び出しをトレース
ltrace
lsでの実行例
$ ltrace /bin/ls
__libc_start_main(0x4028c0, 1, 0x7ffca0650708, 0x411e60 <unfinished ...>
strrchr("/bin/ls", '/') = "/ls"
setlocale(LC_ALL, "") = "LC_CTYPE=en_US.UTF-8;LC_NUMERIC="...
bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
textdomain("coreutils") = "coreutils"
__cxa_atexit(0x40a200, 0, 0, 0x736c6974756572) = 0
isatty(1) = 1
getenv("QUOTING_STYLE") = nil
getenv("COLUMNS") = nil
ioctl(1, 21523, 0x7ffca06502b0) = 0
...
システムコールの呼び出しをトレース
strace
$ strace /bin/ls
execve("/bin/ls", ["/bin/ls"], [/* 72 vars */]) = 0
brk(0) = 0x7d4000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f51bce000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=94491, ...}) = 0
...
close(1) = 0
munmap(0x7f0f51bcd000, 4096) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
-tt
などでタイムスタンプ、-T
で実行時間を表示可能
$ strace -tt -T /bin/ls 2>&1 | head -n 10
21:52:03.157481 execve("/bin/ls", ["/bin/ls"], [/* 72 vars */]) = 0 <0.001690>
21:52:03.160439 brk(0) = 0x654000 <0.000068>
21:52:03.161176 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000416>
21:52:03.163197 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe0b1da6000 <0.000381>
21:52:03.164400 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000419>
21:52:03.165426 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000350>
21:52:03.166938 fstat(3, {st_mode=S_IFREG|0644, st_size=94491, ...}) = 0 <0.000156>
21:52:03.167878 mmap(NULL, 94491, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe0b1d8e000 <0.000179>
21:52:03.168485 close(3) = 0 <0.000186>
21:52:03.169073 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000209>
マルチスレッドの場合は -f
をつけると良い。
参考
ファイル中の表示可能な文字列を表示する
strings
参考