为什么 gcc 默认使用“-z now”链接,尽管惰性绑定是 ld 的默认设置?

bki*_*ing 4 linux gcc ld linker-flags

man ld有以下话要说-z lazy

...告诉动态链接器将函数调用解析推迟到调用函数时...延迟绑定是默认设置

另一方面,gcc --verbose main.c传递-z now -z relro给 ld 以获得一个空的 main.cmain()

$ gcc --verbose main.c
Using built-in specs.
COLLECT_GCC=gcc
[...]
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
[...]
COLLECT_GCC_OPTIONS='-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/7/collect2 [...] -pie -z now -z relro [...]
Run Code Online (Sandbox Code Playgroud)

我在默认安装 gcc 的 Ubuntu 18.04 和 19.04 中看到了这一点。

所以-z lazy可能是 ld 的默认值,但是 gcc 在哪里/为什么将其更改为-z now -z relro

sof*_*are 11

它是 Ubuntu 16.10 中引入的 ELF 二进制强化功能,默认启用 PIE。

延迟绑定可以通过推迟函数符号的解析来提高程序启动性能。这意味着部分 GOT 数据(在 .got.plt 部分)必须在运行时可写。因此.got.plt可能会被“GOT覆盖”攻击所利用。

当 BIND_NOW 启用时,所有符号将在执行程序代码之前解析。.got.plt 部分由 ld 合并到 .got 部分。ld.so 在调用程序入口点之前将 .got 部分更改为只读。这称为完整的 RELRO。

请参阅这篇文章 了解更多详细信息。