bfd/gold emit DF_TEXTREL/DT_TEXTREL only when text relocations are really needed.
Details
Diff Detail
- Repository
- rLLD LLVM Linker
- Build Status
Buildable 17792 Build 17792: arc lint + arc unit
Event Timeline
This is perhaps harmless, but I'm leaning towards not doing this unless there's a reason to do this. I understand why GNU linkers want to do this -- it is because they allow text relocations by default. On the other hand, lld sets DF_TEXTREL only when you explicitly make lld allow text relocations. So, simply setting the flag when the flag is given makes sense to me. Can I ask your motivation of making this change?
The motivation is that IFUNC (e.g. R_X86_64_IRELATIVE) is incompatible with DF_TEXTREL. Setting DF_TEXTREL unconditionally may be sometimes harmful.
bfd will error when both IFUNC and DF_TEXTREL are used in non-writable segments.
// bfd/elfxx-x86.c:1291 if ((info->flags & DF_TEXTREL) != 0) { if (htab->readonly_dynrelocs_against_ifunc) { info->callbacks->einfo (_("%P%X: read-only segment has dynamic IFUNC relocations;" " recompile with -fPIC\n")); bfd_set_error (bfd_error_bad_value); return FALSE; } if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; }
gold does not error. But glibc ld.so will crash when IFUNC relocations are resolved in runtime
// elf/get-dynamic-info.h DF_TEXTREL implies DT_TEXTREL if (l->l_flags & DF_TEXTREL) info[DT_TEXTREL] = info[DT_FLAGS]; // elf/dl-reloc.c if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0)) { /////////// the program text segment is remapped as read+write ///// PROT_EXEC should also be set if ifunc is used if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0) ////// IFUNC (R_X86_64_IRELATIVE) is resolved in this call /// Code in the program segment is executed while the map is non-executable ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
I don't know if setting DF_TEXTREL flag only when text relocation is actually needed is a right solution to solve the issue you described. In lld, when you pass -z textrel, we should assume that the program really needs a text relocations, because otherwise you wouldn't pass that flag to the linker. If it is not compatible with IFUNC, we should emit a warning when we find a IFUNC symbol, no?
"-z textrel" can also be used in build instructions if some platforms will need it, even if not all of them do.
I consider the ifunc in combination with relro example as primary case for those issues a design bug in at least GNU ld. It's not even about text relocations really.
I feel lld's -z notext -z text is better than ld.bfd/gold's on-demand DT_TEXTREL tag. FWIW, glibc 2.19 (the next release) has addressed the incompatibility between DT_TEXTREL and IFUNC https://sourceware.org/bugzilla/show_bug.cgi?id=20480#c19