This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: -fpatchable-function-entry should set SHF_WRITE and create one __patchable_function_entries per function
- From: Fangrui Song <i at maskray dot me>
- To: gcc at gcc dot gnu dot org
- Cc: Martin Liška <mliska at suse dot cz>, Alexander Monakov <amonakov at ispras dot ru>, Torsten Duwe <duwe at suse dot de>, Maxim Kuvyrkov <maxim dot kuvyrkov at linaro dot org>, Nick Clifton <nickc at redhat dot com>
- Date: Mon, 6 Jan 2020 23:25:55 -0800
- Subject: Re: -fpatchable-function-entry should set SHF_WRITE and create one __patchable_function_entries per function
- References: <20200107060629.z7lvo74ravoppg77@gmail.com>
On 2020-01-06, Fangrui Song wrote:
The addresses of NOPs are collected in a section named __patchable_function_entries.
A __patchable_function_entries entry is relocated by a symbolic relocation (e.g. R_X86_64_64, R_AARCH64_ABS64, R_PPC64_ADDR64).
In -shared or -pie mode, the linker will create a dynamic relocation (non-preemptible: relative relocation (e.g. R_X86_64_RELATIVE); preemptible: symbolic relocation (e.g. R_X86_64_64)).
In either case, the section contents will be modified at runtime.
Thus, the section should have the SHF_WRITE flag to avoid text relocations (DF_TEXTREL).
When -ffunction-sections is used, ideally GCC should emit one __patchable_function_entries (SHF_LINK_ORDER) per .text.foo .
If the corresponding .text.foo is discarded (--gc-sections, COMDAT, /DISCARD/), the linker can discard the associated __patchable_function_entries. This can be seen as a lightweight COMDAT section group. (A section group adds an extra section and costs 3 words)
Currently lld (LLVM linker) has implemented such SHF_LINK_ORDER collecting features. GNU ld and gold don't have the features.
I have summarized the feature requests in this post https://sourceware.org/ml/binutils/2019-11/msg00266.html
gcc -fpatchable-function-entry=2 -ffunction-sections -c a.c
[ 4] .text.f0 PROGBITS 0000000000000000 000040 000009 00 AX 0 0 1
### No W flag
### One __patchable_function_entries instead of 3.
[ 5] __patchable_function_entries PROGBITS 0000000000000000 000049 000018 00 A 0 0 1
[ 6] .rela__patchable_function_entries RELA 0000000000000000 000280 000048 18 I 13 5 8
[ 7] .text.f1 PROGBITS 0000000000000000 000061 000009 00 AX 0 0 1
[ 8] .text.f2 PROGBITS 0000000000000000 00006a 000009 00 AX 0 0 1
Emitting a __patchable_function_entries for each function may waste
object file sizes (64 bytes per function on ELF64). If zeros are
allowed, emitting a single __patchable_function_entries should be fine.
If we do want to emit unique sections, the condition should be either
-ffunction-sections or COMDAT is used.