動機
看bpf時突然想起來,整理一下
行前工具
- compiler: gcc
- 看elf的工具: readelf 或 objdump
- 單純看symbol: nm
compile流程
- compile: code -> object code
- 前面其實還有preprocesser展開,但先當成一起的
- 從高階語言變成低階語言
- assemble: object code -> binary(relocatable, 又名object file)
- 從低階語言變成binary
- 但在其他檔案的code怎麼找到他們?
- linking: binary(relocatable, 又名object file) -> binary(real exe)
- 把其他object file整理起來
- 算位置並填上binary去 (relocate)
ELF
kernel就是從ELF去看或找
- 有什麼code
- 有什麼symbol、要去哪找
- 大小、長度多少
- 資料的讀取權限
- debug info
類型有
- relocatable(o)
- executable
- shared obj(so)
- core(core dump)
詳細的可以看這邊
所以生出exe的過程可以看成改寫ELF的過程
linking
- linking
- 把很多object file和在一起
- 確認symbol在不在,處理各個symbol
- 依據symbol的來源分成兩種
- static linking
- symbol實際定義都在object file中
- 只要排好給位置就好(relocate)
- 所以
- static lib其實就是把object file黏成一個
- 如果改code要重算
- static加越多,最後出來的exe越大
- symbol實際定義都在object file中
- dynamic linking
- symbol不在object file中,所以
- 執行時要往外找 (先找到先用)
- 等到要load lib時,linker一樣會做relocate,不過與static不同,看PIC
- 編譯時
- 有找到就編過
- symbol會標上dynamic
- 執行時要往外找 (先找到先用)
- 所以
- 編dynamic lib需要特別一點
- 因為每個proc就算call同一種code,內部addr也會不同
- Position-independent Code(PIC),兩個case
- code都在同一個檔案
- 直接算相對位置
- 需要其他lib
- linker在載入lib時會填Global Offset Table
- 裡面會有其他lib的位置,等要call就去查,再跳
- code都在同一個檔案
- Position-independent Code(PIC),兩個case
- 因為每個proc就算call同一種code,內部addr也會不同
- 可以開心地換lib
- 大家可以共用
- 可以在runtime做load!! (dlopen, dlsym, dlerror, dlclose)
- 編dynamic lib需要特別一點
- symbol不在object file中,所以
- static linking
實際試試看
compile+assemble
main.c,但沒有p1, p2的宣告
void main() {
p1();
}
gcc -c main.c
main.c: In function ‘main’:
main.c:4:5: warning: implicit declaration of function ‘p1’ [-Wimplicit-function-declaration]
4 | p1();
| ^~
把p1補上去
void p1();
void main() {
p1();
}
static linking
a.c
#include <stdio.h>
void p1(){
puts("static");
}
同樣編成object file
gcc -o a.c
開編
gcc -o main main.o a.o
如果想模擬一下static lib
ar rcs liba.a a.o
編的語法是
gcc -o main -L. -la
其中-L
是lib要去哪裡找,-l
是lib的名稱
在linux,lib都是lib<libname>.??
nm
先用nm
看有什麼symbol,有puts與p1
bee314@DESKTOP-259SCE7:~$ nm main
0000000000003dc8 d _DYNAMIC
0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
0000000000002000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000002184 r __FRAME_END__
0000000000002010 r __GNU_EH_FRAME_HDR
0000000000004010 D __TMC_END__
0000000000004010 B __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000001100 t __do_global_dtors_aux
0000000000003dc0 d __do_global_dtors_aux_fini_array_entry
0000000000004008 D __dso_handle
0000000000003db8 d __frame_dummy_init_array_entry
w __gmon_start__
0000000000003dc0 d __init_array_end
0000000000003db8 d __init_array_start
00000000000011f0 T __libc_csu_fini
0000000000001180 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000004010 D _edata
0000000000004018 B _end
00000000000011f8 T _fini
0000000000001000 t _init
0000000000001060 T _start
0000000000004010 b completed.8060
0000000000004000 W data_start
0000000000001090 t deregister_tm_clones
0000000000001140 t frame_dummy
0000000000001149 T main
000000000000115e T p1
U puts@@GLIBC_2.2.5
00000000000010c0 t register_tm_clones
readelf & objdump
編出來後用objdump
與readelf
看dynsym,會看到這裡的dynsym是puts
bee314@DESKTOP-259SCE7:~$ readelf -r main
Relocation section '.rela.dyn' at offset 0x520 contains 8 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003db8 000000000008 R_X86_64_RELATIVE 1140
000000003dc0 000000000008 R_X86_64_RELATIVE 1100
000000004008 000000000008 R_X86_64_RELATIVE 4008
000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000003fe0 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000003fe8 000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
000000003ff8 000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x5e0 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000003fd0 000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
bee314@DESKTOP-259SCE7:~$ objdump -T main
main: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000 w D -UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF -UND* 0000000000000000 GLIBC_2.2.5 puts
0000000000000000 DF -UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D -UND* 0000000000000000 __gmon_start__
0000000000000000 w D -UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF -UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
ldd
最後用ldd
看有連結到那些lib,就是最基本的
bee314@DESKTOP-259SCE7:~$ ldd main
linux-vdso.so.1 (0x00007fffde0c8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0db9050000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0db926d000)
dynamic linking
b.c
void p1() {
puts("dynamic");
}
編成shared lib
gcc -o libb.so -fPIC -shared b.c
開編
gcc -o main -L. -lb
之後執行下去
./main: error while loading shared libraries: libb.so: cannot open shared object file: No such file or directory
這是找不到shared lib,所以
- 把libb.so放到預設路徑
- 加找的路徑
這裡直接幫他加找的路徑
LD_LIBRARY_PATH=. ./main
nm
用nm
看有什麼symbol,少了puts
bee314@DESKTOP-259SCE7:~$ nm main
0000000000003db8 d _DYNAMIC
0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
0000000000002000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
000000000000214c r __FRAME_END__
0000000000002004 r __GNU_EH_FRAME_HDR
0000000000004010 D __TMC_END__
0000000000004010 B __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000001100 t __do_global_dtors_aux
0000000000003db0 d __do_global_dtors_aux_fini_array_entry
0000000000004008 D __dso_handle
0000000000003da8 d __frame_dummy_init_array_entry
w __gmon_start__
0000000000003db0 d __init_array_end
0000000000003da8 d __init_array_start
00000000000011d0 T __libc_csu_fini
0000000000001160 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000004010 D _edata
0000000000004018 B _end
00000000000011d8 T _fini
0000000000001000 t _init
0000000000001060 T _start
0000000000004010 b completed.8060
0000000000004000 W data_start
0000000000001090 t deregister_tm_clones
0000000000001140 t frame_dummy
0000000000001149 T main
U p1
00000000000010c0 t register_tm_clones
readelf & objdump
同樣用objdump
與readelf
看dynsym,這邊只剩下p1,而沒有puts了
bee314@DESKTOP-259SCE7:~$ readelf -r main
Relocation section '.rela.dyn' at offset 0x528 contains 8 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003da8 000000000008 R_X86_64_RELATIVE 1140
000000003db0 000000000008 R_X86_64_RELATIVE 1100
000000004008 000000000008 R_X86_64_RELATIVE 4008
000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000003fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000003fe8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
000000003ff8 000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x5e8 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000003fd0 000400000007 R_X86_64_JUMP_SLO 0000000000000000 p1 + 0
bee314@DESKTOP-259SCE7:~$ objdump -T main
main: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000 w D -UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF -UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D -UND* 0000000000000000 __gmon_start__
0000000000000000 DF -UND* 0000000000000000 p1
0000000000000000 w D -UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF -UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
ldd
用ldd
看連結到那些lib,多了libb.so,雖然找不到
bee314@DESKTOP-259SCE7:~$ ldd main
linux-vdso.so.1 (0x00007fffc4a8a000)
libb.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a07ce0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5a07efa000)
讓ldd
好看一點,把libb.so移到/lib/x86_64-linux-gnu/
(抄libc.so.6)
bee314@DESKTOP-259SCE7:~$ ldd main
linux-vdso.so.1 (0x00007fffeb59a000)
libb.so => /lib/x86_64-linux-gnu/libb.so (0x00007fe732bc0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe7329c0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe732be1000)