泻药!同一个cpp文件,编译成可执行文件和编译成外部动态库(.so)的编译命令有什么区别?应注意哪些地方?
“编译成”动态链接库的目的:就是希望被“复用”,那么一个动态链接库(例如libstdc++.so)是如何被调用的呢?
举个简单的栗子:
#include int main(int argc, char *argv[]) {
std::cout << "Hello World" << std::endl;
return 0;
}
如果使用GNU工具链,调用libstdc++库,通过readelf可以清楚看到:
000000000015 000f0000000a R_X86_64_32 0000000000000000 _ZSt4cout + 0
其中_ZSt4cout这个Symbol,通过c++filt _ZSt4cout能看得更清楚:
std::cout
那么R_X86_64_32这个Relocation类型 Relocation 在GNU工具链binutils是如何处理的呢?具体就得查看binutils-gdb/bfd/elf64-x86-64.c的代码(待续)
继续看栗子的X86 Target(题主使用AArch64平台,请使用GNU交叉编译工具链)的Assembly:
main:
...
movl$_ZSt4cout, %edi
call_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl$_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
movq%rax, %rdi
call_ZNSolsEPFRSoS_E
movl$0, %eax
leave
ret
...
已经把不需要讲解的部分汇编删除,同样用c++filt _ZSt4cout
std::cout
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
std::basic_ostream >& std::operator<< <:char_traits> >(std::basic_ostream >&, char const*)
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
std::basic_ostream >& std::endl >(std::basic_ostream >&)
_ZNSolsEPFRSoS_E
std::basic_ostream >::operator< >& (*)(std::basic_ostream >&))
题主手边可以放上一本《编译原理》龙三,翻翻第7章“运行时环境”把compiler-rt讲清楚了!