why is -z used with -Wl
The following 3 commands are exactly equivalent:
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
They all pass -z norelro
to the linker during the final link stage.
The first form is standard across many compilers. The second form is a tiny bit shorter, but really shouldn't be used (because using a "standard" form is always better). The third form is supported only to be compatible with GCC. It's unnecessarily verbose.
Update:
Couldn't we just write -Wl,norelro
No: that will pass a "naked" norelro
option to the linker, which will treat it as an input file and will complain that no such input file exists. There is (obviously) a difference between passing -z norelro
and just norelro
.
Also, consider clang ./noaslr.c -Wl,-z,-no_pie ...
That is just a bogus command. The -no-pie
is a linker option, and should not be prefixed by -z
. It's also not a valid option value for the -z
option.
Update 2:
Where can I see possible values for the -z linker option?
In the manual page for ld
on the OS that you are targeting. For example, on Linux the latest BFD ld
understands the following -z
options: bndplt
, call-nop-prefix=...
, combreloc
, etc. etc.
Also, do you have any clue why man ld on macOS doesn't show the -z linker option?
Probably because it doesn't support that option at all.