The rtld-audit interfaces introduces a slowdown due to enabling
profiling instrumentation (as if LD_AUDIT implied LD_PROFILE).
However, instrumenting is only necessary if one of audit libraries
provides PLT callbacks (la_pltenter or la_pltexit symbols). Otherwise,
the slowdown can be avoided.
The following patch adjusts the logic that enables profiling to iterate
over all audit modules and check if any of those provides a PLT hook.
To keep la_symbind to work even without PLT callbacks, _dl_fixup now
calls the audit callback if the modules implements it.
Co-authored-by: Alexander Monakov <amonakov@ispras.ru>
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 063f9ba220)
Resolved conflicts:
NEWS
elf/Makefile
dynamic-link.h is included more than once in some elf/ files (rtld.c,
dl-conflict.c, dl-reloc.c, dl-reloc-static-pie.c) and uses GCC nested
functions. This harms readability and the nested functions usage
is the biggest obstacle prevents Clang build (Clang doesn't support GCC
nested functions).
The key idea for unnesting is to add extra parameters (struct link_map
*and struct r_scope_elm *[]) to RESOLVE_MAP,
ELF_MACHINE_BEFORE_RTLD_RELOC, ELF_DYNAMIC_RELOCATE, elf_machine_rel[a],
elf_machine_lazy_rel, and elf_machine_runtime_setup. (This is inspired
by Stan Shebs' ppc64/x86-64 implementation in the
google/grte/v5-2.27/master which uses mixed extra parameters and static
variables.)
Future simplification:
* If mips elf_machine_runtime_setup no longer needs RESOLVE_GOTSYM,
elf_machine_runtime_setup can drop the `scope` parameter.
* If TLSDESC no longer need to be in elf_machine_lazy_rel,
elf_machine_lazy_rel can drop the `scope` parameter.
Tested on aarch64, i386, x86-64, powerpc64le, powerpc64, powerpc32,
sparc64, sparcv9, s390x, s390, hppa, ia64, armhf, alpha, and mips64.
In addition, tested build-many-glibcs.py with {arc,csky,microblaze,nios2}-linux-gnu
and riscv64-linux-gnu-rv64imafdc-lp64d.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 490e6c62aa)
This helps to clarify that the caching of these fields in libpthread
(in __static_tls_size, __static_tls_align_m1) is unnecessary.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
The stack list is available in ld.so since commit
1daccf403b ("nptl: Move stack list
variables into _rtld_global"), so it's possible to walk the stack
list directly in ld.so and perform the initialization there.
This eliminates an unprotected function pointer from _rtld_global
and reduces the libpthread initialization code.
I used these shell commands:
../glibc/scripts/update-copyrights $PWD/../gnulib/build-aux/update-copyright
(cd ../glibc && git commit -am"[this commit message]")
and then ignored the output, which consisted lines saying "FOO: warning:
copyright statement not found" for each of 6694 files FOO.
I then removed trailing white space from benchtests/bench-pthread-locks.c
and iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c, to work around this
diagnostic from Savannah:
remote: *** pre-commit check failed ...
remote: *** error: lines with trailing whitespace found
remote: error: hook declined to update refs/heads/master
On some targets static TLS surplus area can be used opportunistically
for dynamically loaded modules such that the TLS access then becomes
faster (TLSDESC and powerpc TLS optimization). However we don't want
all surplus TLS to be used for this optimization because dynamically
loaded modules with initial-exec model TLS can only use surplus TLS.
The new contract for surplus static TLS use is:
- libc.so can have up to 192 bytes of IE TLS,
- other system libraries together can have up to 144 bytes of IE TLS.
- Some "optional" static TLS is available for opportunistic use.
The optional TLS is now tunable: rtld.optional_static_tls, so users
can directly affect the allocated static TLS size. (Note that module
unloading with dlclose does not reclaim static TLS. After the optional
TLS runs out, TLS access is no longer optimized to use static TLS.)
The default setting of rtld.optional_static_tls is 512 so the surplus
TLS is 3*192 + 4*144 + 512 = 1664 by default, the same as before.
Fixes BZ #25051.
Tested on aarch64-linux-gnu and x86_64-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This will allow changes in dependency processing during non-lazy
binding, for more precise processing of NODELETE objects: During
initial relocation in dlopen, the fate of NODELETE objects is still
unclear, so objects which are depended upon by NODELETE objects
cannot immediately be marked as NODELETE.
Change-Id: Ic7b94a3f7c4719a00ca8e6018088567824da0658
Currently, DT_TEXTREL is incompatible with IFUNC. When DT_TEXTREL or
DF_TEXTREL is seen, the dynamic linker calls __mprotect on the segments
with PROT_READ|PROT_WRITE before applying dynamic relocations. It leads
to segfault when performing IFUNC resolution (which requires PROT_EXEC
as well for the IFUNC resolver).
This patch makes it call __mprotect with extra PROT_WRITE bit, which
will keep the PROT_EXEC bit if exists, and thus fixes the segfault.
FreeBSD rtld libexec/rtld-elf/rtld.c (reloc_textrel_prot) does the same.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
sparc64-linux-gnu, sparcv9-linux-gnu, and armv8-linux-gnueabihf.
Adam J. Richte <adam_richter2004@yahoo.com>
Adhemerval Zanella <adhemerval.zanella@linaro.org>
Fangrui Song <maskray@google.com>
[BZ #20480]
* config.h.in (CAN_TEXTREL_IFUNC): New define.
* configure.ac: Add check if linker supports textrel relocation with
ifunc.
* elf/dl-reloc.c (_dl_relocate_object): Use all required flags on
DT_TEXTREL segments, not only PROT_READ and PROT_WRITE.
* elf/Makefile (ifunc-pie-tests): Add tst-ifunc-textrel.
(CFLAGS-tst-ifunc-textrel.c): New rule.
* elf/tst-ifunc-textrel.c: New file.
posix/wordexp-test.c used libc-internal.h for PTR_ALIGN_DOWN; similar
to what was done with libc-diag.h, I have split the definitions of
cast_to_integer, ALIGN_UP, ALIGN_DOWN, PTR_ALIGN_UP, and PTR_ALIGN_DOWN
to a new header, libc-pointer-arith.h.
It then occurred to me that the remaining declarations in libc-internal.h
are mostly to do with early initialization, and probably most of the
files including it, even in the core code, don't need it anymore. Indeed,
only 19 files actually need what remains of libc-internal.h. 23 others
need libc-diag.h instead, and 12 need libc-pointer-arith.h instead.
No file needs more than one of them, and 16 don't need any of them!
So, with this patch, libc-internal.h stops including libc-diag.h as
well as losing the pointer arithmetic macros, and all including files
are adjusted.
* include/libc-pointer-arith.h: New file. Define
cast_to_integer, ALIGN_UP, ALIGN_DOWN, PTR_ALIGN_UP, and
PTR_ALIGN_DOWN here.
* include/libc-internal.h: Definitions of above macros
moved from here. Don't include libc-diag.h anymore either.
* posix/wordexp-test.c: Include stdint.h and libc-pointer-arith.h.
Don't include libc-internal.h.
* debug/pcprofile.c, elf/dl-tunables.c, elf/soinit.c, io/openat.c
* io/openat64.c, misc/ptrace.c, nptl/pthread_clock_gettime.c
* nptl/pthread_clock_settime.c, nptl/pthread_cond_common.c
* string/strcoll_l.c, sysdeps/nacl/brk.c
* sysdeps/unix/clock_settime.c
* sysdeps/unix/sysv/linux/i386/get_clockfreq.c
* sysdeps/unix/sysv/linux/ia64/get_clockfreq.c
* sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
* sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c:
Don't include libc-internal.h.
* elf/get-dynamic-info.h, iconv/loop.c
* iconvdata/iso-2022-cn-ext.c, locale/weight.h, locale/weightwc.h
* misc/reboot.c, nis/nis_table.c, nptl_db/thread_dbP.h
* nscd/connections.c, resolv/res_send.c, soft-fp/fmadf4.c
* soft-fp/fmasf4.c, soft-fp/fmatf4.c, stdio-common/vfscanf.c
* sysdeps/ieee754/dbl-64/e_lgamma_r.c
* sysdeps/ieee754/dbl-64/k_rem_pio2.c
* sysdeps/ieee754/flt-32/e_lgammaf_r.c
* sysdeps/ieee754/flt-32/k_rem_pio2f.c
* sysdeps/ieee754/ldbl-128/k_tanl.c
* sysdeps/ieee754/ldbl-128ibm/k_tanl.c
* sysdeps/ieee754/ldbl-96/e_lgammal_r.c
* sysdeps/ieee754/ldbl-96/k_tanl.c, sysdeps/nptl/futex-internal.h:
Include libc-diag.h instead of libc-internal.h.
* elf/dl-load.c, elf/dl-reloc.c, locale/programs/locarchive.c
* nptl/nptl-init.c, string/strcspn.c, string/strspn.c
* malloc/malloc.c, sysdeps/i386/nptl/tls.h
* sysdeps/nacl/dl-map-segments.h, sysdeps/x86_64/atomic-machine.h
* sysdeps/unix/sysv/linux/spawni.c
* sysdeps/x86_64/nptl/tls.h:
Include libc-pointer-arith.h instead of libc-internal.h.
* elf/get-dynamic-info.h, sysdeps/nacl/dl-map-segments.h
* sysdeps/x86_64/atomic-machine.h:
Add multiple include guard.
In _dl_nothread_init_static_tls() and init_one_static_tls() we must not
touch the DTV of other threads since we do not have ownership of them.
The DTV need not be initialized at this point anyway since only LD/GD
accesses will use them. If LD/GD accesses occur they will take care to
initialize their own thread's DTV.
Concurrency comments were removed from the patch since they need to be
reworked along with a full description of DTV ownership and when it is
or is not safe to modify these structures.
Alexandre Oliva's original patch and discussion:
https://sourceware.org/ml/libc-alpha/2016-09/msg00512.html
An earlier fix for TLS dropped early initialization of DTV entries for
modules using static TLS, leaving it for __tls_get_addr to set them
up. That worked on platforms that require the GD access model to be
relaxed to LE in the main executable, but it caused a regression on
platforms that allow GD in the main executable, particularly in
statically-linked programs: they use a custom __tls_get_addr that does
not update the DTV, which fails when the DTV early initialization is
not performed.
In static programs, __libc_setup_tls performs the DTV initialization
for the main thread, but the DTV of other threads is set up in
_dl_allocate_tls_init, so that's the fix that matters.
Restoring the initialization in the remaining functions modified by
this patch was just for uniformity. It's not clear that it is ever
needed: even on platforms that allow GD in the main executable, the
dynamically-linked version of __tls_get_addr would set up the DTV
entries, even for static TLS modules, while updating the DTV counter.
for ChangeLog
[BZ #19826]
* elf/dl-tls.c (_dl_allocate_tls_init): Restore DTV early
initialization of static TLS entries.
* elf/dl-reloc.c (_dl_nothread_init_static_tls): Likewise.
* nptl/allocatestack.c (init_one_static_tls): Likewise.
In a reference to PR ld/19908 make ld.so respect symbol export classes
aka visibility and treat STV_HIDDEN and STV_INTERNAL symbols as local,
preventing such symbols from preempting exported symbols.
According to the ELF gABI[1] neither STV_HIDDEN nor STV_INTERNAL symbols
are supposed to be present in linked binaries:
"A hidden symbol contained in a relocatable object must be either
removed or converted to STB_LOCAL binding by the link-editor when the
relocatable object is included in an executable file or shared object."
"An internal symbol contained in a relocatable object must be either
removed or converted to STB_LOCAL binding by the link-editor when the
relocatable object is included in an executable file or shared object."
however some GNU binutils versions produce such symbols in some cases.
PR ld/19908 is one and we also have this note in scripts/abilist.awk:
so clearly there is linked code out there which contains such symbols
which is prone to symbol table misinterpretation, and it'll be more
productive if we handle this gracefully, under the Robustness Principle:
"be liberal in what you accept, and conservative in what you produce",
especially as this is a simple (STV_HIDDEN|STV_INTERNAL) => STB_LOCAL
mapping.
References:
[1] "System V Application Binary Interface - DRAFT - 24 April 2001",
The Santa Cruz Operation, Inc., "Symbol Table",
<http://www.sco.com/developers/gabi/2001-04-24/ch4.symtab.html>
* sysdeps/generic/ldsodefs.h
(dl_symbol_visibility_binds_local_p): New inline function.
* elf/dl-addr.c (determine_info): Treat hidden and internal
symbols as local.
* elf/dl-lookup.c (do_lookup_x): Likewise.
* elf/dl-reloc.c (RESOLVE_MAP): Likewise.
A shared object doesn't need PLT if there are no PLT relocations. It
shouldn't be an error if DT_PLTRELSZ is missing.
[BZ #18410]
* elf/dl-reloc.c (_dl_relocate_object): Don't issue an error
for missing DT_PLTRELSZ.
for ChangeLog
[BZ #17090]
[BZ #17620]
[BZ #17621]
[BZ #17628]
* NEWS: Update.
* elf/dl-tls.c (_dl_update_slotinfo): Clean up outdated DTV
entries with Static TLS too. Skip entries past the end of the
allocated DTV, from Alan Modra.
(tls_get_addr_tail): Update to glibc_likely/unlikely. Move
Static TLS DTV entry set up from...
(_dl_allocate_tls_init): ... here (fix modid assertion), ...
* elf/dl-reloc.c (_dl_nothread_init_static_tls): ... here...
* nptl/allocatestack.c (init_one_static_tls): ... and here...
* elf/dlopen.c (dl_open_worker): Drop l_tls_modid upper bound
for Static TLS.
* elf/tlsdeschtab.h (map_generation): Return size_t. Check
that the slot we find is associated with the given map before
using its generation count.
* nptl_db/db_info.c: Include ldsodefs.h.
(rtld_global, dtv_slotinfo_list, dtv_slotinfo): New typedefs.
* nptl_db/structs.def (DB_RTLD_VARIABLE): New macro.
(DB_MAIN_VARIABLE, DB_RTLD_GLOBAL_FIELD): Likewise.
(link_map::l_tls_offset): New struct field.
(dtv_t::counter): Likewise.
(rtld_global): New struct.
(_rtld_global): New rtld variable.
(dl_tls_dtv_slotinfo_list): New rtld global field.
(dtv_slotinfo_list): New struct.
(dtv_slotinfo): Likewise.
* nptl_db/td_symbol_list.c: Drop gnu/lib-names.h include.
(td_lookup): Rename to...
(td_mod_lookup): ... this. Use new mod parameter instead of
LIBPTHREAD_SO.
* nptl_db/td_thr_tlsbase.c: Include link.h.
(dtv_slotinfo_list, dtv_slotinfo): New functions.
(td_thr_tlsbase): Check DTV generation. Compute Static TLS
addresses even if the DTV is out of date or missing them.
* nptl_db/fetch-value.c (_td_locate_field): Do not refuse to
index zero-length arrays.
* nptl_db/thread_dbP.h: Include gnu/lib-names.h.
(td_lookup): Make it a macro implemented in terms of...
(td_mod_lookup): ... this declaration.
* nptl_db/db-symbols.awk (DB_RTLD_VARIABLE): Override.
(DB_MAIN_VARIABLE): Likewise.
We are replacing all of the bespoke alignment code with
ALIGN_UP, ALIGN_DOWN, PTR_ALIGN_UP, and PTR_ALIGN_DOWN.
This cleans up malloc/malloc.c, malloc/arena.c, and
elf/dl-reloc.c. It also makes all the code consistently
use pagesize, and powerof2 as required.
Code size is reduced with the removal of precomputed
pagemask, and use of pagesize instead. No measurable
difference in performance.
No regressions on x86_64.
During auditing or profiling modes the dynamic loader
builds a cache of the relocated PLT entries in order
to reuse them when called again through the same PLT
entry. This way the PLT entry is never completed and
the call into the resolver always results in profiling
or auditing code running.
The problem is that the PLT relocation cache size
is not computed correctly. The size of the cache
should be "Size of a relocation result structure"
x "Number of PLT-related relocations". Instead the
code erroneously computes "Size of a relocation
result" x "Number of bytes worth of PLT-related
relocations". I can only assume this was a mistake
in the understanding of the value of DT_PLTRELSZ
which is the number of bytes of PLT-related relocs.
We do have a DT_RELACOUNT entry, which is a count
for dynamic relative relocs, but we have no
DT_PLTRELCOUNT and thus we need to compute it.
This patch corrects the computation of the size of the
relocation table used by the glibc profiling code.
For more details see:
https://sourceware.org/ml/libc-alpha/2014-09/msg00513.html
[BZ #17411]
* elf/dl-reloc.c (_dl_relocate_object): Allocate correct amount for
l_reloc_result.
Resolves: #15465
The program name may be unavailable if the user application tampers
with argc and argv[]. Some parts of the dynamic linker caters for
this while others don't, so this patch consolidates the check and
fallback into a single macro and updates all users.
* elf/dl-load.c (_dl_map_object_from_fd): Only call audit hooks
if we are not loading a new audit library.
* elf/dl-reloc (_dl_relocate_object): Third parameter is now a bitmask.
Only use profiling trampoline for auditing if we are not relocating
an audit library.
* elf/dl-open.c (dl_open_worker): Adjust _dl_relocate_object call.
* elf/rtld.c: Likewise.
* sysdeps/generic/ldsodefs.h: Adjust _dl_relocate_object prototype.
* elf/dl-close.c (_dl_close): Check for it.
* elf/dl-reloc.c (CHECK_STATIC_TLS): Likewise.
(_dl_allocate_static_tls): Likewise.
* elf/dl-tls.c (_dl_allocate_tls_init): Likewise.
(__tls_get_addr): Protect from race conditions in setting l_tls_offset
to it.
* elf/tst-tls16.c: New file.
* elf/tst-tlsmod16a.c: New file.
* elf/tst-tlsmod16b.c: New file.
* elf/Makefile: Add rules to build and run tst-tls16.
* elf/dl-reloc.c (_dl_nothread_init_static_tls): Assert that dtv
array index is within bounds.
* elf/dl-load.c: Do not allow PT_TLS in modules loaded in statically
linked code.
* sysdeps/generic/dl-tls.c [!SHARED]: Don't build _dl_next_tls_modid.
* elf/Makefile: Remove rules to build and run tst-tls9-static.