What is the "-z" option of Clang and why is it needed?

Shu*_*eng 2 c macos linker clang

Consider the following linker-specific options of Clang:

-Wl,<arg>                Pass the comma separated arguments in <arg> to the linker
-Xlinker <arg>           Pass <arg> to the linker
-z <arg>                  Pass -z <arg> to the linker
Run Code Online (Sandbox Code Playgroud)

What is meant by Pass -z <arg> to the linker and how does -z <arg> differ from -Xlinker <arg>?

I sometimes see -z <arg> used with -Wl,<arg> like:

-Wl,-z,norelro
Run Code Online (Sandbox Code Playgroud)

But why is this needed, if arguments to -Wl should merely be comma-separated?

Emp*_*ian 6

为什么-z与-Wl一起使用

以下3个命令完全等效:

clang main.c -o a.out -Wl,-z,norelro
clang main.c -o a.out -z norelro
clang main.c -o a.out -Xlinker -z -Xlinker norelro
Run Code Online (Sandbox Code Playgroud)

它们都-z norelro在最终链接阶段传递给链接器。

第一种形式是许多编译器的标准形式。第二种形式稍短一些,但实际上不应该使用(因为使用“标准”形式总是更好)。仅支持第三种形式以与GCC兼容。它不必要地冗长。

更新:

我们不能只是写 -Wl,norelro

否:会将“裸” norelro选项传递给链接器,链接器会将其视为输入文件,并且会抱怨不存在这样的输入文件。(显然)pass -z norelro和just 之间有区别norelro

另外,考虑 clang ./noaslr.c -Wl,-z,-no_pie ...

那只是伪指令。该-no-pie 一个连接器选项,而不应被作为前缀-z。这也不是该-z选项的有效选项值。

更新2:

在哪里可以看到-z链接器选项的可能值?

ld 目标操作系统上的手册页中。例如,在Linux的最新BFD ld 了解以下-z选项:bndpltcall-nop-prefix=...combreloc,等等等等。

另外,您是否有任何线索为什么在macOS上的man不显示-z链接器选项?

可能是因为它根本不支持该选项。