This allows the resolution of the symbol value to be determined dynamically at load time, and an optimized version of the routine can be selected for the particular processor or other system characteristics determined then.
NOTE: require a recent binutils (at least version 2.20.1), and GNU C library (at least version 2.11.1).
ps. building arm static binary with using ld.gold linker has bug
https://sourceware.org/bugzilla/show_bug.cgi?id=17081
https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
https://gcc.gnu.org/ml/gcc-help/2012-03/msg00209.html
Real example:
glibc for armv7 has 3 type memcpy implementation.
- __memcpy_neon
- __memcpy_vfp
- memcpy_arm
memcpy (IFUNC):
if (neon supported)
return &__memcpy_neon
if (vfp supported)
return &__memcpy_vfp
return &__memcpy_arm
memcpy will choose memcpy implementation at load time
memcpy use HWCP info (include CPU info) to got cpu capability
HWCAP(hardware capabilities)
#require executable file for system info
$LD_SHOW_AUXV=1 /lib/ld-linux-armhf.so.3
.got
ld-linux0 --> a.out's struct link map in ld-linux.so
ld-linux1 --> _dl_runtime_reolve in ld-linux.so
dynamic link的lazy binding
WHY? 呼叫.so function
HOW? GOT + PLT
第一次呼叫foo時, got內foo的address會指到ld-linux.so的dl_runtime_resolve
dl_runtime_resolve會把foo的address填到got內foo的address,然後跳到foo
第二次呼叫foo時, got內的foo的address就是指到foo, 就直接跳過去執行foo
Q: softfp的memcpy_vfp 跟 hardfp的memcpy_vfp的實做會一樣嗎?
A: libc有分不同版本, 所以沒問題
ifunc is indriect call
在static build的情況下
在main之前必須執行glibc apply_iplt去initialize ifunc
apply_iplt:
for each R_ARM_IRELATIVE
val = * GOT[i](hwcap);
GOT[i] = val;