Toshaan Bharvani
2 years ago
199 changed files with 52391 additions and 0 deletions
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit ea89d5bbd9e5e514b606045d909e6ab87d851c88 |
||||
Author: Arjun Shankar <arjun@redhat.com> |
||||
Date: Thu Feb 24 21:43:09 2022 +0100 |
||||
|
||||
localedef: Handle symbolic links when generating locale-archive |
||||
|
||||
Whenever locale data for any locale included symbolic links, localedef |
||||
would throw the error "incomplete set of locale files" and exclude it |
||||
from the generated locale archive. This commit fixes that. |
||||
|
||||
Co-authored-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c |
||||
index f38e835c52e4a967..d79278b6ed7340bf 100644 |
||||
--- a/locale/programs/locarchive.c |
||||
+++ b/locale/programs/locarchive.c |
||||
@@ -1391,7 +1391,7 @@ add_locales_to_archive (size_t nlist, char *list[], bool replace) |
||||
{ |
||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; |
||||
|
||||
- if (d_type == DT_UNKNOWN) |
||||
+ if (d_type == DT_UNKNOWN || d_type == DT_LNK) |
||||
{ |
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), |
||||
d->d_name); |
@ -0,0 +1,605 @@
@@ -0,0 +1,605 @@
|
||||
commit c901c3e764d7c7079f006b4e21e877d5036eb4f5 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Dec 9 09:49:32 2021 +0100 |
||||
|
||||
nptl: Add public rseq symbols and <sys/rseq.h> |
||||
|
||||
The relationship between the thread pointer and the rseq area |
||||
is made explicit. The constant offset can be used by JIT compilers |
||||
to optimize rseq access (e.g., for really fast sched_getcpu). |
||||
|
||||
Extensibility is provided through __rseq_size and __rseq_flags. |
||||
(In the future, the kernel could request a different rseq size |
||||
via the auxiliary vector.) |
||||
|
||||
Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
|
||||
diff --git a/manual/threads.texi b/manual/threads.texi |
||||
index 7f166bfa87e88c36..4869f69d2ceed255 100644 |
||||
--- a/manual/threads.texi |
||||
+++ b/manual/threads.texi |
||||
@@ -629,6 +629,8 @@ the standard. |
||||
* Waiting with Explicit Clocks:: Functions for waiting with an |
||||
explicit clock specification. |
||||
* Single-Threaded:: Detecting single-threaded execution. |
||||
+* Restartable Sequences:: Linux-specific restartable sequences |
||||
+ integration. |
||||
@end menu |
||||
|
||||
@node Default Thread Attributes |
||||
@@ -958,6 +960,85 @@ application-created thread because future versions of @theglibc{} may |
||||
create background threads after the first thread has been created, and |
||||
the application has no way of knowning that these threads are present. |
||||
|
||||
+@node Restartable Sequences |
||||
+@subsubsection Restartable Sequences |
||||
+ |
||||
+This section describes restartable sequences integration for |
||||
+@theglibc{}. This functionality is only available on Linux. |
||||
+ |
||||
+@deftp {Data Type} {struct rseq} |
||||
+@standards{Linux, sys/rseq.h} |
||||
+The type of the restartable sequences area. Future versions |
||||
+of Linux may add additional fields to the end of this structure. |
||||
+ |
||||
+ |
||||
+Users need to obtain the address of the restartable sequences area using |
||||
+the thread pointer and the @code{__rseq_offset} variable, described |
||||
+below. |
||||
+ |
||||
+One use of the restartable sequences area is to read the current CPU |
||||
+number from its @code{cpu_id} field, as an inline version of |
||||
+@code{sched_getcpu}. @Theglibc{} sets the @code{cpu_id} field to |
||||
+@code{RSEQ_CPU_ID_REGISTRATION_FAILED} if registration failed or was |
||||
+explicitly disabled. |
||||
+ |
||||
+Furthermore, users can store the address of a @code{struct rseq_cs} |
||||
+object into the @code{rseq_cs} field of @code{struct rseq}, thus |
||||
+informing the kernel that the thread enters a restartable sequence |
||||
+critical section. This pointer and the code areas it itself points to |
||||
+must not be left pointing to memory areas which are freed or re-used. |
||||
+Several approaches can guarantee this. If the application or library |
||||
+can guarantee that the memory used to hold the @code{struct rseq_cs} and |
||||
+the code areas it refers to are never freed or re-used, no special |
||||
+action must be taken. Else, before that memory is re-used of freed, the |
||||
+application is responsible for setting the @code{rseq_cs} field to |
||||
+@code{NULL} in each thread's restartable sequence area to guarantee that |
||||
+it does not leak dangling references. Because the application does not |
||||
+typically have knowledge of libraries' use of restartable sequences, it |
||||
+is recommended that libraries using restartable sequences which may end |
||||
+up freeing or re-using their memory set the @code{rseq_cs} field to |
||||
+@code{NULL} before returning from library functions which use |
||||
+restartable sequences. |
||||
+ |
||||
+The manual for the @code{rseq} system call can be found |
||||
+at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}. |
||||
+@end deftp |
||||
+ |
||||
+@deftypevar {int} __rseq_offset |
||||
+@standards{Linux, sys/rseq.h} |
||||
+This variable contains the offset between the thread pointer (as defined |
||||
+by @code{__builtin_thread_pointer} or the thread pointer register for |
||||
+the architecture) and the restartable sequences area. This value is the |
||||
+same for all threads in the process. If the restartable sequences area |
||||
+is located at a lower address than the location to which the thread |
||||
+pointer points, the value is negative. |
||||
+@end deftypevar |
||||
+ |
||||
+@deftypevar {unsigned int} __rseq_size |
||||
+@standards{Linux, sys/rseq.h} |
||||
+This variable is either zero (if restartable sequence registration |
||||
+failed or has been disabled) or the size of the restartable sequence |
||||
+registration. This can be different from the size of @code{struct rseq} |
||||
+if the kernel has extended the size of the registration. If |
||||
+registration is successful, @code{__rseq_size} is at least 32 (the |
||||
+initial size of @code{struct rseq}). |
||||
+@end deftypevar |
||||
+ |
||||
+@deftypevar {unsigned int} __rseq_flags |
||||
+@standards{Linux, sys/rseq.h} |
||||
+The flags used during restartable sequence registration with the kernel. |
||||
+Currently zero. |
||||
+@end deftypevar |
||||
+ |
||||
+@deftypevr Macro int RSEQ_SIG |
||||
+@standards{Linux, sys/rseq.h} |
||||
+Each supported architecture provides a @code{RSEQ_SIG} macro in |
||||
+@file{sys/rseq.h} which contains a signature. That signature is |
||||
+expected to be present in the code before each restartable sequences |
||||
+abort handler. Failure to provide the expected signature may terminate |
||||
+the process with a segmentation fault. |
||||
+@end deftypevr |
||||
+ |
||||
@c FIXME these are undocumented: |
||||
@c pthread_atfork |
||||
@c pthread_attr_destroy |
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c |
||||
index 23aa4cfc0b784dfc..0f5280a75d546d2f 100644 |
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c |
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c |
||||
@@ -22,6 +22,7 @@ |
||||
#include <pthreadP.h> |
||||
#include <tls.h> |
||||
#include <rseq-internal.h> |
||||
+#include <thread_pointer.h> |
||||
|
||||
#define TUNABLE_NAMESPACE pthread |
||||
#include <dl-tunables.h> |
||||
@@ -43,6 +44,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock) |
||||
} |
||||
#endif |
||||
|
||||
+const unsigned int __rseq_flags; |
||||
+const unsigned int __rseq_size attribute_relro; |
||||
+const int __rseq_offset attribute_relro; |
||||
+ |
||||
void |
||||
__tls_pre_init_tp (void) |
||||
{ |
||||
@@ -100,7 +105,23 @@ __tls_init_tp (void) |
||||
#if HAVE_TUNABLES |
||||
do_rseq = TUNABLE_GET (rseq, int, NULL); |
||||
#endif |
||||
- rseq_register_current_thread (pd, do_rseq); |
||||
+ if (rseq_register_current_thread (pd, do_rseq)) |
||||
+ { |
||||
+ /* We need a writable view of the variables. They are in |
||||
+ .data.relro and are not yet write-protected. */ |
||||
+ extern unsigned int size __asm__ ("__rseq_size"); |
||||
+ size = sizeof (pd->rseq_area); |
||||
+ } |
||||
+ |
||||
+#ifdef RSEQ_SIG |
||||
+ /* This should be a compile-time constant, but the current |
||||
+ infrastructure makes it difficult to determine its value. Not |
||||
+ all targets support __thread_pointer, so set __rseq_offset only |
||||
+ if thre rseq registration may have happened because RSEQ_SIG is |
||||
+ defined. */ |
||||
+ extern int offset __asm__ ("__rseq_offset"); |
||||
+ offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); |
||||
+#endif |
||||
} |
||||
|
||||
/* Set initial thread's stack block from 0 up to __libc_stack_end. |
||||
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile |
||||
index 5c772f69d1b1f1f1..9b7e214219943531 100644 |
||||
--- a/sysdeps/unix/sysv/linux/Makefile |
||||
+++ b/sysdeps/unix/sysv/linux/Makefile |
||||
@@ -110,7 +110,8 @@ sysdep_headers += sys/mount.h sys/acct.h \ |
||||
bits/types/struct_semid64_ds_helper.h \ |
||||
bits/types/struct_shmid64_ds.h \ |
||||
bits/types/struct_shmid64_ds_helper.h \ |
||||
- bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h |
||||
+ bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h \ |
||||
+ sys/rseq.h bits/rseq.h |
||||
|
||||
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ |
||||
tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \ |
||||
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions |
||||
index 26452f3f17b5421d..3f8809a1581f27d0 100644 |
||||
--- a/sysdeps/unix/sysv/linux/Versions |
||||
+++ b/sysdeps/unix/sysv/linux/Versions |
||||
@@ -316,6 +316,11 @@ librt { |
||||
} |
||||
|
||||
ld { |
||||
+ GLIBC_2.35 { |
||||
+ __rseq_flags; |
||||
+ __rseq_offset; |
||||
+ __rseq_size; |
||||
+ } |
||||
GLIBC_PRIVATE { |
||||
__nptl_change_stack_perm; |
||||
} |
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
index b7196a80e2df8efc..bf4d4f9b6f2ddf97 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.17 __tls_get_addr F |
||||
GLIBC_2.17 _dl_mcount F |
||||
GLIBC_2.17 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
index 13f7fc74af62941d..a23325a566419b41 100644 |
||||
--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x8 |
||||
GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x8 |
||||
diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist |
||||
index 7284383a6bea8e64..55f0c2ab9c6f7d91 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arc/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/arc/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.32 __tls_get_addr F |
||||
GLIBC_2.32 _dl_mcount F |
||||
GLIBC_2.32 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist |
||||
index 7987bbae1112aa3d..f1da2c636ddb359d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist |
||||
@@ -1,4 +1,7 @@ |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __libc_stack_end D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
GLIBC_2.4 __tls_get_addr F |
||||
diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist |
||||
index 7987bbae1112aa3d..f1da2c636ddb359d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist |
||||
@@ -1,4 +1,7 @@ |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __libc_stack_end D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
GLIBC_2.4 __tls_get_addr F |
||||
diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist |
||||
index 4939b20631dc6c54..7f482276ed8df1d5 100644 |
||||
--- a/sysdeps/unix/sysv/linux/csky/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/csky/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.29 __tls_get_addr F |
||||
GLIBC_2.29 _dl_mcount F |
||||
GLIBC_2.29 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist |
||||
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x14 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist |
||||
index e8d187b14d722a64..9c4a45d8dc525e52 100644 |
||||
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 ___tls_get_addr F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
index be5122650ae2b327..8ccb5be911e0e9a2 100644 |
||||
--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist |
||||
index 7987bbae1112aa3d..f1da2c636ddb359d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist |
||||
@@ -1,4 +1,7 @@ |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __libc_stack_end D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
GLIBC_2.4 __tls_get_addr F |
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist |
||||
index 4f2854edf7746958..dadbf852d0522e77 100644 |
||||
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x4 |
||||
GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist |
||||
index 9f0fdeca38890a34..89a0b7e4fd5a95fa 100644 |
||||
--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.18 __tls_get_addr F |
||||
GLIBC_2.18 _dl_mcount F |
||||
GLIBC_2.18 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist |
||||
index f750067d5c34bf42..e304d1bb464b28f4 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4 |
||||
GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist |
||||
index f750067d5c34bf42..e304d1bb464b28f4 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4 |
||||
GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
index 2fba6a9b6ec92e47..37a47ebc0a0d16c8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x8 |
||||
GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x8 |
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist |
||||
index 57dfad5a53b739e8..811ae9da2fa85399 100644 |
||||
--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.21 __tls_get_addr F |
||||
GLIBC_2.21 _dl_mcount F |
||||
GLIBC_2.21 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist |
||||
index e89660739262c6ab..5a68aeb9eed33844 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist |
||||
@@ -5,3 +5,6 @@ GLIBC_2.22 __tls_get_addr_opt F |
||||
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
index ce0bc639597c4bd9..da24dc7fb52ad2d4 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
@@ -5,3 +5,6 @@ GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.3 _dl_mcount F |
||||
GLIBC_2.3 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
index 65b22674d2462e96..b9ae89ae8d90ed9e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
@@ -5,3 +5,6 @@ GLIBC_2.17 _r_debug D 0x28 |
||||
GLIBC_2.22 __tls_get_addr_opt F |
||||
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist |
||||
index 5ad4c81d12d7a612..068368878eb2406e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.33 __tls_get_addr F |
||||
GLIBC_2.33 _dl_mcount F |
||||
GLIBC_2.33 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
index 479efdea9bb654bb..48431c91a9fd16b0 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
@@ -4,3 +4,6 @@ GLIBC_2.27 __tls_get_addr F |
||||
GLIBC_2.27 _dl_mcount F |
||||
GLIBC_2.27 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h |
||||
index 6a3441f2cc49e7c4..9e8f99fd51a063b1 100644 |
||||
--- a/sysdeps/unix/sysv/linux/rseq-internal.h |
||||
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h |
||||
@@ -41,7 +41,7 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq) |
||||
return false; |
||||
} |
||||
#else /* RSEQ_SIG */ |
||||
-static inline void |
||||
+static inline bool |
||||
rseq_register_current_thread (struct pthread *self, bool do_rseq) |
||||
{ |
||||
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist |
||||
index d5ecb636bb792bdf..c15288394a232a8c 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4 |
||||
GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_offset F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
index 62a5e1d99a2e6f42..117d1430a4c6272e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_offset F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist |
||||
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x14 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist |
||||
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist |
||||
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x14 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist |
||||
index 2e6054349871e7d5..3aac73f3df646cb6 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4 |
||||
GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
index be5122650ae2b327..8ccb5be911e0e9a2 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
index c8edff50d40e29b6..1215b5d086b8852b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
@@ -171,4 +171,14 @@ struct rseq |
||||
|
||||
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */ |
||||
|
||||
+/* Offset from the thread pointer to the rseq area. */ |
||||
+extern const int __rseq_offset; |
||||
+ |
||||
+/* Size of the registered rseq area. 0 if the registration was |
||||
+ unsuccessful. */ |
||||
+extern const unsigned int __rseq_size; |
||||
+ |
||||
+/* Flags used during rseq registration. */ |
||||
+extern const unsigned int __rseq_flags; |
||||
+ |
||||
#endif /* sys/rseq.h */ |
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c |
||||
index 000e351872fc2f76..6d73f77e9621da42 100644 |
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c |
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c |
||||
@@ -21,6 +21,7 @@ |
||||
#include <support/namespace.h> |
||||
#include <support/xthread.h> |
||||
#include <sysdep.h> |
||||
+#include <thread_pointer.h> |
||||
#include <unistd.h> |
||||
|
||||
#ifdef RSEQ_SIG |
||||
@@ -30,6 +31,11 @@ static void |
||||
check_rseq_disabled (void) |
||||
{ |
||||
struct pthread *pd = THREAD_SELF; |
||||
+ |
||||
+ TEST_COMPARE (__rseq_flags, 0); |
||||
+ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset |
||||
+ == (char *) &pd->rseq_area); |
||||
+ TEST_COMPARE (__rseq_size, 0); |
||||
TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); |
||||
|
||||
int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), |
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c |
||||
index 926376b6a5446ece..572c11166f8b6533 100644 |
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq.c |
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c |
||||
@@ -29,12 +29,20 @@ |
||||
# include <stdlib.h> |
||||
# include <string.h> |
||||
# include <syscall.h> |
||||
+# include <thread_pointer.h> |
||||
+# include <tls.h> |
||||
# include "tst-rseq.h" |
||||
|
||||
static void |
||||
do_rseq_main_test (void) |
||||
{ |
||||
+ struct pthread *pd = THREAD_SELF; |
||||
+ |
||||
TEST_VERIFY_EXIT (rseq_thread_registered ()); |
||||
+ TEST_COMPARE (__rseq_flags, 0); |
||||
+ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset |
||||
+ == (char *) &pd->rseq_area); |
||||
+ TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area)); |
||||
} |
||||
|
||||
static void |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
index afddaec57c11f837..ae622bdf9710bdbd 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.2.5 _dl_mcount F |
||||
GLIBC_2.2.5 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |
||||
index defc488d137c61c3..e17496d124b0c7b7 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |
||||
@@ -3,3 +3,6 @@ GLIBC_2.16 __tls_get_addr F |
||||
GLIBC_2.16 _dl_mcount F |
||||
GLIBC_2.16 _r_debug D 0x14 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
+GLIBC_2.35 __rseq_flags D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_size D 0x4 |
@ -0,0 +1,180 @@
@@ -0,0 +1,180 @@
|
||||
commit 6c33b018438ee799c29486f21d43d8100bdbd597 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Wed Feb 2 22:37:20 2022 +0100 |
||||
|
||||
Linux: Use ptrdiff_t for __rseq_offset |
||||
|
||||
This matches the data size initial-exec relocations use on most |
||||
targets. |
||||
|
||||
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/manual/threads.texi b/manual/threads.texi |
||||
index 4869f69d2ceed255..48fd562923800b34 100644 |
||||
--- a/manual/threads.texi |
||||
+++ b/manual/threads.texi |
||||
@@ -1004,7 +1004,7 @@ The manual for the @code{rseq} system call can be found |
||||
at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}. |
||||
@end deftp |
||||
|
||||
-@deftypevar {int} __rseq_offset |
||||
+@deftypevar {ptrdiff_t} __rseq_offset |
||||
@standards{Linux, sys/rseq.h} |
||||
This variable contains the offset between the thread pointer (as defined |
||||
by @code{__builtin_thread_pointer} or the thread pointer register for |
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c |
||||
index 0f5280a75d546d2f..d5f2587f1348441c 100644 |
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c |
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c |
||||
@@ -46,7 +46,7 @@ rtld_mutex_dummy (pthread_mutex_t *lock) |
||||
|
||||
const unsigned int __rseq_flags; |
||||
const unsigned int __rseq_size attribute_relro; |
||||
-const int __rseq_offset attribute_relro; |
||||
+const ptrdiff_t __rseq_offset attribute_relro; |
||||
|
||||
void |
||||
__tls_pre_init_tp (void) |
||||
@@ -119,7 +119,7 @@ __tls_init_tp (void) |
||||
all targets support __thread_pointer, so set __rseq_offset only |
||||
if thre rseq registration may have happened because RSEQ_SIG is |
||||
defined. */ |
||||
- extern int offset __asm__ ("__rseq_offset"); |
||||
+ extern ptrdiff_t offset __asm__ ("__rseq_offset"); |
||||
offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); |
||||
#endif |
||||
} |
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
index bf4d4f9b6f2ddf97..5151c0781de01bf1 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist |
||||
@@ -5,5 +5,5 @@ GLIBC_2.17 _dl_mcount F |
||||
GLIBC_2.17 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
index a23325a566419b41..3e296c547314f6c2 100644 |
||||
--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist |
||||
@@ -4,6 +4,6 @@ GLIBC_2.1 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x8 |
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
index 8ccb5be911e0e9a2..5471b24d59a7527a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist |
||||
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
index 37a47ebc0a0d16c8..f26e594a139f0058 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |
||||
@@ -4,6 +4,6 @@ GLIBC_2.2 _dl_mcount F |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
GLIBC_2.4 __stack_chk_guard D 0x8 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
index da24dc7fb52ad2d4..21f472e674299ab7 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist |
||||
@@ -6,5 +6,5 @@ GLIBC_2.3 _dl_mcount F |
||||
GLIBC_2.3 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
index b9ae89ae8d90ed9e..9c9c40450d651880 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist |
||||
@@ -6,5 +6,5 @@ GLIBC_2.22 __tls_get_addr_opt F |
||||
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
index 48431c91a9fd16b0..a7758a0e52fc8cc8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist |
||||
@@ -5,5 +5,5 @@ GLIBC_2.27 _dl_mcount F |
||||
GLIBC_2.27 _r_debug D 0x28 |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
index 117d1430a4c6272e..78d071600b1f3431 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist |
||||
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_offset F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
index 8ccb5be911e0e9a2..5471b24d59a7527a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist |
||||
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
||||
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
index 1215b5d086b8852b..791ed83176b61fe4 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
@@ -21,6 +21,7 @@ |
||||
/* Architecture-specific rseq signature. */ |
||||
#include <bits/rseq.h> |
||||
|
||||
+#include <stddef.h> |
||||
#include <stdint.h> |
||||
#include <sys/cdefs.h> |
||||
#include <bits/endian.h> |
||||
@@ -172,7 +173,7 @@ struct rseq |
||||
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */ |
||||
|
||||
/* Offset from the thread pointer to the rseq area. */ |
||||
-extern const int __rseq_offset; |
||||
+extern const ptrdiff_t __rseq_offset; |
||||
|
||||
/* Size of the registered rseq area. 0 if the registration was |
||||
unsuccessful. */ |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
index ae622bdf9710bdbd..5a8bd322cdc95d5b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist |
||||
@@ -4,5 +4,5 @@ GLIBC_2.2.5 _r_debug D 0x28 |
||||
GLIBC_2.3 __tls_get_addr F |
||||
GLIBC_2.34 __rtld_version_placeholder F |
||||
GLIBC_2.35 __rseq_flags D 0x4 |
||||
-GLIBC_2.35 __rseq_offset D 0x4 |
||||
+GLIBC_2.35 __rseq_offset D 0x8 |
||||
GLIBC_2.35 __rseq_size D 0x4 |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
commit 4b527650e0d559a5f693275c598667e06cd6455c |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Jun 2 16:29:55 2022 +0200 |
||||
|
||||
Linux: Adjust struct rseq definition to current kernel version |
||||
|
||||
This definition is only used as a fallback with old kernel headers. |
||||
The change follows kernel commit bfdf4e6208051ed7165b2e92035b4bf11 |
||||
("rseq: Remove broken uapi field layout on 32-bit little endian"). |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
index 791ed83176b61fe4..56550329db962cc8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h |
||||
@@ -24,7 +24,6 @@ |
||||
#include <stddef.h> |
||||
#include <stdint.h> |
||||
#include <sys/cdefs.h> |
||||
-#include <bits/endian.h> |
||||
|
||||
#ifdef __has_include |
||||
# if __has_include ("linux/rseq.h") |
||||
@@ -129,28 +128,13 @@ struct rseq |
||||
targeted by the rseq_cs. Also needs to be set to NULL by user-space |
||||
before reclaiming memory that contains the targeted struct rseq_cs. |
||||
|
||||
- Read and set by the kernel. Set by user-space with single-copy |
||||
- atomicity semantics. This field should only be updated by the |
||||
- thread which registered this data structure. Aligned on 64-bit. */ |
||||
- union |
||||
- { |
||||
- uint64_t ptr64; |
||||
-# ifdef __LP64__ |
||||
- uint64_t ptr; |
||||
-# else /* __LP64__ */ |
||||
- struct |
||||
- { |
||||
-#if __BYTE_ORDER == __BIG_ENDIAN |
||||
- uint32_t padding; /* Initialized to zero. */ |
||||
- uint32_t ptr32; |
||||
-# else /* LITTLE */ |
||||
- uint32_t ptr32; |
||||
- uint32_t padding; /* Initialized to zero. */ |
||||
-# endif /* ENDIAN */ |
||||
- } ptr; |
||||
-# endif /* __LP64__ */ |
||||
- } rseq_cs; |
||||
+ Read and set by the kernel. Set by user-space with single-copy |
||||
+ atomicity semantics. This field should only be updated by the |
||||
+ thread which registered this data structure. Aligned on 64-bit. |
||||
|
||||
+ 32-bit architectures should update the low order bits of the |
||||
+ rseq_cs field, leaving the high order bits initialized to 0. */ |
||||
+ uint64_t rseq_cs; |
||||
/* Restartable sequences flags field. |
||||
|
||||
This field should only be updated by the thread which |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
Revert glibc-rh2024347-13.patch. Enable rseq by default. |
||||
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi |
||||
index f559c44dcec4624b..28ff502990c2a10f 100644 |
||||
--- a/manual/tunables.texi |
||||
+++ b/manual/tunables.texi |
||||
@@ -425,13 +425,11 @@ The value is measured in bytes. The default is @samp{41943040} |
||||
@end deftp |
||||
|
||||
@deftp Tunable glibc.pthread.rseq |
||||
-The @code{glibc.pthread.rseq} tunable can be set to @samp{1}, to enable |
||||
-restartable sequences support. @Theglibc{} uses this to optimize the |
||||
-@code{sched_getcpu} function. |
||||
- |
||||
-The default is @samp{0}, which means that applications can perform |
||||
-restartable sequences registration, but @code{sched_getcpu} is not |
||||
-accelerated. |
||||
+The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable |
||||
+restartable sequences support in @theglibc{}. This enables applications |
||||
+to perform direct restartable sequence registration with the kernel. |
||||
+The default is @samp{1}, which means that @theglibc{} performs |
||||
+registration on behalf of the application. |
||||
|
||||
Restartable sequences are a Linux-specific extension. |
||||
@end deftp |
||||
diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list |
||||
index df2a39ce01858d3b..d24f4be0d08ba407 100644 |
||||
--- a/sysdeps/nptl/dl-tunables.list |
||||
+++ b/sysdeps/nptl/dl-tunables.list |
||||
@@ -31,7 +31,7 @@ glibc { |
||||
type: INT_32 |
||||
minval: 0 |
||||
maxval: 1 |
||||
- default: 0 |
||||
+ default: 1 |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
commit 62a321b12d0e397af88fa422db65079332f971dc |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Jun 24 18:16:41 2022 +0200 |
||||
|
||||
support: Change non-address output format of support_format_dns_packet |
||||
|
||||
It makes sense to include the owner name (LHS) and record type in the |
||||
output, so that they can be checked for correctness. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c |
||||
index 1f8e9ca172a06f4f..c3dff0e019801904 100644 |
||||
--- a/support/support_format_dns_packet.c |
||||
+++ b/support/support_format_dns_packet.c |
||||
@@ -101,6 +101,17 @@ extract_name (struct in_buffer full, struct in_buffer *in, struct dname *value) |
||||
return true; |
||||
} |
||||
|
||||
+static void |
||||
+extract_name_data (struct in_buffer full, struct in_buffer *rdata, |
||||
+ const struct dname *owner, const char *typename, FILE *out) |
||||
+{ |
||||
+ struct dname name; |
||||
+ if (extract_name (full, rdata, &name)) |
||||
+ fprintf (out, "data: %s %s %s\n", owner->name, typename, name.name); |
||||
+ else |
||||
+ fprintf (out, "error: malformed CNAME/PTR record\n"); |
||||
+} |
||||
+ |
||||
char * |
||||
support_format_dns_packet (const unsigned char *buffer, size_t length) |
||||
{ |
||||
@@ -206,14 +217,11 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) |
||||
} |
||||
break; |
||||
case T_CNAME: |
||||
+ extract_name_data (full, &rdata, &rname, "CNAME", mem.out); |
||||
+ break; |
||||
case T_PTR: |
||||
- { |
||||
- struct dname name; |
||||
- if (extract_name (full, &rdata, &name)) |
||||
- fprintf (mem.out, "name: %s\n", name.name); |
||||
- else |
||||
- fprintf (mem.out, "error: malformed CNAME/PTR record\n"); |
||||
- } |
||||
+ extract_name_data (full, &rdata, &rname, "PTR", mem.out); |
||||
+ break; |
||||
} |
||||
} |
||||
|
||||
diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c |
||||
index 03ff59457e3bdde8..5596db1785009557 100644 |
||||
--- a/support/tst-support_format_dns_packet.c |
||||
+++ b/support/tst-support_format_dns_packet.c |
||||
@@ -85,8 +85,8 @@ test_multiple_cnames (void) |
||||
"\xc0\x00\x02\x01"; |
||||
check_packet (packet, sizeof (packet) - 1, __func__, |
||||
"name: www.example\n" |
||||
- "name: www1.example\n" |
||||
- "name: www2.example\n" |
||||
+ "data: www.example CNAME www1.example\n" |
||||
+ "data: www1.example CNAME www2.example\n" |
||||
"address: 192.0.2.1\n"); |
||||
} |
||||
|
@ -0,0 +1,941 @@
@@ -0,0 +1,941 @@
|
||||
commit f282cdbe7f436c75864e5640a409a10485e9abb2 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Jun 24 18:16:41 2022 +0200 |
||||
|
||||
resolv: Implement no-aaaa stub resolver option |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile |
||||
index 59e599535c7aa6eb..e8269dcb5bcf216b 100644 |
||||
--- a/resolv/Makefile |
||||
+++ b/resolv/Makefile |
||||
@@ -51,6 +51,7 @@ routines := \ |
||||
nss_dns_functions \ |
||||
res-close \ |
||||
res-name-checking \ |
||||
+ res-noaaaa \ |
||||
res-state \ |
||||
res_context_hostalias \ |
||||
res_enable_icmp \ |
||||
@@ -93,6 +94,7 @@ tests += \ |
||||
tst-resolv-binary \ |
||||
tst-resolv-edns \ |
||||
tst-resolv-network \ |
||||
+ tst-resolv-noaaaa \ |
||||
tst-resolv-nondecimal \ |
||||
tst-resolv-res_init-multi \ |
||||
tst-resolv-search \ |
||||
@@ -256,6 +258,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ |
||||
$(shared-thread-library) |
||||
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \ |
||||
$(shared-thread-library) |
||||
+$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) |
||||
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) |
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) |
||||
$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) |
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c |
||||
index 7248ade18db5ba47..6e83fca1c5b1f98c 100644 |
||||
--- a/resolv/nss_dns/dns-host.c |
||||
+++ b/resolv/nss_dns/dns-host.c |
||||
@@ -125,6 +125,14 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, |
||||
char *buffer, size_t buflen, |
||||
int *errnop, int *h_errnop, |
||||
int32_t *ttlp); |
||||
+static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1, |
||||
+ int anslen1, |
||||
+ const char *qname, |
||||
+ struct gaih_addrtuple **pat, |
||||
+ char *buffer, size_t buflen, |
||||
+ int *errnop, int *h_errnop, |
||||
+ int32_t *ttlp); |
||||
+ |
||||
|
||||
static enum nss_status gethostbyname3_context (struct resolv_context *ctx, |
||||
const char *name, int af, |
||||
@@ -370,17 +378,31 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, |
||||
int resplen2 = 0; |
||||
int ans2p_malloced = 0; |
||||
|
||||
+ |
||||
int olderr = errno; |
||||
- int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, |
||||
+ int n; |
||||
+ |
||||
+ if ((ctx->resp->options & RES_NOAAAA) == 0) |
||||
+ { |
||||
+ n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, |
||||
host_buffer.buf->buf, 2048, &host_buffer.ptr, |
||||
&ans2p, &nans2p, &resplen2, &ans2p_malloced); |
||||
- if (n >= 0) |
||||
- { |
||||
- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, |
||||
- resplen2, name, pat, buffer, buflen, |
||||
- errnop, herrnop, ttlp); |
||||
+ if (n >= 0) |
||||
+ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, |
||||
+ resplen2, name, pat, buffer, buflen, |
||||
+ errnop, herrnop, ttlp); |
||||
} |
||||
else |
||||
+ { |
||||
+ n = __res_context_search (ctx, name, C_IN, T_A, |
||||
+ host_buffer.buf->buf, 2048, NULL, |
||||
+ NULL, NULL, NULL, NULL); |
||||
+ if (n >= 0) |
||||
+ status = gaih_getanswer_noaaaa (host_buffer.buf, n, |
||||
+ name, pat, buffer, buflen, |
||||
+ errnop, herrnop, ttlp); |
||||
+ } |
||||
+ if (n < 0) |
||||
{ |
||||
switch (errno) |
||||
{ |
||||
@@ -1388,3 +1410,21 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, |
||||
|
||||
return status; |
||||
} |
||||
+ |
||||
+/* Variant of gaih_getanswer without a second (AAAA) response. */ |
||||
+static enum nss_status |
||||
+gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname, |
||||
+ struct gaih_addrtuple **pat, |
||||
+ char *buffer, size_t buflen, |
||||
+ int *errnop, int *h_errnop, int32_t *ttlp) |
||||
+{ |
||||
+ int first = 1; |
||||
+ |
||||
+ enum nss_status status = NSS_STATUS_NOTFOUND; |
||||
+ if (anslen1 > 0) |
||||
+ status = gaih_getanswer_slice (answer1, anslen1, qname, |
||||
+ &pat, &buffer, &buflen, |
||||
+ errnop, h_errnop, ttlp, |
||||
+ &first); |
||||
+ return status; |
||||
+} |
||||
diff --git a/resolv/res-noaaaa.c b/resolv/res-noaaaa.c |
||||
new file mode 100644 |
||||
index 0000000000000000..4ba197664a86aed7 |
||||
--- /dev/null |
||||
+++ b/resolv/res-noaaaa.c |
||||
@@ -0,0 +1,143 @@ |
||||
+/* Implement suppression of AAAA queries. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <resolv.h> |
||||
+#include <string.h> |
||||
+#include <resolv-internal.h> |
||||
+#include <resolv_context.h> |
||||
+#include <arpa/nameser.h> |
||||
+ |
||||
+/* Returns true if the question type at P matches EXPECTED, and the |
||||
+ class is IN. */ |
||||
+static bool |
||||
+qtype_matches (const unsigned char *p, int expected) |
||||
+{ |
||||
+ /* This assumes that T_A/C_IN constants are less than 256, which |
||||
+ they are. */ |
||||
+ return p[0] == 0 && p[1] == expected && p[2] == 0 && p[3] == C_IN; |
||||
+} |
||||
+ |
||||
+/* Handle RES_NOAAAA translation of AAAA queries. To produce a Name |
||||
+ Error (NXDOMAIN) repsonse for domain names that do not exist, it is |
||||
+ still necessary to send a query. Using question type A is a |
||||
+ conservative choice. In the returned answer, it is necessary to |
||||
+ switch back the question type to AAAA. */ |
||||
+bool |
||||
+__res_handle_no_aaaa (struct resolv_context *ctx, |
||||
+ const unsigned char *buf, int buflen, |
||||
+ unsigned char *ans, int anssiz, int *result) |
||||
+{ |
||||
+ /* AAAA mode is not active, or the query looks invalid (will not be |
||||
+ able to be parsed). */ |
||||
+ if ((ctx->resp->options & RES_NOAAAA) == 0 |
||||
+ || buflen <= sizeof (HEADER)) |
||||
+ return false; |
||||
+ |
||||
+ /* The replacement A query is produced here. */ |
||||
+ struct |
||||
+ { |
||||
+ HEADER header; |
||||
+ unsigned char question[NS_MAXCDNAME + 4]; |
||||
+ } replacement; |
||||
+ memcpy (&replacement.header, buf, sizeof (replacement.header)); |
||||
+ |
||||
+ if (replacement.header.qr |
||||
+ || replacement.header.opcode != 0 |
||||
+ || replacement.header.rcode != 0 |
||||
+ || ntohs (replacement.header.qdcount) != 1 |
||||
+ || ntohs (replacement.header.ancount) != 0 |
||||
+ || ntohs (replacement.header.nscount) != 0) |
||||
+ /* Not a well-formed question. Let the core resolver code produce |
||||
+ the proper error. */ |
||||
+ return false; |
||||
+ |
||||
+ /* Disable EDNS0. */ |
||||
+ replacement.header.arcount = htons (0); |
||||
+ |
||||
+ /* Extract the QNAME. */ |
||||
+ int ret = __ns_name_unpack (buf, buf + buflen, buf + sizeof (HEADER), |
||||
+ replacement.question, NS_MAXCDNAME); |
||||
+ if (ret < 0) |
||||
+ /* Format error. */ |
||||
+ return false; |
||||
+ |
||||
+ /* Compute the end of the question name. */ |
||||
+ const unsigned char *after_question = buf + sizeof (HEADER) + ret; |
||||
+ |
||||
+ /* Check that we are dealing with an AAAA query. */ |
||||
+ if (buf + buflen - after_question < 4 |
||||
+ || !qtype_matches (after_question, T_AAAA)) |
||||
+ return false; |
||||
+ |
||||
+ /* Find the place to store the type/class data in the replacement |
||||
+ query. */ |
||||
+ after_question = replacement.question; |
||||
+ /* This cannot fail because __ns_name_unpack above produced a valid |
||||
+ domain name. */ |
||||
+ (void) __ns_name_skip (&after_question, &replacement.question[NS_MAXCDNAME]); |
||||
+ unsigned char *start_of_query = (unsigned char *) &replacement; |
||||
+ const unsigned char *end_of_query = after_question + 4; |
||||
+ |
||||
+ /* Produce an A/IN query. */ |
||||
+ { |
||||
+ unsigned char *p = (unsigned char *) after_question; |
||||
+ p[0] = 0; |
||||
+ p[1] = T_A; |
||||
+ p[2] = 0; |
||||
+ p[3] = C_IN; |
||||
+ } |
||||
+ |
||||
+ /* Clear the output buffer, to avoid reading undefined data when |
||||
+ rewriting the result from A to AAAA. */ |
||||
+ memset (ans, 0, anssiz); |
||||
+ |
||||
+ /* Always perform the message translation, independent of the error |
||||
+ code. */ |
||||
+ ret = __res_context_send (ctx, |
||||
+ start_of_query, end_of_query - start_of_query, |
||||
+ NULL, 0, ans, anssiz, |
||||
+ NULL, NULL, NULL, NULL, NULL); |
||||
+ |
||||
+ /* Patch in the AAAA question type if there is room and the A query |
||||
+ type was received. */ |
||||
+ after_question = ans + sizeof (HEADER); |
||||
+ if (__ns_name_skip (&after_question, ans + anssiz) == 0 |
||||
+ && ans + anssiz - after_question >= 4 |
||||
+ && qtype_matches (after_question, T_A)) |
||||
+ { |
||||
+ ((unsigned char *) after_question)[1] = T_AAAA; |
||||
+ |
||||
+ /* Create an aligned copy of the header. Hide all data except |
||||
+ the question from the response. Put back the header. There is |
||||
+ no need to change the response code. The zero answer count turns |
||||
+ a positive response with data into a no-data response. */ |
||||
+ memcpy (&replacement.header, ans, sizeof (replacement.header)); |
||||
+ replacement.header.ancount = htons (0); |
||||
+ replacement.header.nscount = htons (0); |
||||
+ replacement.header.arcount = htons (0); |
||||
+ memcpy (ans, &replacement.header, sizeof (replacement.header)); |
||||
+ |
||||
+ /* Truncate the reply. */ |
||||
+ if (ret <= 0) |
||||
+ *result = ret; |
||||
+ else |
||||
+ *result = after_question - ans + 4; |
||||
+ } |
||||
+ |
||||
+ return true; |
||||
+} |
||||
diff --git a/resolv/res_debug.c b/resolv/res_debug.c |
||||
index 030df0aa90c9f34f..b0fe69b1aa5186a0 100644 |
||||
--- a/resolv/res_debug.c |
||||
+++ b/resolv/res_debug.c |
||||
@@ -613,6 +613,7 @@ p_option(u_long option) { |
||||
case RES_NOTLDQUERY: return "no-tld-query"; |
||||
case RES_NORELOAD: return "no-reload"; |
||||
case RES_TRUSTAD: return "trust-ad"; |
||||
+ case RES_NOAAAA: return "no-aaaa"; |
||||
/* XXX nonreentrant */ |
||||
default: sprintf(nbuf, "?0x%lx?", (u_long)option); |
||||
return (nbuf); |
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c |
||||
index 6b2936eda9618ac9..8bde915903565f60 100644 |
||||
--- a/resolv/res_init.c |
||||
+++ b/resolv/res_init.c |
||||
@@ -695,6 +695,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options) |
||||
{ STRnLEN ("no-reload"), 0, RES_NORELOAD }, |
||||
{ STRnLEN ("use-vc"), 0, RES_USEVC }, |
||||
{ STRnLEN ("trust-ad"), 0, RES_TRUSTAD }, |
||||
+ { STRnLEN ("no-aaaa"), 0, RES_NOAAAA }, |
||||
}; |
||||
#define noptions (sizeof (options) / sizeof (options[0])) |
||||
for (int i = 0; i < noptions; ++i) |
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c |
||||
index 75b0e5f2f7b51eb2..2f3c28cfc8c0d832 100644 |
||||
--- a/resolv/res_query.c |
||||
+++ b/resolv/res_query.c |
||||
@@ -204,10 +204,26 @@ __res_context_query (struct resolv_context *ctx, const char *name, |
||||
free (buf); |
||||
return (n); |
||||
} |
||||
- assert (answerp == NULL || (void *) *answerp == (void *) answer); |
||||
- n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer, |
||||
- anslen, answerp, answerp2, nanswerp2, resplen2, |
||||
- answerp2_malloced); |
||||
+ |
||||
+ /* Suppress AAAA lookups if required. __res_handle_no_aaaa |
||||
+ checks RES_NOAAAA first, so avoids parsing the |
||||
+ just-generated query packet in most cases. nss_dns avoids |
||||
+ using T_QUERY_A_AND_AAAA in RES_NOAAAA mode, so there is no |
||||
+ need to handle it here. */ |
||||
+ if (type == T_AAAA && __res_handle_no_aaaa (ctx, query1, nquery1, |
||||
+ answer, anslen, &n)) |
||||
+ /* There must be no second query for AAAA queries. The code |
||||
+ below is still needed to translate NODATA responses. */ |
||||
+ assert (query2 == NULL); |
||||
+ else |
||||
+ { |
||||
+ assert (answerp == NULL || (void *) *answerp == (void *) answer); |
||||
+ n = __res_context_send (ctx, query1, nquery1, query2, nquery2, |
||||
+ answer, anslen, |
||||
+ answerp, answerp2, nanswerp2, resplen2, |
||||
+ answerp2_malloced); |
||||
+ } |
||||
+ |
||||
if (use_malloc) |
||||
free (buf); |
||||
if (n < 0) { |
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c |
||||
index 9f86f5fe47194887..8ac6a307b40fa2ca 100644 |
||||
--- a/resolv/res_send.c |
||||
+++ b/resolv/res_send.c |
||||
@@ -438,8 +438,13 @@ context_send_common (struct resolv_context *ctx, |
||||
RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); |
||||
return -1; |
||||
} |
||||
- int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, |
||||
- NULL, NULL, NULL, NULL, NULL); |
||||
+ |
||||
+ int result; |
||||
+ if (__res_handle_no_aaaa (ctx, buf, buflen, ans, anssiz, &result)) |
||||
+ return result; |
||||
+ |
||||
+ result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, |
||||
+ NULL, NULL, NULL, NULL, NULL); |
||||
__resolv_context_put (ctx); |
||||
return result; |
||||
} |
||||
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h |
||||
index 216e47ed42076b72..8ab02fc9e648d30f 100644 |
||||
--- a/resolv/resolv-internal.h |
||||
+++ b/resolv/resolv-internal.h |
||||
@@ -78,6 +78,14 @@ int __res_context_send (struct resolv_context *, const unsigned char *, int, |
||||
int *, int *, int *); |
||||
libc_hidden_proto (__res_context_send) |
||||
|
||||
+/* Return true if the query has been handled in RES_NOAAAA mode. For |
||||
+ that, RES_NOAAAA must be active, and the question type must be AAAA. |
||||
+ The caller is expected to return *RESULT as the return value. */ |
||||
+bool __res_handle_no_aaaa (struct resolv_context *ctx, |
||||
+ const unsigned char *buf, int buflen, |
||||
+ unsigned char *ans, int anssiz, int *result) |
||||
+ attribute_hidden; |
||||
+ |
||||
/* Internal function similar to res_hostalias. */ |
||||
const char *__res_context_hostalias (struct resolv_context *, |
||||
const char *, char *, size_t); |
||||
diff --git a/resolv/resolv.h b/resolv/resolv.h |
||||
index e7c8d44645912ddf..3a79ffea57a6916f 100644 |
||||
--- a/resolv/resolv.h |
||||
+++ b/resolv/resolv.h |
||||
@@ -132,6 +132,7 @@ struct res_sym { |
||||
as a TLD. */ |
||||
#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */ |
||||
#define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */ |
||||
+#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */ |
||||
|
||||
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) |
||||
|
||||
diff --git a/resolv/tst-resolv-noaaaa.c b/resolv/tst-resolv-noaaaa.c |
||||
new file mode 100644 |
||||
index 0000000000000000..56b25f88a58ad286 |
||||
--- /dev/null |
||||
+++ b/resolv/tst-resolv-noaaaa.c |
||||
@@ -0,0 +1,533 @@ |
||||
+/* Test the RES_NOAAAA resolver option. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <errno.h> |
||||
+#include <netdb.h> |
||||
+#include <resolv.h> |
||||
+#include <stdlib.h> |
||||
+#include <support/check.h> |
||||
+#include <support/check_nss.h> |
||||
+#include <support/resolv_test.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+/* Used to keep track of the number of queries. */ |
||||
+static volatile unsigned int queries; |
||||
+ |
||||
+static void |
||||
+response (const struct resolv_response_context *ctx, |
||||
+ struct resolv_response_builder *b, |
||||
+ const char *qname, uint16_t qclass, uint16_t qtype) |
||||
+{ |
||||
+ /* Each test should only send one query. */ |
||||
+ ++queries; |
||||
+ TEST_COMPARE (queries, 1); |
||||
+ |
||||
+ /* AAAA queries are supposed to be disabled. */ |
||||
+ TEST_VERIFY (qtype != T_AAAA); |
||||
+ TEST_COMPARE (qclass, C_IN); |
||||
+ |
||||
+ /* The only other query type besides A is PTR. */ |
||||
+ if (qtype != T_A) |
||||
+ TEST_COMPARE (qtype, T_PTR); |
||||
+ |
||||
+ int an, ns, ar; |
||||
+ char *tail; |
||||
+ if (sscanf (qname, "an%d.ns%d.ar%d.%ms", &an, &ns, &ar, &tail) != 4) |
||||
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname); |
||||
+ TEST_COMPARE_STRING (tail, "example"); |
||||
+ free (tail); |
||||
+ |
||||
+ if (an < 0 || ns < 0 || ar < 0) |
||||
+ { |
||||
+ struct resolv_response_flags flags = { .rcode = NXDOMAIN, }; |
||||
+ resolv_response_init (b, flags); |
||||
+ resolv_response_add_question (b, qname, qclass, qtype); |
||||
+ return; |
||||
+ } |
||||
+ |
||||
+ struct resolv_response_flags flags = {}; |
||||
+ resolv_response_init (b, flags); |
||||
+ resolv_response_add_question (b, qname, qclass, qtype); |
||||
+ |
||||
+ resolv_response_section (b, ns_s_an); |
||||
+ for (int i = 0; i < an; ++i) |
||||
+ { |
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 60); |
||||
+ switch (qtype) |
||||
+ { |
||||
+ case T_A: |
||||
+ char ipv4[4] = {192, 0, 2, i + 1}; |
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); |
||||
+ break; |
||||
+ |
||||
+ case T_PTR: |
||||
+ char *name = xasprintf ("ptr-%d", i); |
||||
+ resolv_response_add_name (b, name); |
||||
+ free (name); |
||||
+ break; |
||||
+ } |
||||
+ resolv_response_close_record (b); |
||||
+ } |
||||
+ |
||||
+ resolv_response_section (b, ns_s_ns); |
||||
+ for (int i = 0; i < ns; ++i) |
||||
+ { |
||||
+ resolv_response_open_record (b, qname, qclass, T_NS, 60); |
||||
+ char *name = xasprintf ("ns%d.example.net", i); |
||||
+ resolv_response_add_name (b, name); |
||||
+ free (name); |
||||
+ resolv_response_close_record (b); |
||||
+ } |
||||
+ |
||||
+ resolv_response_section (b, ns_s_ar); |
||||
+ int addr = 1; |
||||
+ for (int i = 0; i < ns; ++i) |
||||
+ { |
||||
+ char *name = xasprintf ("ns%d.example.net", i); |
||||
+ for (int j = 0; j < ar; ++j) |
||||
+ { |
||||
+ resolv_response_open_record (b, name, qclass, T_A, 60); |
||||
+ char ipv4[4] = {192, 0, 2, addr}; |
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); |
||||
+ resolv_response_close_record (b); |
||||
+ |
||||
+ resolv_response_open_record (b, name, qclass, T_AAAA, 60); |
||||
+ char ipv6[16] |
||||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr}; |
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); |
||||
+ resolv_response_close_record (b); |
||||
+ |
||||
+ ++addr; |
||||
+ } |
||||
+ free (name); |
||||
+ } |
||||
+} |
||||
+ |
||||
+/* Number of modes. Lowest bit encodes *n* function vs implicit _res |
||||
+ argument. The mode numbers themselves are arbitrary. */ |
||||
+enum { mode_count = 8 }; |
||||
+ |
||||
+/* res_send-like modes do not perform error translation. */ |
||||
+enum { first_send_mode = 6 }; |
||||
+ |
||||
+static int |
||||
+libresolv_query (unsigned int mode, const char *qname, uint16_t qtype, |
||||
+ unsigned char *buf, size_t buflen) |
||||
+{ |
||||
+ int saved_errno = errno; |
||||
+ |
||||
+ TEST_VERIFY_EXIT (mode < mode_count); |
||||
+ |
||||
+ switch (mode) |
||||
+ { |
||||
+ case 0: |
||||
+ return res_query (qname, C_IN, qtype, buf, buflen); |
||||
+ case 1: |
||||
+ return res_nquery (&_res, qname, C_IN, qtype, buf, buflen); |
||||
+ case 2: |
||||
+ return res_search (qname, C_IN, qtype, buf, buflen); |
||||
+ case 3: |
||||
+ return res_nsearch (&_res, qname, C_IN, qtype, buf, buflen); |
||||
+ case 4: |
||||
+ return res_querydomain (qname, "", C_IN, qtype, buf, buflen); |
||||
+ case 5: |
||||
+ return res_nquerydomain (&_res, qname, "", C_IN, qtype, buf, buflen); |
||||
+ case 6: |
||||
+ { |
||||
+ unsigned char querybuf[512]; |
||||
+ int ret = res_mkquery (QUERY, qname, C_IN, qtype, |
||||
+ NULL, 0, NULL, querybuf, sizeof (querybuf)); |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ errno = saved_errno; |
||||
+ return res_send (querybuf, ret, buf, buflen); |
||||
+ } |
||||
+ case 7: |
||||
+ { |
||||
+ unsigned char querybuf[512]; |
||||
+ int ret = res_nmkquery (&_res, QUERY, qname, C_IN, qtype, |
||||
+ NULL, 0, NULL, querybuf, sizeof (querybuf)); |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ errno = saved_errno; |
||||
+ return res_nsend (&_res, querybuf, ret, buf, buflen); |
||||
+ } |
||||
+ } |
||||
+ __builtin_unreachable (); |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ struct resolv_test *obj = resolv_test_start |
||||
+ ((struct resolv_redirect_config) |
||||
+ { |
||||
+ .response_callback = response |
||||
+ }); |
||||
+ |
||||
+ _res.options |= RES_NOAAAA; |
||||
+ |
||||
+ check_hostent ("an1.ns2.ar1.example", |
||||
+ gethostbyname ("an1.ns2.ar1.example"), |
||||
+ "name: an1.ns2.ar1.example\n" |
||||
+ "address: 192.0.2.1\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an0.ns2.ar1.example", |
||||
+ gethostbyname ("an0.ns2.ar1.example"), |
||||
+ "error: NO_ADDRESS\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an-1.ns2.ar1.example", |
||||
+ gethostbyname ("an-1.ns2.ar1.example"), |
||||
+ "error: HOST_NOT_FOUND\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ check_hostent ("an1.ns2.ar1.example AF_INET", |
||||
+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET), |
||||
+ "name: an1.ns2.ar1.example\n" |
||||
+ "address: 192.0.2.1\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an0.ns2.ar1.example AF_INET", |
||||
+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET), |
||||
+ "error: NO_ADDRESS\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an-1.ns2.ar1.example AF_INET", |
||||
+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET), |
||||
+ "error: HOST_NOT_FOUND\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ check_hostent ("an1.ns2.ar1.example AF_INET6", |
||||
+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET6), |
||||
+ "error: NO_ADDRESS\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an0.ns2.ar1.example AF_INET6", |
||||
+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET6), |
||||
+ "error: NO_ADDRESS\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an-1.ns2.ar1.example AF_INET6", |
||||
+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET6), |
||||
+ "error: HOST_NOT_FOUND\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* Multiple addresses. */ |
||||
+ check_hostent ("an2.ns0.ar0.example", |
||||
+ gethostbyname ("an2.ns0.ar0.example"), |
||||
+ "name: an2.ns0.ar0.example\n" |
||||
+ "address: 192.0.2.1\n" |
||||
+ "address: 192.0.2.2\n"); |
||||
+ queries = 0; |
||||
+ check_hostent ("an2.ns0.ar0.example AF_INET6", |
||||
+ gethostbyname2 ("an2.ns0.ar0.example", AF_INET6), |
||||
+ "error: NO_ADDRESS\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* getaddrinfo checks with one address. */ |
||||
+ struct addrinfo *ai; |
||||
+ int ret; |
||||
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai, ret, |
||||
+ "address: STREAM/TCP 192.0.2.1 80\n"); |
||||
+ freeaddrinfo (ai); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET6, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai, ret, |
||||
+ "error: No address associated with hostname\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_UNSPEC, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC)", ai, ret, |
||||
+ "address: STREAM/TCP 192.0.2.1 80\n"); |
||||
+ freeaddrinfo (ai); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* getaddrinfo checks with three addresses. */ |
||||
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai, ret, |
||||
+ "address: STREAM/TCP 192.0.2.1 80\n" |
||||
+ "address: STREAM/TCP 192.0.2.2 80\n" |
||||
+ "address: STREAM/TCP 192.0.2.3 80\n"); |
||||
+ freeaddrinfo (ai); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET6, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai, ret, |
||||
+ "error: No address associated with hostname\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_UNSPEC, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC)", ai, ret, |
||||
+ "address: STREAM/TCP 192.0.2.1 80\n" |
||||
+ "address: STREAM/TCP 192.0.2.2 80\n" |
||||
+ "address: STREAM/TCP 192.0.2.3 80\n"); |
||||
+ freeaddrinfo (ai); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* getaddrinfo checks with no address. */ |
||||
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai, ret, |
||||
+ "error: No address associated with hostname\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET6, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai, ret, |
||||
+ "error: No address associated with hostname\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_UNSPEC, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, |
||||
+ "error: No address associated with hostname\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* getaddrinfo checks with NXDOMAIN. */ |
||||
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai, ret, |
||||
+ "error: Name or service not known\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_INET6, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai, ret, |
||||
+ "error: Name or service not known\n"); |
||||
+ queries = 0; |
||||
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", |
||||
+ &(struct addrinfo) |
||||
+ { |
||||
+ .ai_family = AF_UNSPEC, |
||||
+ .ai_socktype = SOCK_STREAM, |
||||
+ }, &ai); |
||||
+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, |
||||
+ "error: Name or service not known\n"); |
||||
+ queries = 0; |
||||
+ |
||||
+ for (unsigned int mode = 0; mode < mode_count; ++mode) |
||||
+ { |
||||
+ unsigned char *buf; |
||||
+ int ret; |
||||
+ |
||||
+ /* Response for A. */ |
||||
+ buf = malloc (512); |
||||
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_A, buf, 512); |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, |
||||
+ "name: an1.ns2.ar1.example\n" |
||||
+ "address: 192.0.2.1\n"); |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NODATA response for A. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_A, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, NO_ADDRESS); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); |
||||
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, |
||||
+ "name: an0.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NXDOMAIN response for A. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_A, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); |
||||
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, |
||||
+ "name: an-1.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* Response for PTR. */ |
||||
+ buf = malloc (512); |
||||
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_PTR, buf, 512); |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, |
||||
+ "name: an1.ns2.ar1.example\n" |
||||
+ "data: an1.ns2.ar1.example PTR ptr-0\n"); |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NODATA response for PTR. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_PTR, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, NO_ADDRESS); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); |
||||
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, |
||||
+ "name: an0.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NXDOMAIN response for PTR. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_PTR, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); |
||||
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, |
||||
+ "name: an-1.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NODATA response for AAAA. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_AAAA, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, NO_ADDRESS); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); |
||||
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, |
||||
+ "name: an1.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NODATA response for AAAA (original is already NODATA). */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_AAAA, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, NO_ADDRESS); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0); |
||||
+ check_dns_packet ("an0.ns2.ar1.example A", buf, ret, |
||||
+ "name: an0.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ |
||||
+ /* NXDOMAIN response. */ |
||||
+ buf = malloc (512); |
||||
+ errno = 0; |
||||
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_AAAA, buf, 512); |
||||
+ if (mode < first_send_mode) |
||||
+ { |
||||
+ TEST_COMPARE (ret, -1); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND); |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ TEST_VERIFY_EXIT (ret > 0); |
||||
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); |
||||
+ check_dns_packet ("an-1.ns2.ar1.example A", buf, ret, |
||||
+ "name: an-1.ns2.ar1.example\n"); |
||||
+ } |
||||
+ free (buf); |
||||
+ queries = 0; |
||||
+ } |
||||
+ |
||||
+ resolv_test_end (obj); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c |
||||
index c87596762fcb23b1..28ed9c2eb150532d 100644 |
||||
--- a/resolv/tst-resolv-res_init-skeleton.c |
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c |
||||
@@ -128,6 +128,7 @@ print_resp (FILE *fp, res_state resp) |
||||
print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query"); |
||||
print_option_flag (fp, &options, RES_NORELOAD, "no-reload"); |
||||
print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad"); |
||||
+ print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa"); |
||||
fputc ('\n', fp); |
||||
if (options != 0) |
||||
fprintf (fp, "; error: unresolved option bits: 0x%x\n", options); |
||||
@@ -721,6 +722,15 @@ struct test_case test_cases[] = |
||||
"nameserver 192.0.2.1\n" |
||||
"; nameserver[0]: [192.0.2.1]:53\n" |
||||
}, |
||||
+ {.name = "no-aaaa flag", |
||||
+ .conf = "options no-aaaa\n" |
||||
+ "nameserver 192.0.2.1\n", |
||||
+ .expected = "options no-aaaa\n" |
||||
+ "search example.com\n" |
||||
+ "; search[0]: example.com\n" |
||||
+ "nameserver 192.0.2.1\n" |
||||
+ "; nameserver[0]: [192.0.2.1]:53\n" |
||||
+ }, |
||||
{ NULL } |
||||
}; |
||||
|
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
commit 0351c75c5f94134fcec0e778e8cf86d149f8bbfb |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Feb 3 16:52:52 2022 -0300 |
||||
|
||||
linux: Fix missing __convert_scm_timestamps (BZ #28860) |
||||
|
||||
Commit 948ce73b31 made recvmsg/recvmmsg to always call |
||||
__convert_scm_timestamps for 64 bit time_t symbol, so adjust it to |
||||
always build it for __TIMESIZE != 64. |
||||
|
||||
It fixes build for architecture with 32 bit time_t support when |
||||
configured with minimum kernel of 5.1. |
||||
|
||||
(cherry-picked from 798d716df71fb23dc89d1d5dba1fc26a1b5c0024) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c |
||||
index 5d3c4199e0b32944..953ce97bd2e03849 100644 |
||||
--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c |
||||
+++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c |
||||
@@ -16,9 +16,10 @@ |
||||
License along with the GNU C Library; if not, see |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
-#include <kernel-features.h> |
||||
+#include <bits/wordsize.h> |
||||
+#include <bits/timesize.h> |
||||
|
||||
-#ifndef __ASSUME_TIME64_SYSCALLS |
||||
+#if __TIMESIZE != 64 |
||||
# include <stdint.h> |
||||
# include <string.h> |
||||
# include <sys/socket.h> |
@ -0,0 +1,192 @@
@@ -0,0 +1,192 @@
|
||||
commit 007e054d786be340699c634e3a3b30ab1fde1a7a |
||||
Author: Dmitry V. Levin <ldv@altlinux.org> |
||||
Date: Sat Feb 5 08:00:00 2022 +0000 |
||||
|
||||
linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ #28865] |
||||
|
||||
get_nprocs() and get_nprocs_conf() use various methods to obtain an |
||||
accurate number of processors. Re-introduce __get_nprocs_sched() as |
||||
a source of information, and fix the order in which these methods are |
||||
used to return the most accurate information. The primary source of |
||||
information used in both functions remains unchanged. |
||||
|
||||
This also changes __get_nprocs_sched() error return value from 2 to 0, |
||||
but all its users are already prepared to handle that. |
||||
|
||||
Old fallback order: |
||||
get_nprocs: |
||||
/sys/devices/system/cpu/online -> /proc/stat -> 2 |
||||
get_nprocs_conf: |
||||
/sys/devices/system/cpu/ -> /proc/stat -> 2 |
||||
|
||||
New fallback order: |
||||
get_nprocs: |
||||
/sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2 |
||||
get_nprocs_conf: |
||||
/sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2 |
||||
|
||||
Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc") |
||||
Closes: BZ #28865 |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
|
||||
(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c |
||||
index 7babd947aa902e77..327802b14c7326a3 100644 |
||||
--- a/sysdeps/unix/sysv/linux/getsysstats.c |
||||
+++ b/sysdeps/unix/sysv/linux/getsysstats.c |
||||
@@ -51,9 +51,8 @@ __get_nprocs_sched (void) |
||||
is an arbitrary values assuming such systems should be rare and there |
||||
is no offline cpus. */ |
||||
return max_num_cpus; |
||||
- /* Some other error. 2 is conservative (not a uniprocessor system, so |
||||
- atomics are needed). */ |
||||
- return 2; |
||||
+ /* Some other error. */ |
||||
+ return 0; |
||||
} |
||||
|
||||
static char * |
||||
@@ -109,22 +108,19 @@ next_line (int fd, char *const buffer, char **cp, char **re, |
||||
} |
||||
|
||||
static int |
||||
-get_nproc_stat (char *buffer, size_t buffer_size) |
||||
+get_nproc_stat (void) |
||||
{ |
||||
+ enum { buffer_size = 1024 }; |
||||
+ char buffer[buffer_size]; |
||||
char *buffer_end = buffer + buffer_size; |
||||
char *cp = buffer_end; |
||||
char *re = buffer_end; |
||||
- |
||||
- /* Default to an SMP system in case we cannot obtain an accurate |
||||
- number. */ |
||||
- int result = 2; |
||||
+ int result = 0; |
||||
|
||||
const int flags = O_RDONLY | O_CLOEXEC; |
||||
int fd = __open_nocancel ("/proc/stat", flags); |
||||
if (fd != -1) |
||||
{ |
||||
- result = 0; |
||||
- |
||||
char *l; |
||||
while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) |
||||
/* The current format of /proc/stat has all the cpu* entries |
||||
@@ -140,8 +136,8 @@ get_nproc_stat (char *buffer, size_t buffer_size) |
||||
return result; |
||||
} |
||||
|
||||
-int |
||||
-__get_nprocs (void) |
||||
+static int |
||||
+get_nprocs_cpu_online (void) |
||||
{ |
||||
enum { buffer_size = 1024 }; |
||||
char buffer[buffer_size]; |
||||
@@ -180,7 +176,8 @@ __get_nprocs (void) |
||||
} |
||||
} |
||||
|
||||
- result += m - n + 1; |
||||
+ if (m >= n) |
||||
+ result += m - n + 1; |
||||
|
||||
l = endp; |
||||
if (l < re && *l == ',') |
||||
@@ -189,28 +186,18 @@ __get_nprocs (void) |
||||
while (l < re && *l != '\n'); |
||||
|
||||
__close_nocancel_nostatus (fd); |
||||
- |
||||
- if (result > 0) |
||||
- return result; |
||||
} |
||||
|
||||
- return get_nproc_stat (buffer, buffer_size); |
||||
+ return result; |
||||
} |
||||
-libc_hidden_def (__get_nprocs) |
||||
-weak_alias (__get_nprocs, get_nprocs) |
||||
- |
||||
|
||||
-/* On some architectures it is possible to distinguish between configured |
||||
- and active cpus. */ |
||||
-int |
||||
-__get_nprocs_conf (void) |
||||
+static int |
||||
+get_nprocs_cpu (void) |
||||
{ |
||||
- /* Try to use the sysfs filesystem. It has actual information about |
||||
- online processors. */ |
||||
+ int count = 0; |
||||
DIR *dir = __opendir ("/sys/devices/system/cpu"); |
||||
if (dir != NULL) |
||||
{ |
||||
- int count = 0; |
||||
struct dirent64 *d; |
||||
|
||||
while ((d = __readdir64 (dir)) != NULL) |
||||
@@ -225,12 +212,57 @@ __get_nprocs_conf (void) |
||||
|
||||
__closedir (dir); |
||||
|
||||
- return count; |
||||
} |
||||
+ return count; |
||||
+} |
||||
|
||||
- enum { buffer_size = 1024 }; |
||||
- char buffer[buffer_size]; |
||||
- return get_nproc_stat (buffer, buffer_size); |
||||
+static int |
||||
+get_nprocs_fallback (void) |
||||
+{ |
||||
+ int result; |
||||
+ |
||||
+ /* Try /proc/stat first. */ |
||||
+ result = get_nproc_stat (); |
||||
+ if (result != 0) |
||||
+ return result; |
||||
+ |
||||
+ /* Try sched_getaffinity. */ |
||||
+ result = __get_nprocs_sched (); |
||||
+ if (result != 0) |
||||
+ return result; |
||||
+ |
||||
+ /* We failed to obtain an accurate number. Be conservative: return |
||||
+ the smallest number meaning that this is not a uniprocessor system, |
||||
+ so atomics are needed. */ |
||||
+ return 2; |
||||
+} |
||||
+ |
||||
+int |
||||
+__get_nprocs (void) |
||||
+{ |
||||
+ /* Try /sys/devices/system/cpu/online first. */ |
||||
+ int result = get_nprocs_cpu_online (); |
||||
+ if (result != 0) |
||||
+ return result; |
||||
+ |
||||
+ /* Fall back to /proc/stat and sched_getaffinity. */ |
||||
+ return get_nprocs_fallback (); |
||||
+} |
||||
+libc_hidden_def (__get_nprocs) |
||||
+weak_alias (__get_nprocs, get_nprocs) |
||||
+ |
||||
+/* On some architectures it is possible to distinguish between configured |
||||
+ and active cpus. */ |
||||
+int |
||||
+__get_nprocs_conf (void) |
||||
+{ |
||||
+ /* Try /sys/devices/system/cpu/ first. */ |
||||
+ int result = get_nprocs_cpu (); |
||||
+ if (result != 0) |
||||
+ return result; |
||||
+ |
||||
+ /* Fall back to /proc/stat and sched_getaffinity. */ |
||||
+ return get_nprocs_fallback (); |
||||
} |
||||
libc_hidden_def (__get_nprocs_conf) |
||||
weak_alias (__get_nprocs_conf, get_nprocs_conf) |
@ -0,0 +1,60 @@
@@ -0,0 +1,60 @@
|
||||
commit 04d60ce0f21ffe2a4add148cb37a1942dbad64e2 |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Thu Feb 17 08:10:35 2022 -0800 |
||||
|
||||
string: Add a testcase for wcsncmp with SIZE_MAX [BZ #28755] |
||||
|
||||
Verify that wcsncmp (L("abc"), L("abd"), SIZE_MAX) == 0. The new test |
||||
fails without |
||||
|
||||
commit ddf0992cf57a93200e0c782e2a94d0733a5a0b87 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Sun Jan 9 16:02:21 2022 -0600 |
||||
|
||||
x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755] |
||||
|
||||
and |
||||
|
||||
commit 7e08db3359c86c94918feb33a1182cd0ff3bb10b |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Sun Jan 9 16:02:28 2022 -0600 |
||||
|
||||
x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755] |
||||
|
||||
This is for BZ #28755. |
||||
|
||||
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com> |
||||
|
||||
(cherry picked from commit aa5a720056d37cf24924c138a3dbe6dace98e97c) |
||||
|
||||
diff --git a/string/test-strncmp.c b/string/test-strncmp.c |
||||
index 10b34de8d2acb2a1..97e831d88fd24316 100644 |
||||
--- a/string/test-strncmp.c |
||||
+++ b/string/test-strncmp.c |
||||
@@ -435,6 +435,18 @@ check3 (void) |
||||
} |
||||
} |
||||
|
||||
+static void |
||||
+check4 (void) |
||||
+{ |
||||
+ const CHAR *s1 = L ("abc"); |
||||
+ CHAR *s2 = STRDUP (s1); |
||||
+ |
||||
+ FOR_EACH_IMPL (impl, 0) |
||||
+ check_result (impl, s1, s2, SIZE_MAX, 0); |
||||
+ |
||||
+ free (s2); |
||||
+} |
||||
+ |
||||
int |
||||
test_main (void) |
||||
{ |
||||
@@ -445,6 +457,7 @@ test_main (void) |
||||
check1 (); |
||||
check2 (); |
||||
check3 (); |
||||
+ check4 (); |
||||
|
||||
printf ("%23s", ""); |
||||
FOR_EACH_IMPL (impl, 0) |
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
commit 38e0d2479413ccdbc02b4c9e9e246eca31e956c9 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Tue Feb 15 08:18:15 2022 -0600 |
||||
|
||||
x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ #28896] |
||||
|
||||
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would |
||||
call strcmp-avx2 and wcscmp-avx2 respectively. This would have |
||||
not checks around vzeroupper and would trigger spurious |
||||
aborts. This commit fixes that. |
||||
|
||||
test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on |
||||
AVX2 machines with and without RTM. |
||||
|
||||
Co-authored-by: H.J. Lu <hjl.tools@gmail.com> |
||||
|
||||
(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf) |
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile |
||||
index 36ca1a7126047b86..af934d6ccf1fa337 100644 |
||||
--- a/sysdeps/x86/Makefile |
||||
+++ b/sysdeps/x86/Makefile |
||||
@@ -105,7 +105,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm |
||||
CFLAGS-tst-strchr-rtm.c += -mrtm |
||||
CFLAGS-tst-strcpy-rtm.c += -mrtm |
||||
CFLAGS-tst-strlen-rtm.c += -mrtm |
||||
-CFLAGS-tst-strncmp-rtm.c += -mrtm |
||||
+CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error |
||||
CFLAGS-tst-strrchr-rtm.c += -mrtm |
||||
endif |
||||
|
||||
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c |
||||
index 236ad951b5b59cd1..4d0004b58aae428d 100644 |
||||
--- a/sysdeps/x86/tst-strncmp-rtm.c |
||||
+++ b/sysdeps/x86/tst-strncmp-rtm.c |
||||
@@ -16,6 +16,7 @@ |
||||
License along with the GNU C Library; if not, see |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
+#include <stdint.h> |
||||
#include <tst-string-rtm.h> |
||||
|
||||
#define LOOP 3000 |
||||
@@ -45,8 +46,22 @@ function (void) |
||||
return 1; |
||||
} |
||||
|
||||
+__attribute__ ((noinline, noclone)) |
||||
+static int |
||||
+function_overflow (void) |
||||
+{ |
||||
+ if (strncmp (string1, string2, SIZE_MAX) == 0) |
||||
+ return 0; |
||||
+ else |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
static int |
||||
do_test (void) |
||||
{ |
||||
- return do_test_1 ("strncmp", LOOP, prepare, function); |
||||
+ int status = do_test_1 ("strncmp", LOOP, prepare, function); |
||||
+ if (status != EXIT_SUCCESS) |
||||
+ return status; |
||||
+ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow); |
||||
+ return status; |
||||
} |
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
index 3dfcb1bf803cf9ec..fa70c994fc25dfd8 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
@@ -95,7 +95,7 @@ ENTRY (STRCMP) |
||||
length to bound a valid memory region. In these cases just use |
||||
'wcscmp'. */ |
||||
shrq $56, %rcx |
||||
- jnz __wcscmp_avx2 |
||||
+ jnz OVERFLOW_STRCMP |
||||
# endif |
||||
/* Convert units: from wide to byte char. */ |
||||
shl $2, %RDX_LP |
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S |
||||
index 37d1224bb9b7056b..68bad365ba728eec 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S |
||||
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S |
||||
@@ -1,3 +1,4 @@ |
||||
#define STRCMP __strncmp_avx2_rtm |
||||
#define USE_AS_STRNCMP 1 |
||||
+#define OVERFLOW_STRCMP __strcmp_avx2_rtm |
||||
#include "strcmp-avx2-rtm.S" |
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S |
||||
index 1678bcc235a4bc6a..f138e9f1fdcf277c 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strncmp-avx2.S |
||||
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S |
||||
@@ -1,3 +1,4 @@ |
||||
#define STRCMP __strncmp_avx2 |
||||
#define USE_AS_STRNCMP 1 |
||||
+#define OVERFLOW_STRCMP __strcmp_avx2 |
||||
#include "strcmp-avx2.S" |
||||
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S |
||||
index 4e88c70cc696b82d..f467582cbedd4535 100644 |
||||
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S |
||||
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S |
||||
@@ -1,5 +1,5 @@ |
||||
#define STRCMP __wcsncmp_avx2_rtm |
||||
#define USE_AS_STRNCMP 1 |
||||
#define USE_AS_WCSCMP 1 |
||||
- |
||||
+#define OVERFLOW_STRCMP __wcscmp_avx2_rtm |
||||
#include "strcmp-avx2-rtm.S" |
||||
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S |
||||
index 4fa1de4d3f1f97ff..e9ede522b8bde27d 100644 |
||||
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S |
||||
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S |
||||
@@ -1,5 +1,5 @@ |
||||
#define STRCMP __wcsncmp_avx2 |
||||
#define USE_AS_STRNCMP 1 |
||||
#define USE_AS_WCSCMP 1 |
||||
- |
||||
+#define OVERFLOW_STRCMP __wcscmp_avx2 |
||||
#include "strcmp-avx2.S" |
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
commit d093b677c36ef4b360bf30483b68b95d9f0ad1d2 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Fri Feb 18 14:19:15 2022 -0600 |
||||
|
||||
x86: Test wcscmp RTM in the wcsncmp overflow case [BZ #28896] |
||||
|
||||
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would |
||||
call strcmp-avx2 and wcscmp-avx2 respectively. This would have |
||||
not checks around vzeroupper and would trigger spurious |
||||
aborts. This commit fixes that. |
||||
|
||||
test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on |
||||
AVX2 machines with and without RTM. |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
|
||||
(cherry picked from commit 7835d611af0854e69a0c71e3806f8fe379282d6f) |
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile |
||||
index af934d6ccf1fa337..cd94e683afd5b4a4 100644 |
||||
--- a/sysdeps/x86/Makefile |
||||
+++ b/sysdeps/x86/Makefile |
||||
@@ -95,7 +95,9 @@ tests += \ |
||||
tst-strcpy-rtm \ |
||||
tst-strlen-rtm \ |
||||
tst-strncmp-rtm \ |
||||
- tst-strrchr-rtm |
||||
+ tst-strrchr-rtm \ |
||||
+ tst-wcsncmp-rtm \ |
||||
+# tests |
||||
|
||||
CFLAGS-tst-memchr-rtm.c += -mrtm |
||||
CFLAGS-tst-memcmp-rtm.c += -mrtm |
||||
@@ -107,6 +109,7 @@ CFLAGS-tst-strcpy-rtm.c += -mrtm |
||||
CFLAGS-tst-strlen-rtm.c += -mrtm |
||||
CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error |
||||
CFLAGS-tst-strrchr-rtm.c += -mrtm |
||||
+CFLAGS-tst-wcsncmp-rtm.c += -mrtm -Wno-error |
||||
endif |
||||
|
||||
ifneq ($(enable-cet),no) |
||||
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c |
||||
index 4d0004b58aae428d..4e9f094f39c72f67 100644 |
||||
--- a/sysdeps/x86/tst-strncmp-rtm.c |
||||
+++ b/sysdeps/x86/tst-strncmp-rtm.c |
||||
@@ -19,18 +19,32 @@ |
||||
#include <stdint.h> |
||||
#include <tst-string-rtm.h> |
||||
|
||||
+#ifdef WIDE |
||||
+# define CHAR wchar_t |
||||
+# define MEMSET wmemset |
||||
+# define STRNCMP wcsncmp |
||||
+# define TEST_NAME wcsncmp |
||||
+#else /* !WIDE */ |
||||
+# define CHAR char |
||||
+# define MEMSET memset |
||||
+# define STRNCMP strncmp |
||||
+# define TEST_NAME strncmp |
||||
+#endif /* !WIDE */ |
||||
+ |
||||
+ |
||||
+ |
||||
#define LOOP 3000 |
||||
#define STRING_SIZE 1024 |
||||
-char string1[STRING_SIZE]; |
||||
-char string2[STRING_SIZE]; |
||||
+CHAR string1[STRING_SIZE]; |
||||
+CHAR string2[STRING_SIZE]; |
||||
|
||||
__attribute__ ((noinline, noclone)) |
||||
static int |
||||
prepare (void) |
||||
{ |
||||
- memset (string1, 'a', STRING_SIZE - 1); |
||||
- memset (string2, 'a', STRING_SIZE - 1); |
||||
- if (strncmp (string1, string2, STRING_SIZE) == 0) |
||||
+ MEMSET (string1, 'a', STRING_SIZE - 1); |
||||
+ MEMSET (string2, 'a', STRING_SIZE - 1); |
||||
+ if (STRNCMP (string1, string2, STRING_SIZE) == 0) |
||||
return EXIT_SUCCESS; |
||||
else |
||||
return EXIT_FAILURE; |
||||
@@ -40,7 +54,7 @@ __attribute__ ((noinline, noclone)) |
||||
static int |
||||
function (void) |
||||
{ |
||||
- if (strncmp (string1, string2, STRING_SIZE) == 0) |
||||
+ if (STRNCMP (string1, string2, STRING_SIZE) == 0) |
||||
return 0; |
||||
else |
||||
return 1; |
||||
@@ -50,7 +64,7 @@ __attribute__ ((noinline, noclone)) |
||||
static int |
||||
function_overflow (void) |
||||
{ |
||||
- if (strncmp (string1, string2, SIZE_MAX) == 0) |
||||
+ if (STRNCMP (string1, string2, SIZE_MAX) == 0) |
||||
return 0; |
||||
else |
||||
return 1; |
||||
@@ -59,9 +73,9 @@ function_overflow (void) |
||||
static int |
||||
do_test (void) |
||||
{ |
||||
- int status = do_test_1 ("strncmp", LOOP, prepare, function); |
||||
+ int status = do_test_1 (TEST_NAME, LOOP, prepare, function); |
||||
if (status != EXIT_SUCCESS) |
||||
return status; |
||||
- status = do_test_1 ("strncmp", LOOP, prepare, function_overflow); |
||||
+ status = do_test_1 (TEST_NAME, LOOP, prepare, function_overflow); |
||||
return status; |
||||
} |
||||
diff --git a/sysdeps/x86/tst-wcsncmp-rtm.c b/sysdeps/x86/tst-wcsncmp-rtm.c |
||||
new file mode 100644 |
||||
index 0000000000000000..bad3b863782c5e56 |
||||
--- /dev/null |
||||
+++ b/sysdeps/x86/tst-wcsncmp-rtm.c |
||||
@@ -0,0 +1,21 @@ |
||||
+/* Test case for wcsncmp inside a transactionally executing RTM region. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#define WIDE 1 |
||||
+#include <wchar.h> |
||||
+#include "tst-strncmp-rtm.c" |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
commit 15b00d2af0e56dcc8c244a36d6872d301b0c7185 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Fri Feb 18 17:00:25 2022 -0600 |
||||
|
||||
x86: Fix TEST_NAME to make it a string in tst-strncmp-rtm.c |
||||
|
||||
Previously TEST_NAME was passing a function pointer. This didn't fail |
||||
because of the -Wno-error flag (to allow for overflow sizes passed |
||||
to strncmp/wcsncmp) |
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit b98d0bbf747f39770e0caba7e984ce9f8f900330) |
||||
|
||||
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c |
||||
index 4e9f094f39c72f67..aef9866cf2fbe774 100644 |
||||
--- a/sysdeps/x86/tst-strncmp-rtm.c |
||||
+++ b/sysdeps/x86/tst-strncmp-rtm.c |
||||
@@ -23,12 +23,12 @@ |
||||
# define CHAR wchar_t |
||||
# define MEMSET wmemset |
||||
# define STRNCMP wcsncmp |
||||
-# define TEST_NAME wcsncmp |
||||
+# define TEST_NAME "wcsncmp" |
||||
#else /* !WIDE */ |
||||
# define CHAR char |
||||
# define MEMSET memset |
||||
# define STRNCMP strncmp |
||||
-# define TEST_NAME strncmp |
||||
+# define TEST_NAME "strncmp" |
||||
#endif /* !WIDE */ |
||||
|
||||
|
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
commit 3be79b72d556e3ac37075ad6b99eb5eac18e1402 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Sun Mar 6 15:56:57 2022 +0000 |
||||
|
||||
Fix elf/tst-audit2 on hppa |
||||
|
||||
The test elf/tst-audit2 fails on hppa with a segmentation fault in the |
||||
long branch stub used to call malloc from calloc. This occurs because |
||||
the test is not a PIC executable and calloc is called from the dynamic |
||||
linker before the dp register is initialized in _dl_start_user. |
||||
|
||||
The fix is to move the dp register initialization into |
||||
elf_machine_runtime_setup. Since the address of $global$ can't be |
||||
loaded directly, we continue to use the DT_PLTGOT value from the |
||||
the main_map to initialize dp. Since l_main_map is not available |
||||
in v2.34 and earlier, we use a new function, elf_machine_main_map, |
||||
to find the main map. |
||||
|
||||
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h |
||||
index f048fd20728ccde6..24f0f47d8f1e25cd 100644 |
||||
--- a/sysdeps/hppa/dl-machine.h |
||||
+++ b/sysdeps/hppa/dl-machine.h |
||||
@@ -27,6 +27,7 @@ |
||||
#include <string.h> |
||||
#include <link.h> |
||||
#include <errno.h> |
||||
+#include <ldsodefs.h> |
||||
#include <dl-fptr.h> |
||||
#include <abort-instr.h> |
||||
#include <tls.h> |
||||
@@ -159,6 +160,24 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc, |
||||
return (struct fdesc) { value.ip + reloc->r_addend, value.gp }; |
||||
} |
||||
|
||||
+static inline struct link_map * |
||||
+elf_machine_main_map (void) |
||||
+{ |
||||
+ struct link_map *main_map; |
||||
+ |
||||
+#if defined SHARED && IS_IN (rtld) |
||||
+ asm ( |
||||
+" bl 1f,%0\n" |
||||
+" addil L'_rtld_local - ($PIC_pcrel$0 - 1),%0\n" |
||||
+"1: ldw R'_rtld_local - ($PIC_pcrel$0 - 5)(%%r1),%0\n" |
||||
+ : "=r" (main_map) : : "r1"); |
||||
+#else |
||||
+ main_map = NULL; |
||||
+#endif |
||||
+ |
||||
+ return main_map; |
||||
+} |
||||
+ |
||||
/* Set up the loaded object described by L so its unrelocated PLT |
||||
entries will jump to the on-demand fixup code in dl-runtime.c. */ |
||||
|
||||
@@ -174,6 +193,15 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) |
||||
Elf32_Addr i[2]; |
||||
} sig = {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}}; |
||||
|
||||
+ /* Initialize dp register for main executable. */ |
||||
+ if (l == elf_machine_main_map ()) |
||||
+ { |
||||
+ register Elf32_Addr dp asm ("%r27"); |
||||
+ |
||||
+ dp = D_PTR (l, l_info[DT_PLTGOT]); |
||||
+ asm volatile ("" : : "r" (dp)); |
||||
+ } |
||||
+ |
||||
/* If we don't have a PLT we can just skip all this... */ |
||||
if (__builtin_expect (l->l_info[DT_JMPREL] == NULL,0)) |
||||
return lazy; |
||||
@@ -336,16 +364,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) |
||||
its return value is the user program's entry point. */ |
||||
|
||||
#define RTLD_START \ |
||||
-/* Set up dp for any non-PIC lib constructors that may be called. */ \ |
||||
-static struct link_map * __attribute__((used)) \ |
||||
-set_dp (struct link_map *map) \ |
||||
-{ \ |
||||
- register Elf32_Addr dp asm ("%r27"); \ |
||||
- dp = D_PTR (map, l_info[DT_PLTGOT]); \ |
||||
- asm volatile ("" : : "r" (dp)); \ |
||||
- return map; \ |
||||
-} \ |
||||
- \ |
||||
asm ( \ |
||||
" .text\n" \ |
||||
" .globl _start\n" \ |
||||
@@ -445,14 +463,11 @@ asm ( \ |
||||
" stw %r24,-44(%sp)\n" \ |
||||
\ |
||||
".Lnofix:\n" \ |
||||
+ /* Call _dl_init(main_map, argc, argv, envp). */ \ |
||||
" addil LT'_rtld_local,%r19\n" \ |
||||
" ldw RT'_rtld_local(%r1),%r26\n" \ |
||||
-" bl set_dp, %r2\n" \ |
||||
" ldw 0(%r26),%r26\n" \ |
||||
\ |
||||
- /* Call _dl_init(_dl_loaded, argc, argv, envp). */ \ |
||||
-" copy %r28,%r26\n" \ |
||||
- \ |
||||
/* envp = argv + argc + 1 */ \ |
||||
" sh2add %r25,%r24,%r23\n" \ |
||||
" bl _dl_init,%r2\n" \ |
@ -0,0 +1,146 @@
@@ -0,0 +1,146 @@
|
||||
commit c6f9085ee4e913a0b8260340ac7b75c426b780ce |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Fri Feb 18 20:38:25 2022 +0000 |
||||
|
||||
hppa: Fix swapcontext |
||||
|
||||
This change fixes the failure of stdlib/tst-setcontext2 and |
||||
stdlib/tst-setcontext7 on hppa. The implementation of swapcontext |
||||
in C is broken. C saves the return pointer (rp) and any non |
||||
call-clobbered registers (in this case r3, r4 and r5) on the |
||||
stack. However, the setcontext call in swapcontext pops the |
||||
stack and subsequent calls clobber the saved registers. When |
||||
the context in oucp is restored, both tests fault. |
||||
|
||||
Here we rewrite swapcontext in assembly code to avoid using |
||||
the stack for register values that need to be used after |
||||
restoration. The getcontext and setcontext routines are |
||||
revised to save and restore register ret1 for normal returns. |
||||
We copy the oucp pointer to ret1. This allows access to |
||||
the old context after calling getcontext and setcontext. |
||||
|
||||
(cherry picked from commit 71b108d7eb33b2bf3e61d5e92d2a47f74c1f7d96) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/getcontext.S b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
index 1405b42819c38993..c8b690aab8ecc47c 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
@@ -138,6 +138,8 @@ ENTRY(__getcontext) |
||||
stw %r19, -32(%sp) |
||||
.cfi_offset 19, 32 |
||||
#endif |
||||
+ stw %ret1, -60(%sp) |
||||
+ .cfi_offset 29, 4 |
||||
|
||||
/* Set up the trampoline registers. |
||||
r20, r23, r24, r25, r26 and r2 are clobbered |
||||
@@ -168,6 +170,7 @@ ENTRY(__getcontext) |
||||
#ifdef PIC |
||||
ldw -32(%sp), %r19 |
||||
#endif |
||||
+ ldw -60(%sp), %ret1 |
||||
bv %r0(%r2) |
||||
ldwm -64(%sp), %r4 |
||||
END(__getcontext) |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/setcontext.S b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
index 8fc5f5e56cb31f51..e1ae3aefcaac198d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
@@ -34,6 +34,8 @@ ENTRY(__setcontext) |
||||
stw %r19, -32(%sp) |
||||
.cfi_offset 19, 32 |
||||
#endif |
||||
+ stw %ret1, -60(%sp) |
||||
+ .cfi_offset 29, 4 |
||||
|
||||
/* Save ucp. */ |
||||
copy %r26, %r3 |
||||
@@ -155,6 +157,7 @@ ENTRY(__setcontext) |
||||
#ifdef PIC |
||||
ldw -32(%r30), %r19 |
||||
#endif |
||||
+ ldw -60(%r30), %ret1 |
||||
bv %r0(%r2) |
||||
ldwm -64(%r30), %r3 |
||||
L(pseudo_end): |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.c b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
index f9a8207543c164cb..562f00ff0546177d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
@@ -18,6 +18,7 @@ |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
#include <ucontext.h> |
||||
+#include "ucontext_i.h" |
||||
|
||||
extern int __getcontext (ucontext_t *ucp); |
||||
extern int __setcontext (const ucontext_t *ucp); |
||||
@@ -25,17 +26,61 @@ extern int __setcontext (const ucontext_t *ucp); |
||||
int |
||||
__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
||||
{ |
||||
+ /* Save ucp in stack argument slot. */ |
||||
+ asm ("stw %r25,-40(%sp)"); |
||||
+ asm (".cfi_offset 25, -40"); |
||||
+ |
||||
+ /* Save rp for debugger. */ |
||||
+ asm ("stw %rp,-20(%sp)"); |
||||
+ asm (".cfi_offset 2, -20"); |
||||
+ |
||||
+ /* Copy rp to ret0 (r28). */ |
||||
+ asm ("copy %rp,%ret0"); |
||||
+ |
||||
+ /* Create a frame. */ |
||||
+ asm ("ldo 64(%sp),%sp"); |
||||
+ asm (".cfi_def_cfa_offset -64"); |
||||
+ |
||||
/* Save the current machine context to oucp. */ |
||||
- __getcontext (oucp); |
||||
+ asm ("bl __getcontext,%rp"); |
||||
+ |
||||
+ /* Copy oucp to register ret1 (r29). __getcontext saves and restores it |
||||
+ on a normal return. It is restored from oR29 on reactivation. */ |
||||
+ asm ("copy %r26,%ret1"); |
||||
+ |
||||
+ /* Pop frame. */ |
||||
+ asm ("ldo -64(%sp),%sp"); |
||||
+ asm (".cfi_def_cfa_offset 0"); |
||||
+ |
||||
+ /* Load return pointer from oR28. */ |
||||
+ asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28)); |
||||
+ |
||||
+ /* Return if error. */ |
||||
+ asm ("or,= %r0,%ret0,%r0"); |
||||
+ asm ("bv,n %r0(%rp)"); |
||||
+ |
||||
+ /* Load sc_sar flag. */ |
||||
+ asm ("ldw %0(%%ret1),%%r20" : : "i" (oSAR)); |
||||
+ |
||||
+ /* Return if oucp context has been reactivated. */ |
||||
+ asm ("or,= %r0,%r20,%r0"); |
||||
+ asm ("bv,n %r0(%rp)"); |
||||
+ |
||||
+ /* Mark sc_sar flag. */ |
||||
+ asm ("1: ldi 1,%r20"); |
||||
+ asm ("stw %%r20,%0(%%ret1)" : : "i" (oSAR)); |
||||
+ |
||||
+ /* Activate the machine context in ucp. */ |
||||
+ asm ("bl __setcontext,%rp"); |
||||
+ asm ("ldw -40(%sp),%r26"); |
||||
|
||||
- /* mark sc_sar flag to skip the setcontext call on reactivation. */ |
||||
- if (oucp->uc_mcontext.sc_sar == 0) { |
||||
- oucp->uc_mcontext.sc_sar++; |
||||
+ /* Load return pointer. */ |
||||
+ asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28)); |
||||
|
||||
- /* Restore the machine context in ucp. */ |
||||
- __setcontext (ucp); |
||||
- } |
||||
+ /* A successful call to setcontext does not return. */ |
||||
+ asm ("bv,n %r0(%rp)"); |
||||
|
||||
+ /* Make gcc happy. */ |
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
commit f610d2935f041c5f41ddcb96924ea42ca2fb5ea5 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Tue Feb 22 17:28:46 2022 +0000 |
||||
|
||||
hppa: Revise gettext trampoline design |
||||
|
||||
The current getcontext return trampoline is overly complex and it |
||||
unnecessarily clobbers several registers. By saving the context |
||||
pointer (r26) in the context, __getcontext_ret can restore any |
||||
registers not restored by setcontext. This allows getcontext to |
||||
save and restore the entire register context present when getcontext |
||||
is entered. We use the unused oR0 context slot for the return |
||||
from __getcontext_ret. |
||||
|
||||
While this is not directly useful in C, it can be exploited in |
||||
assembly code. Registers r20, r23, r24 and r25 are not clobbered |
||||
in the call path to getcontext. This allows a small simplification |
||||
of swapcontext. |
||||
|
||||
It also allows saving and restoring the 6-bit SAR register in the |
||||
LSB of the oSAR context slot. The getcontext flag value can be |
||||
stored in the MSB of the oSAR slot. |
||||
|
||||
(cherry picked from commit 9e7e5fda38471e00d1190479ea91d7b08ae3e304) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/getcontext.S b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
index c8b690aab8ecc47c..4f2e2587d60effc8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
||||
@@ -22,22 +22,28 @@ |
||||
#include "ucontext_i.h" |
||||
|
||||
|
||||
- /* Trampoline function. Non-standard calling ABI. */ |
||||
+ /* Trampoline function. Non-standard calling ABI. */ |
||||
/* Can not use ENTRY(__getcontext_ret) here. */ |
||||
.type __getcontext_ret, @function |
||||
.hidden __getcontext_ret |
||||
__getcontext_ret: |
||||
.proc |
||||
.callinfo FRAME=0,NO_CALLS |
||||
- /* r26-r23 contain original r3-r6, but because setcontext |
||||
- does not reload r3-r6 (it's using them as temporaries) |
||||
- we must save them elsewhere and swap them back in. */ |
||||
- copy %r23, %r3 |
||||
- copy %r24, %r4 |
||||
- copy %r25, %r5 |
||||
- copy %r26, %r6 |
||||
- /* r20 contains original return pointer. */ |
||||
- bv 0(%r20) |
||||
+ /* Because setcontext does not reload r3-r6 (it's using them |
||||
+ as temporaries), we must load them ourself. */ |
||||
+ ldw oR3(%r26), %r3 |
||||
+ ldw oR4(%r26), %r4 |
||||
+ ldw oR5(%r26), %r5 |
||||
+ ldw oR6(%r26), %r6 |
||||
+ |
||||
+ /* Also reload registers clobbered by $$dyncall. */ |
||||
+ ldw oR21(%r26), %r21 |
||||
+ ldw oR22(%r26), %r22 |
||||
+ ldw oR31(%r26), %r31 |
||||
+ |
||||
+ /* oR0 contains original return pointer. */ |
||||
+ ldw oR0(%r26), %rp |
||||
+ bv 0(%rp) |
||||
copy %r0, %ret0 |
||||
.procend |
||||
.size __getcontext_ret, .-__getcontext_ret |
||||
@@ -65,13 +71,13 @@ ENTRY(__getcontext) |
||||
stw %r17, oR17(%r26) |
||||
stw %r18, oR18(%r26) |
||||
stw %r19, oR19(%r26) |
||||
- /* stw %r20, oR20(%r26) - used for trampoline. */ |
||||
+ stw %r20, oR20(%r26) |
||||
stw %r21, oR21(%r26) |
||||
stw %r22, oR22(%r26) |
||||
- /* stw %r23, oR23(%r26) - used for trampoline. */ |
||||
- /* stw %r24, oR24(%r26) - used for trampoline. */ |
||||
- /* stw %r25, oR25(%r26) - used for trampoline. */ |
||||
- /* stw %r26, oR26(%r26) - used for trampoline. */ |
||||
+ stw %r23, oR23(%r26) |
||||
+ stw %r24, oR24(%r26) |
||||
+ stw %r25, oR25(%r26) |
||||
+ stw %r26, oR26(%r26) |
||||
stw %r27, oR27(%r26) |
||||
stw %r28, oR28(%r26) |
||||
stw %r29, oR29(%r26) |
||||
@@ -90,7 +96,10 @@ ENTRY(__getcontext) |
||||
stw %r0, oIASQ1(%r26) |
||||
stw %r0, oIAOQ0(%r26) |
||||
stw %r0, oIAOQ1(%r26) |
||||
- stw %r0, oSAR(%r26) /* used as flag in swapcontext(). */ |
||||
+ |
||||
+ /* Save SAR register. */ |
||||
+ mfctl %sar, %r1 |
||||
+ stw %r1, oSAR(%r26) /* MSB used as flag in swapcontext(). */ |
||||
|
||||
|
||||
/* Store floating-point regs. */ |
||||
@@ -142,13 +151,8 @@ ENTRY(__getcontext) |
||||
.cfi_offset 29, 4 |
||||
|
||||
/* Set up the trampoline registers. |
||||
- r20, r23, r24, r25, r26 and r2 are clobbered |
||||
- by call to getcontext() anyway. Reuse them. */ |
||||
- stw %r2, oR20(%r26) |
||||
- stw %r3, oR23(%r26) |
||||
- stw %r4, oR24(%r26) |
||||
- stw %r5, oR25(%r26) |
||||
- stw %r6, oR26(%r26) |
||||
+ Use oR0 context slot to save return value. */ |
||||
+ stw %r2, oR0(%r26) |
||||
#ifdef PIC |
||||
addil LT%__getcontext_ret, %r19 |
||||
ldw RT%__getcontext_ret(%r1), %r1 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/setcontext.S b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
index e1ae3aefcaac198d..616405b80c61d531 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
||||
@@ -76,7 +76,7 @@ ENTRY(__setcontext) |
||||
ldw oR18(%r3), %r18 |
||||
ldw oR19(%r3), %r19 |
||||
ldw oR20(%r3), %r20 |
||||
- ldw oR21(%r3), %r21 |
||||
+ ldw oR21(%r3), %r21 /* maybe clobbered by dyncall */ |
||||
/* ldw oR22(%r3), %r22 - dyncall arg. */ |
||||
ldw oR23(%r3), %r23 |
||||
ldw oR24(%r3), %r24 |
||||
@@ -88,6 +88,10 @@ ENTRY(__setcontext) |
||||
ldw oR30(%r3), %sp |
||||
/* ldw oR31(%r3), %r31 - dyncall scratch register */ |
||||
|
||||
+ /* Restore SAR register. */ |
||||
+ ldw oSAR(%r3), %r22 |
||||
+ mtsar %r22 |
||||
+ |
||||
/* Restore floating-point registers. */ |
||||
ldo oFPREGS31(%r3), %r22 |
||||
fldds 0(%r22), %fr31 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.c b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
index 562f00ff0546177d..1664f68c7b9982e8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
@@ -26,10 +26,6 @@ extern int __setcontext (const ucontext_t *ucp); |
||||
int |
||||
__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
||||
{ |
||||
- /* Save ucp in stack argument slot. */ |
||||
- asm ("stw %r25,-40(%sp)"); |
||||
- asm (".cfi_offset 25, -40"); |
||||
- |
||||
/* Save rp for debugger. */ |
||||
asm ("stw %rp,-20(%sp)"); |
||||
asm (".cfi_offset 2, -20"); |
||||
@@ -60,7 +56,7 @@ __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
||||
asm ("bv,n %r0(%rp)"); |
||||
|
||||
/* Load sc_sar flag. */ |
||||
- asm ("ldw %0(%%ret1),%%r20" : : "i" (oSAR)); |
||||
+ asm ("ldb %0(%%ret1),%%r20" : : "i" (oSAR)); |
||||
|
||||
/* Return if oucp context has been reactivated. */ |
||||
asm ("or,= %r0,%r20,%r0"); |
||||
@@ -68,11 +64,11 @@ __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
||||
|
||||
/* Mark sc_sar flag. */ |
||||
asm ("1: ldi 1,%r20"); |
||||
- asm ("stw %%r20,%0(%%ret1)" : : "i" (oSAR)); |
||||
+ asm ("stb %%r20,%0(%%ret1)" : : "i" (oSAR)); |
||||
|
||||
/* Activate the machine context in ucp. */ |
||||
asm ("bl __setcontext,%rp"); |
||||
- asm ("ldw -40(%sp),%r26"); |
||||
+ asm ("ldw %0(%%ret1),%%r26" : : "i" (oR25)); |
||||
|
||||
/* Load return pointer. */ |
||||
asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28)); |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit 40fc6a74ee3dd600c84d311d91cbb16962f11a71 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Mon Feb 28 15:47:38 2022 +0000 |
||||
|
||||
nptl: Fix cleanups for stack grows up [BZ# 28899] |
||||
|
||||
_STACK_GROWS_DOWN is defined to 0 when the stack grows up. The |
||||
code in unwind.c used `#ifdef _STACK_GROWS_DOWN' to selct the |
||||
stack grows down define for FRAME_LEFT. As a result, the |
||||
_STACK_GROWS_DOWN define was always selected and cleanups were |
||||
incorrectly sequenced when the stack grows up. |
||||
|
||||
(cherry picked from commit 2bbc694df279020a6620096d31c1e05c93966f9b) |
||||
|
||||
diff --git a/nptl/unwind.c b/nptl/unwind.c |
||||
index f50997f728ccde0d..404fab46d00e9f10 100644 |
||||
--- a/nptl/unwind.c |
||||
+++ b/nptl/unwind.c |
||||
@@ -27,7 +27,7 @@ |
||||
#include <jmpbuf-unwind.h> |
||||
#include <shlib-compat.h> |
||||
|
||||
-#ifdef _STACK_GROWS_DOWN |
||||
+#if _STACK_GROWS_DOWN |
||||
# define FRAME_LEFT(frame, other, adj) \ |
||||
((uintptr_t) frame - adj >= (uintptr_t) other - adj) |
||||
#elif _STACK_GROWS_UP |
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
commit 6c9c2307657529e52c5fa7037618835f2a50b916 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Sun Mar 6 16:04:32 2022 +0000 |
||||
|
||||
hppa: Fix warnings from _dl_lookup_address |
||||
|
||||
This change fixes two warnings from _dl_lookup_address. |
||||
|
||||
The first warning comes from dropping the volatile keyword from |
||||
desc in the call to _dl_read_access_allowed. We now have a full |
||||
atomic barrier between loading desc[0] and the access check, so |
||||
desc no longer needs to be declared as volatile. |
||||
|
||||
The second warning comes from the implicit declaration of |
||||
_dl_fix_reloc_arg. This is fixed by including dl-runtime.h and |
||||
declaring _dl_fix_reloc_arg in dl-runtime.h. |
||||
|
||||
diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c |
||||
index 62ef68b62bd601f4..cd4f77c0ecfd376f 100644 |
||||
--- a/sysdeps/hppa/dl-fptr.c |
||||
+++ b/sysdeps/hppa/dl-fptr.c |
||||
@@ -26,6 +26,7 @@ |
||||
#include <ldsodefs.h> |
||||
#include <elf/dynamic-link.h> |
||||
#include <dl-fptr.h> |
||||
+#include <dl-runtime.h> |
||||
#include <dl-unmap-segments.h> |
||||
#include <atomic.h> |
||||
#include <libc-pointer-arith.h> |
||||
@@ -351,21 +352,20 @@ _dl_lookup_address (const void *address) |
||||
{ |
||||
ElfW(Addr) addr = (ElfW(Addr)) address; |
||||
ElfW(Word) reloc_arg; |
||||
- volatile unsigned int *desc; |
||||
- unsigned int *gptr; |
||||
+ unsigned int *desc, *gptr; |
||||
|
||||
/* Return ADDR if the least-significant two bits of ADDR are not consistent |
||||
with ADDR being a linker defined function pointer. The normal value for |
||||
a code address in a backtrace is 3. */ |
||||
- if (((unsigned int) addr & 3) != 2) |
||||
+ if (((uintptr_t) addr & 3) != 2) |
||||
return addr; |
||||
|
||||
/* Handle special case where ADDR points to page 0. */ |
||||
- if ((unsigned int) addr < 4096) |
||||
+ if ((uintptr_t) addr < 4096) |
||||
return addr; |
||||
|
||||
/* Clear least-significant two bits from descriptor address. */ |
||||
- desc = (unsigned int *) ((unsigned int) addr & ~3); |
||||
+ desc = (unsigned int *) ((uintptr_t) addr & ~3); |
||||
if (!_dl_read_access_allowed (desc)) |
||||
return addr; |
||||
|
||||
@@ -376,7 +376,7 @@ _dl_lookup_address (const void *address) |
||||
/* Then load first word of candidate descriptor. It should be a pointer |
||||
with word alignment and point to memory that can be read. */ |
||||
gptr = (unsigned int *) desc[0]; |
||||
- if (((unsigned int) gptr & 3) != 0 |
||||
+ if (((uintptr_t) gptr & 3) != 0 |
||||
|| !_dl_read_access_allowed (gptr)) |
||||
return addr; |
||||
|
||||
@@ -400,10 +400,11 @@ _dl_lookup_address (const void *address) |
||||
|
||||
/* If gp has been resolved, we need to hunt for relocation offset. */ |
||||
if (!(reloc_arg & PA_GP_RELOC)) |
||||
- reloc_arg = _dl_fix_reloc_arg (addr, l); |
||||
+ reloc_arg = _dl_fix_reloc_arg ((struct fdesc *) addr, l); |
||||
|
||||
_dl_fixup (l, reloc_arg); |
||||
} |
||||
|
||||
return (ElfW(Addr)) desc[0]; |
||||
} |
||||
+rtld_hidden_def (_dl_lookup_address) |
||||
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h |
||||
index a9a927f26c6fec09..2f6991aa16e87a00 100644 |
||||
--- a/sysdeps/hppa/dl-lookupcfg.h |
||||
+++ b/sysdeps/hppa/dl-lookupcfg.h |
||||
@@ -30,6 +30,7 @@ rtld_hidden_proto (_dl_symbol_address) |
||||
#define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref) |
||||
|
||||
Elf32_Addr _dl_lookup_address (const void *address); |
||||
+rtld_hidden_proto (_dl_lookup_address) |
||||
|
||||
#define DL_LOOKUP_ADDRESS(addr) _dl_lookup_address ((const void *) addr) |
||||
|
||||
diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c |
||||
index e7fbb7417d866bb0..a71b5b2013abf723 100644 |
||||
--- a/sysdeps/hppa/dl-runtime.c |
||||
+++ b/sysdeps/hppa/dl-runtime.c |
||||
@@ -25,8 +25,7 @@ |
||||
return that to the caller. The caller will continue on to call |
||||
_dl_fixup with the relocation offset. */ |
||||
|
||||
-ElfW(Word) |
||||
-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE |
||||
+ElfW(Word) __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE |
||||
_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) |
||||
{ |
||||
Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type; |
||||
@@ -52,3 +51,4 @@ _dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) |
||||
ABORT_INSTRUCTION; |
||||
return 0; |
||||
} |
||||
+rtld_hidden_def (_dl_fix_reloc_arg) |
||||
diff --git a/sysdeps/hppa/dl-runtime.h b/sysdeps/hppa/dl-runtime.h |
||||
index 5d6ee53b076d5e0e..9913539b5f0e7435 100644 |
||||
--- a/sysdeps/hppa/dl-runtime.h |
||||
+++ b/sysdeps/hppa/dl-runtime.h |
||||
@@ -17,6 +17,9 @@ |
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
||||
02111-1307 USA. */ |
||||
|
||||
+ElfW(Word) _dl_fix_reloc_arg (struct fdesc *, struct link_map *); |
||||
+rtld_hidden_proto (_dl_fix_reloc_arg) |
||||
+ |
||||
/* Clear PA_GP_RELOC bit in relocation offset. */ |
||||
static inline uintptr_t |
||||
reloc_offset (uintptr_t plt0, uintptr_t pltn) |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
commit b5032c3d37aa614644c7afbad33bb8226a52e6da |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Feb 28 11:50:41 2022 +0100 |
||||
|
||||
io: Add fsync call in tst-stat |
||||
|
||||
io/tst-stat and io/tst-stat-lfs fail sporadically on the Fedora |
||||
builders, and this change hopefully helps to avoid the issue. |
||||
|
||||
(cherry picked from commit ae132284092edc5885315b44cd17d5ea91177e49) |
||||
|
||||
diff --git a/io/tst-stat.c b/io/tst-stat.c |
||||
index 82e965de6ad87f61..be20cf16d70d05cc 100644 |
||||
--- a/io/tst-stat.c |
||||
+++ b/io/tst-stat.c |
||||
@@ -69,6 +69,10 @@ do_test (void) |
||||
TEST_VERIFY_EXIT (fd >= 0); |
||||
support_write_file_string (path, "abc"); |
||||
|
||||
+ /* This should help to prevent delayed allocation, which may result |
||||
+ in a spurious stx_blocks/st_blocks difference. */ |
||||
+ fsync (fd); |
||||
+ |
||||
bool check_ns = support_stat_nanoseconds (path); |
||||
if (!check_ns) |
||||
printf ("warning: timestamp with nanoseconds not supported\n"); |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
commit b53f0c11de409b04560a70570178d1a9d03d5860 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Mar 11 08:23:56 2022 +0100 |
||||
|
||||
nss: Do not mention NSS test modules in <gnu/lib-names.h> |
||||
|
||||
They are not actually installed. Use the nss_files version instead |
||||
in nss/Makefile, similar to how __nss_shlib_revision is derived |
||||
from LIBNSS_FILES_SO. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit aefc79ab5ad4bb9feea2876720cec70dca7cd8ed) |
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile |
||||
index bccf9f2806c15651..e223243d9d62041c 100644 |
||||
--- a/nss/Makefile |
||||
+++ b/nss/Makefile |
||||
@@ -171,17 +171,14 @@ $(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps) |
||||
$(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps) |
||||
$(build-module) |
||||
$(objpfx)nss_test2.os : nss_test1.c |
||||
-ifdef libnss_test1.so-version |
||||
-$(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so |
||||
+# Use the nss_files suffix for these objects as well. |
||||
+$(objpfx)/libnss_test1.so$(libnss_files.so-version): $(objpfx)/libnss_test1.so |
||||
$(make-link) |
||||
-endif |
||||
-ifdef libnss_test2.so-version |
||||
-$(objpfx)/libnss_test2.so$(libnss_test2.so-version): $(objpfx)/libnss_test2.so |
||||
+$(objpfx)/libnss_test2.so$(libnss_files.so-version): $(objpfx)/libnss_test2.so |
||||
$(make-link) |
||||
-endif |
||||
$(patsubst %,$(objpfx)%.out,$(tests) $(tests-container)) : \ |
||||
- $(objpfx)/libnss_test1.so$(libnss_test1.so-version) \ |
||||
- $(objpfx)/libnss_test2.so$(libnss_test2.so-version) |
||||
+ $(objpfx)/libnss_test1.so$(libnss_files.so-version) \ |
||||
+ $(objpfx)/libnss_test2.so$(libnss_files.so-version) |
||||
|
||||
ifeq (yes,$(have-thread-library)) |
||||
$(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library) |
||||
diff --git a/shlib-versions b/shlib-versions |
||||
index df6603e6992b8382..b87ab50c59af1bfd 100644 |
||||
--- a/shlib-versions |
||||
+++ b/shlib-versions |
||||
@@ -47,11 +47,6 @@ libnss_ldap=2 |
||||
libnss_hesiod=2 |
||||
libnss_db=2 |
||||
|
||||
-# Tests for NSS. They must have the same NSS_SHLIB_REVISION number as |
||||
-# the rest. |
||||
-libnss_test1=2 |
||||
-libnss_test2=2 |
||||
- |
||||
# Version for libnsl with YP and NIS+ functions. |
||||
libnsl=1 |
||||
|
@ -0,0 +1,224 @@
@@ -0,0 +1,224 @@
|
||||
commit 54b12733959238204d7b0e46e69fc7f7d8890b20 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Mar 11 08:23:56 2022 +0100 |
||||
|
||||
nss: Protect against errno changes in function lookup (bug 28953) |
||||
|
||||
dlopen may clobber errno. The nss_test_errno module uses an ELF |
||||
constructor to achieve that, but there could be internal errors |
||||
during dlopen that cause this, too. Therefore, the NSS framework |
||||
has to guard against such errno clobbers. |
||||
|
||||
__nss_module_get_function is currently the only function that calls |
||||
__nss_module_load, so it is sufficient to save and restore errno |
||||
around this call. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 9bdf92c79d63b42f931101bb6df87129c408b0c4) |
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile |
||||
index e223243d9d62041c..716bc8f6ef5276b0 100644 |
||||
--- a/nss/Makefile |
||||
+++ b/nss/Makefile |
||||
@@ -60,7 +60,8 @@ tests = test-netdb test-digits-dots tst-nss-getpwent bug17079 \ |
||||
tst-nss-test1 \ |
||||
tst-nss-test2 \ |
||||
tst-nss-test4 \ |
||||
- tst-nss-test5 |
||||
+ tst-nss-test5 \ |
||||
+ tst-nss-test_errno |
||||
xtests = bug-erange |
||||
|
||||
tests-container = \ |
||||
@@ -132,7 +133,7 @@ libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) |
||||
ifeq ($(build-static-nss),yes) |
||||
tests-static += tst-nss-static |
||||
endif |
||||
-extra-test-objs += nss_test1.os nss_test2.os |
||||
+extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os |
||||
|
||||
include ../Rules |
||||
|
||||
@@ -166,19 +167,26 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver |
||||
|
||||
libof-nss_test1 = extramodules |
||||
libof-nss_test2 = extramodules |
||||
+libof-nss_test_errno = extramodules |
||||
$(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps) |
||||
$(build-module) |
||||
$(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps) |
||||
$(build-module) |
||||
+$(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps) |
||||
+ $(build-module) |
||||
$(objpfx)nss_test2.os : nss_test1.c |
||||
# Use the nss_files suffix for these objects as well. |
||||
$(objpfx)/libnss_test1.so$(libnss_files.so-version): $(objpfx)/libnss_test1.so |
||||
$(make-link) |
||||
$(objpfx)/libnss_test2.so$(libnss_files.so-version): $(objpfx)/libnss_test2.so |
||||
$(make-link) |
||||
+$(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \ |
||||
+ $(objpfx)/libnss_test_errno.so |
||||
+ $(make-link) |
||||
$(patsubst %,$(objpfx)%.out,$(tests) $(tests-container)) : \ |
||||
$(objpfx)/libnss_test1.so$(libnss_files.so-version) \ |
||||
- $(objpfx)/libnss_test2.so$(libnss_files.so-version) |
||||
+ $(objpfx)/libnss_test2.so$(libnss_files.so-version) \ |
||||
+ $(objpfx)/libnss_test_errno.so$(libnss_files.so-version) |
||||
|
||||
ifeq (yes,$(have-thread-library)) |
||||
$(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library) |
||||
diff --git a/nss/nss_module.c b/nss/nss_module.c |
||||
index b28cb94a6a0aeb41..3a4a464256121e41 100644 |
||||
--- a/nss/nss_module.c |
||||
+++ b/nss/nss_module.c |
||||
@@ -330,8 +330,18 @@ name_search (const void *left, const void *right) |
||||
void * |
||||
__nss_module_get_function (struct nss_module *module, const char *name) |
||||
{ |
||||
+ /* A successful dlopen might clobber errno. */ |
||||
+ int saved_errno = errno; |
||||
+ |
||||
if (!__nss_module_load (module)) |
||||
- return NULL; |
||||
+ { |
||||
+ /* Reporting module load failure is currently inaccurate. See |
||||
+ bug 22041. Not changing errno is the conservative choice. */ |
||||
+ __set_errno (saved_errno); |
||||
+ return NULL; |
||||
+ } |
||||
+ |
||||
+ __set_errno (saved_errno); |
||||
|
||||
function_name *name_entry = bsearch (name, nss_function_name_array, |
||||
array_length (nss_function_name_array), |
||||
diff --git a/nss/nss_test_errno.c b/nss/nss_test_errno.c |
||||
new file mode 100644 |
||||
index 0000000000000000..680f8a07b97fe263 |
||||
--- /dev/null |
||||
+++ b/nss/nss_test_errno.c |
||||
@@ -0,0 +1,58 @@ |
||||
+/* NSS service provider with errno clobber. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <errno.h> |
||||
+#include <nss.h> |
||||
+#include <stdlib.h> |
||||
+ |
||||
+/* Catch misnamed and functions. */ |
||||
+#pragma GCC diagnostic error "-Wmissing-prototypes" |
||||
+NSS_DECLARE_MODULE_FUNCTIONS (test_errno) |
||||
+ |
||||
+static void __attribute__ ((constructor)) |
||||
+init (void) |
||||
+{ |
||||
+ /* An arbitrary error code which is otherwise not used. */ |
||||
+ errno = ELIBBAD; |
||||
+} |
||||
+ |
||||
+/* Lookup functions for pwd follow that do not return any data. */ |
||||
+ |
||||
+/* Catch misnamed function definitions. */ |
||||
+ |
||||
+enum nss_status |
||||
+_nss_test_errno_setpwent (int stayopen) |
||||
+{ |
||||
+ setenv ("_nss_test_errno_setpwent", "yes", 1); |
||||
+ return NSS_STATUS_SUCCESS; |
||||
+} |
||||
+ |
||||
+enum nss_status |
||||
+_nss_test_errno_getpwent_r (struct passwd *result, |
||||
+ char *buffer, size_t size, int *errnop) |
||||
+{ |
||||
+ setenv ("_nss_test_errno_getpwent_r", "yes", 1); |
||||
+ return NSS_STATUS_NOTFOUND; |
||||
+} |
||||
+ |
||||
+enum nss_status |
||||
+_nss_test_errno_endpwent (void) |
||||
+{ |
||||
+ setenv ("_nss_test_errno_endpwent", "yes", 1); |
||||
+ return NSS_STATUS_SUCCESS; |
||||
+} |
||||
diff --git a/nss/tst-nss-test_errno.c b/nss/tst-nss-test_errno.c |
||||
new file mode 100644 |
||||
index 0000000000000000..d2c42dd363a38b0e |
||||
--- /dev/null |
||||
+++ b/nss/tst-nss-test_errno.c |
||||
@@ -0,0 +1,61 @@ |
||||
+/* getpwent failure when dlopen clobbers errno (bug 28953). |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <nss.h> |
||||
+#include <support/check.h> |
||||
+#include <stdlib.h> |
||||
+#include <errno.h> |
||||
+#include <stdbool.h> |
||||
+#include <pwd.h> |
||||
+#include <string.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ __nss_configure_lookup ("passwd", "files test_errno"); |
||||
+ |
||||
+ errno = 0; |
||||
+ setpwent (); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ |
||||
+ bool root_seen = false; |
||||
+ while (true) |
||||
+ { |
||||
+ errno = 0; |
||||
+ struct passwd *e = getpwent (); |
||||
+ if (e == NULL) |
||||
+ break; |
||||
+ if (strcmp (e->pw_name, "root")) |
||||
+ root_seen = true; |
||||
+ } |
||||
+ |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ TEST_VERIFY (root_seen); |
||||
+ |
||||
+ errno = 0; |
||||
+ endpwent (); |
||||
+ TEST_COMPARE (errno, 0); |
||||
+ |
||||
+ TEST_COMPARE_STRING (getenv ("_nss_test_errno_setpwent"), "yes"); |
||||
+ TEST_COMPARE_STRING (getenv ("_nss_test_errno_getpwent_r"), "yes"); |
||||
+ TEST_COMPARE_STRING (getenv ("_nss_test_errno_endpwent"), "yes"); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,345 @@
@@ -0,0 +1,345 @@
|
||||
commit c82bdf033f93a710044e25f721340c26e89a3769 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Tue Oct 12 12:29:13 2021 +0530 |
||||
|
||||
Don't add access size hints to fortifiable functions |
||||
|
||||
In the context of a function definition, the size hints imply that the |
||||
size of an object pointed to by one parameter is another parameter. |
||||
This doesn't make sense for the fortified versions of the functions |
||||
since that's the bit it's trying to validate. |
||||
|
||||
This is harmless with __builtin_object_size since it has fairly simple |
||||
semantics when it comes to objects passed as function parameters. |
||||
With __builtin_dynamic_object_size we could (as my patchset for gcc[1] |
||||
already does) use the access attribute to determine the object size in |
||||
the general case but it misleads the fortified functions. |
||||
|
||||
Basically the problem occurs when access attributes are present on |
||||
regular functions that have inline fortified definitions to generate |
||||
_chk variants; the attributes get inherited by these definitions, |
||||
causing problems when analyzing them. For example with poll(fds, nfds, |
||||
timeout), nfds is hinted using the __attr_access as being the size of |
||||
fds. |
||||
|
||||
Now, when analyzing the inline function definition in bits/poll2.h, the |
||||
compiler sees that nfds is the size of fds and tries to use that |
||||
information in the function body. In _FORTIFY_SOURCE=3 case, where the |
||||
object size could be a non-constant expression, this information results |
||||
in the conclusion that nfds is the size of fds, which defeats the |
||||
purpose of the implementation because we're trying to check here if nfds |
||||
does indeed represent the size of fds. Hence for this case, it is best |
||||
to not have the access attribute. |
||||
|
||||
With the attributes gone, the expression evaluation should get delayed |
||||
until the function is actually inlined into its destinations. |
||||
|
||||
Disable the access attribute for fortified function inline functions |
||||
when building at _FORTIFY_SOURCE=3 to make this work better. The |
||||
access attributes remain for the _chk variants since they can be used |
||||
by the compiler to warn when the caller is passing invalid arguments. |
||||
|
||||
[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-October/581125.html |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
(cherry picked from commit e938c02748402c50f60ba0eb983273e7b52937d1) |
||||
|
||||
diff --git a/io/bits/poll2.h b/io/bits/poll2.h |
||||
index a623678c09f9f04f..be74d020f2e0e434 100644 |
||||
--- a/io/bits/poll2.h |
||||
+++ b/io/bits/poll2.h |
||||
@@ -33,7 +33,7 @@ extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds, |
||||
__poll_chk) |
||||
__warnattr ("poll called with fds buffer too small file nfds entries"); |
||||
|
||||
-__fortify_function __attr_access ((__write_only__, 1, 2)) int |
||||
+__fortify_function __fortified_attr_access (__write_only__, 1, 2) int |
||||
poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) |
||||
{ |
||||
if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1) |
||||
@@ -64,7 +64,7 @@ extern int __REDIRECT (__ppoll_chk_warn, (struct pollfd *__fds, nfds_t __nfds, |
||||
__ppoll_chk) |
||||
__warnattr ("ppoll called with fds buffer too small file nfds entries"); |
||||
|
||||
-__fortify_function __attr_access ((__write_only__, 1, 2)) int |
||||
+__fortify_function __fortified_attr_access (__write_only__, 1, 2) int |
||||
ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout, |
||||
const __sigset_t *__ss) |
||||
{ |
||||
diff --git a/io/sys/poll.h b/io/sys/poll.h |
||||
index e640efb2bce7ea67..751c7f5f72db8be2 100644 |
||||
--- a/io/sys/poll.h |
||||
+++ b/io/sys/poll.h |
||||
@@ -52,7 +52,7 @@ __BEGIN_DECLS |
||||
This function is a cancellation point and therefore not marked with |
||||
__THROW. */ |
||||
extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
|
||||
#ifdef __USE_GNU |
||||
/* Like poll, but before waiting the threads signal mask is replaced |
||||
@@ -64,7 +64,7 @@ extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) |
||||
extern int ppoll (struct pollfd *__fds, nfds_t __nfds, |
||||
const struct timespec *__timeout, |
||||
const __sigset_t *__ss) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
|
||||
# ifdef __USE_TIME_BITS64 |
||||
# ifdef __REDIRECT |
||||
@@ -72,7 +72,7 @@ extern int __REDIRECT (ppoll, (struct pollfd *__fds, nfds_t __nfds, |
||||
const struct timespec *__timeout, |
||||
const __sigset_t *__ss), |
||||
__ppoll64) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
# else |
||||
# define ppoll __ppoll64 |
||||
# endif |
||||
diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h |
||||
index 3f0cab1254b02c43..4f016a563857a137 100644 |
||||
--- a/libio/bits/stdio2.h |
||||
+++ b/libio/bits/stdio2.h |
||||
@@ -258,7 +258,7 @@ extern char *__REDIRECT (__fgets_chk_warn, |
||||
__wur __warnattr ("fgets called with bigger size than length " |
||||
"of destination buffer"); |
||||
|
||||
-__fortify_function __wur __attr_access ((__write_only__, 1, 2)) char * |
||||
+__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2) char * |
||||
fgets (char *__restrict __s, int __n, FILE *__restrict __stream) |
||||
{ |
||||
if (__glibc_objsize (__s) != (size_t) -1) |
||||
@@ -320,7 +320,7 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn, |
||||
__wur __warnattr ("fgets_unlocked called with bigger size than length " |
||||
"of destination buffer"); |
||||
|
||||
-__fortify_function __wur __attr_access ((__write_only__, 1, 2)) char * |
||||
+__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2) char * |
||||
fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream) |
||||
{ |
||||
if (__glibc_objsize (__s) != (size_t) -1) |
||||
diff --git a/libio/stdio.h b/libio/stdio.h |
||||
index 497da016ffa2e230..abefe640e52d18d5 100644 |
||||
--- a/libio/stdio.h |
||||
+++ b/libio/stdio.h |
||||
@@ -584,7 +584,7 @@ extern int putw (int __w, FILE *__stream); |
||||
This function is a possible cancellation point and therefore not |
||||
marked with __THROW. */ |
||||
extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) |
||||
- __wur __attr_access ((__write_only__, 1, 2)); |
||||
+ __wur __fortified_attr_access (__write_only__, 1, 2); |
||||
|
||||
#if __GLIBC_USE (DEPRECATED_GETS) |
||||
/* Get a newline-terminated string from stdin, removing the newline. |
||||
@@ -608,7 +608,7 @@ extern char *gets (char *__s) __wur __attribute_deprecated__; |
||||
therefore not marked with __THROW. */ |
||||
extern char *fgets_unlocked (char *__restrict __s, int __n, |
||||
FILE *__restrict __stream) __wur |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
#endif |
||||
|
||||
|
||||
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h |
||||
index e490fc1aebeadc3d..cd836441a9807d6a 100644 |
||||
--- a/misc/sys/cdefs.h |
||||
+++ b/misc/sys/cdefs.h |
||||
@@ -603,12 +603,22 @@ _Static_assert (0, "IEEE 128-bits long double requires redirection on this platf |
||||
size-index is not provided: |
||||
access (access-mode, <ref-index> [, <size-index>]) */ |
||||
# define __attr_access(x) __attribute__ ((__access__ x)) |
||||
+/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may |
||||
+ use the access attribute to get object sizes from function definition |
||||
+ arguments, so we can't use them on functions we fortify. Drop the object |
||||
+ size hints for such functions. */ |
||||
+# if __USE_FORTIFY_LEVEL == 3 |
||||
+# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o))) |
||||
+# else |
||||
+# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s)) |
||||
+# endif |
||||
# if __GNUC_PREREQ (11, 0) |
||||
# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno))) |
||||
# else |
||||
# define __attr_access_none(argno) |
||||
# endif |
||||
#else |
||||
+# define __fortified_attr_access(a, o, s) |
||||
# define __attr_access(x) |
||||
# define __attr_access_none(argno) |
||||
#endif |
||||
diff --git a/posix/unistd.h b/posix/unistd.h |
||||
index 8224c5fbc956306f..7a61ff5e868c3456 100644 |
||||
--- a/posix/unistd.h |
||||
+++ b/posix/unistd.h |
||||
@@ -369,7 +369,7 @@ extern void closefrom (int __lowfd) __THROW; |
||||
This function is a cancellation point and therefore not marked with |
||||
__THROW. */ |
||||
extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur |
||||
- __attr_access ((__write_only__, 2, 3)); |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
|
||||
/* Write N bytes of BUF to FD. Return the number written, or -1. |
||||
|
||||
@@ -388,7 +388,7 @@ extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur |
||||
__THROW. */ |
||||
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, |
||||
__off_t __offset) __wur |
||||
- __attr_access ((__write_only__, 2, 3)); |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
|
||||
/* Write N bytes of BUF to FD at the given position OFFSET without |
||||
changing the file pointer. Return the number written, or -1. |
||||
@@ -404,7 +404,7 @@ extern ssize_t pwrite (int __fd, const void *__buf, size_t __n, |
||||
extern ssize_t __REDIRECT (pread, (int __fd, void *__buf, size_t __nbytes, |
||||
__off64_t __offset), |
||||
pread64) __wur |
||||
- __attr_access ((__write_only__, 2, 3)); |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
extern ssize_t __REDIRECT (pwrite, (int __fd, const void *__buf, |
||||
size_t __nbytes, __off64_t __offset), |
||||
pwrite64) __wur |
||||
@@ -421,7 +421,7 @@ extern ssize_t __REDIRECT (pwrite, (int __fd, const void *__buf, |
||||
or 0 for EOF. */ |
||||
extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, |
||||
__off64_t __offset) __wur |
||||
- __attr_access ((__write_only__, 2, 3)); |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
/* Write N bytes of BUF to FD at the given position OFFSET without |
||||
changing the file pointer. Return the number written, or -1. */ |
||||
extern ssize_t pwrite64 (int __fd, const void *__buf, size_t __n, |
||||
@@ -642,7 +642,7 @@ extern long int sysconf (int __name) __THROW; |
||||
#ifdef __USE_POSIX2 |
||||
/* Get the value of the string-valued system variable NAME. */ |
||||
extern size_t confstr (int __name, char *__buf, size_t __len) __THROW |
||||
- __attr_access ((__write_only__, 2, 3)); |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
#endif |
||||
|
||||
|
||||
@@ -709,7 +709,7 @@ extern __gid_t getegid (void) __THROW; |
||||
the calling process is in. Otherwise, fill in the group IDs |
||||
of its supplementary groups in LIST and return the number written. */ |
||||
extern int getgroups (int __size, __gid_t __list[]) __THROW __wur |
||||
- __attr_access ((__write_only__, 2, 1)); |
||||
+ __fortified_attr_access (__write_only__, 2, 1); |
||||
#ifdef __USE_GNU |
||||
/* Return nonzero iff the calling process is in group GID. */ |
||||
extern int group_member (__gid_t __gid) __THROW; |
||||
@@ -801,7 +801,8 @@ extern char *ttyname (int __fd) __THROW; |
||||
/* Store at most BUFLEN characters of the pathname of the terminal FD is |
||||
open on in BUF. Return 0 on success, otherwise an error number. */ |
||||
extern int ttyname_r (int __fd, char *__buf, size_t __buflen) |
||||
- __THROW __nonnull ((2)) __wur __attr_access ((__write_only__, 2, 3)); |
||||
+ __THROW __nonnull ((2)) __wur |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
|
||||
/* Return 1 if FD is a valid descriptor associated |
||||
with a terminal, zero if not. */ |
||||
@@ -836,7 +837,8 @@ extern int symlink (const char *__from, const char *__to) |
||||
Returns the number of characters read, or -1 for errors. */ |
||||
extern ssize_t readlink (const char *__restrict __path, |
||||
char *__restrict __buf, size_t __len) |
||||
- __THROW __nonnull ((1, 2)) __wur __attr_access ((__write_only__, 2, 3)); |
||||
+ __THROW __nonnull ((1, 2)) __wur |
||||
+ __fortified_attr_access (__write_only__, 2, 3); |
||||
|
||||
#endif /* Use POSIX.1-2001. */ |
||||
|
||||
@@ -848,7 +850,8 @@ extern int symlinkat (const char *__from, int __tofd, |
||||
/* Like readlink but a relative PATH is interpreted relative to FD. */ |
||||
extern ssize_t readlinkat (int __fd, const char *__restrict __path, |
||||
char *__restrict __buf, size_t __len) |
||||
- __THROW __nonnull ((2, 3)) __wur __attr_access ((__write_only__, 3, 4)); |
||||
+ __THROW __nonnull ((2, 3)) __wur |
||||
+ __fortified_attr_access (__write_only__, 3, 4); |
||||
#endif |
||||
|
||||
/* Remove the link NAME. */ |
||||
@@ -884,7 +887,7 @@ extern char *getlogin (void); |
||||
This function is a possible cancellation point and therefore not |
||||
marked with __THROW. */ |
||||
extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
#endif |
||||
|
||||
#ifdef __USE_MISC |
||||
@@ -906,7 +909,7 @@ extern int setlogin (const char *__name) __THROW __nonnull ((1)); |
||||
The result is null-terminated if LEN is large enough for the full |
||||
name and the terminator. */ |
||||
extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
#endif |
||||
|
||||
|
||||
@@ -925,7 +928,8 @@ extern int sethostid (long int __id) __THROW __wur; |
||||
Called just like `gethostname' and `sethostname'. |
||||
The NIS domain name is usually the empty string when not using NIS. */ |
||||
extern int getdomainname (char *__name, size_t __len) |
||||
- __THROW __nonnull ((1)) __wur __attr_access ((__write_only__, 1, 2)); |
||||
+ __THROW __nonnull ((1)) __wur |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
extern int setdomainname (const char *__name, size_t __len) |
||||
__THROW __nonnull ((1)) __wur __attr_access ((__read_only__, 1, 2)); |
||||
|
||||
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h |
||||
index 0481c1235514f6e7..74c00eee73e4009d 100644 |
||||
--- a/stdlib/stdlib.h |
||||
+++ b/stdlib/stdlib.h |
||||
@@ -943,7 +943,8 @@ extern size_t mbstowcs (wchar_t *__restrict __pwcs, |
||||
extern size_t wcstombs (char *__restrict __s, |
||||
const wchar_t *__restrict __pwcs, size_t __n) |
||||
__THROW |
||||
- __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 3) |
||||
+ __attr_access ((__read_only__, 2)); |
||||
|
||||
#ifdef __USE_MISC |
||||
/* Determine whether the string value of RESPONSE matches the affirmation |
||||
@@ -997,7 +998,7 @@ extern char *ptsname (int __fd) __THROW __wur; |
||||
terminal associated with the master FD is open on in BUF. |
||||
Return 0 on success, otherwise an error number. */ |
||||
extern int ptsname_r (int __fd, char *__buf, size_t __buflen) |
||||
- __THROW __nonnull ((2)) __attr_access ((__write_only__, 2, 3)); |
||||
+ __THROW __nonnull ((2)) __fortified_attr_access (__write_only__, 2, 3); |
||||
|
||||
/* Open a master pseudo terminal and return its file descriptor. */ |
||||
extern int getpt (void); |
||||
diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h |
||||
index 67ae2c6b50435368..5731274848260ad2 100644 |
||||
--- a/string/bits/string_fortified.h |
||||
+++ b/string/bits/string_fortified.h |
||||
@@ -64,7 +64,7 @@ __NTH (memset (void *__dest, int __ch, size_t __len)) |
||||
# include <bits/strings_fortified.h> |
||||
|
||||
void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen) |
||||
- __THROW __nonnull ((1)) __attr_access ((__write_only__, 1, 2)); |
||||
+ __THROW __nonnull ((1)) __fortified_attr_access (__write_only__, 1, 2); |
||||
|
||||
__fortify_function void |
||||
__NTH (explicit_bzero (void *__dest, size_t __len)) |
||||
@@ -106,7 +106,8 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) |
||||
#else |
||||
extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, |
||||
size_t __destlen) __THROW |
||||
- __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); |
||||
+ __fortified_attr_access ((__write_only__, 1, 3)) |
||||
+ __attr_access ((__read_only__, 2)); |
||||
extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src, |
||||
size_t __n), stpncpy); |
||||
|
||||
diff --git a/string/string.h b/string/string.h |
||||
index 04e1b7067dc31d3c..8dcafb4ac4952853 100644 |
||||
--- a/string/string.h |
||||
+++ b/string/string.h |
||||
@@ -448,7 +448,7 @@ extern char *strerror_l (int __errnum, locale_t __l) __THROW; |
||||
/* Set N bytes of S to 0. The compiler will not delete a call to this |
||||
function, even if S is dead after the call. */ |
||||
extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1)) |
||||
- __attr_access ((__write_only__, 1, 2)); |
||||
+ __fortified_attr_access (__write_only__, 1, 2); |
||||
|
||||
/* Return the next DELIM-delimited token from *STRINGP, |
||||
terminating it with a '\0', and update *STRINGP to point past it. */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,358 @@
@@ -0,0 +1,358 @@
|
||||
commit 536910724d30a38eeecd14cdbe2c93c78ea67646 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed Oct 20 18:13:05 2021 +0530 |
||||
|
||||
debug: Add tests for _FORTIFY_SOURCE=3 |
||||
|
||||
Add some testing coverage for _FORTIFY_SOURCE=3. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit ad6f2a010c2ce759936de4747f6e0d53991912f8) |
||||
|
||||
diff --git a/debug/Makefile b/debug/Makefile |
||||
index 6893111cbfaa0900..357f888246061e15 100644 |
||||
--- a/debug/Makefile |
||||
+++ b/debug/Makefile |
||||
@@ -120,6 +120,8 @@ CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
+CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
+CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
@@ -129,6 +131,7 @@ CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
LDLIBS-tst-chk4 = -lstdc++ |
||||
LDLIBS-tst-chk5 = -lstdc++ |
||||
LDLIBS-tst-chk6 = -lstdc++ |
||||
+LDLIBS-tst-chk8 = -lstdc++ |
||||
LDLIBS-tst-lfschk4 = -lstdc++ |
||||
LDLIBS-tst-lfschk5 = -lstdc++ |
||||
LDLIBS-tst-lfschk6 = -lstdc++ |
||||
@@ -150,16 +153,16 @@ CFLAGS-tst-ssp-1.c += -fstack-protector-all |
||||
|
||||
tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ |
||||
tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ |
||||
- tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \ |
||||
- tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \ |
||||
- tst-backtrace5 tst-backtrace6 |
||||
+ tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ |
||||
+ tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ |
||||
+ tst-backtrace4 tst-backtrace5 tst-backtrace6 |
||||
|
||||
ifeq ($(have-ssp),yes) |
||||
tests += tst-ssp-1 |
||||
endif |
||||
|
||||
ifeq (,$(CXX)) |
||||
-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \ |
||||
+tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \ |
||||
tst-lfschk4 tst-lfschk5 tst-lfschk6 |
||||
endif |
||||
|
||||
@@ -193,6 +196,8 @@ $(objpfx)tst-chk3.out: $(gen-locales) |
||||
$(objpfx)tst-chk4.out: $(gen-locales) |
||||
$(objpfx)tst-chk5.out: $(gen-locales) |
||||
$(objpfx)tst-chk6.out: $(gen-locales) |
||||
+$(objpfx)tst-chk7.out: $(gen-locales) |
||||
+$(objpfx)tst-chk8.out: $(gen-locales) |
||||
$(objpfx)tst-lfschk1.out: $(gen-locales) |
||||
$(objpfx)tst-lfschk2.out: $(gen-locales) |
||||
$(objpfx)tst-lfschk3.out: $(gen-locales) |
||||
diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c |
||||
index 6c1d32cc62c3a964..68ac00d1808382b8 100644 |
||||
--- a/debug/tst-chk1.c |
||||
+++ b/debug/tst-chk1.c |
||||
@@ -83,8 +83,14 @@ handler (int sig) |
||||
_exit (127); |
||||
} |
||||
|
||||
+#if __USE_FORTIFY_LEVEL == 3 |
||||
+volatile size_t buf_size = 10; |
||||
+#else |
||||
char buf[10]; |
||||
wchar_t wbuf[10]; |
||||
+#define buf_size sizeof (buf) |
||||
+#endif |
||||
+ |
||||
volatile size_t l0; |
||||
volatile char *p; |
||||
volatile wchar_t *wp; |
||||
@@ -123,6 +129,10 @@ int num2 = 987654; |
||||
static int |
||||
do_test (void) |
||||
{ |
||||
+#if __USE_FORTIFY_LEVEL == 3 |
||||
+ char *buf = (char *) malloc (buf_size); |
||||
+ wchar_t *wbuf = (wchar_t *) malloc (buf_size * sizeof (wchar_t)); |
||||
+#endif |
||||
set_fortify_handler (handler); |
||||
|
||||
struct A { char buf1[9]; char buf2[1]; } a; |
||||
@@ -947,93 +957,93 @@ do_test (void) |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fgets (buf, sizeof (buf), stdin) != buf |
||||
+ if (fgets (buf, buf_size, stdin) != buf |
||||
|| memcmp (buf, "abcdefgh\n", 10)) |
||||
FAIL (); |
||||
- if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10)) |
||||
+ if (fgets (buf, buf_size, stdin) != buf || memcmp (buf, "ABCDEFGHI", 10)) |
||||
FAIL (); |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fgets (buf, l0 + sizeof (buf), stdin) != buf |
||||
+ if (fgets (buf, l0 + buf_size, stdin) != buf |
||||
|| memcmp (buf, "abcdefgh\n", 10)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (fgets (buf, sizeof (buf) + 1, stdin) != buf) |
||||
+ if (fgets (buf, buf_size + 1, stdin) != buf) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf) |
||||
+ if (fgets (buf, l0 + buf_size + 1, stdin) != buf) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fgets_unlocked (buf, sizeof (buf), stdin) != buf |
||||
+ if (fgets_unlocked (buf, buf_size, stdin) != buf |
||||
|| memcmp (buf, "abcdefgh\n", 10)) |
||||
FAIL (); |
||||
- if (fgets_unlocked (buf, sizeof (buf), stdin) != buf |
||||
+ if (fgets_unlocked (buf, buf_size, stdin) != buf |
||||
|| memcmp (buf, "ABCDEFGHI", 10)) |
||||
FAIL (); |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf |
||||
+ if (fgets_unlocked (buf, l0 + buf_size, stdin) != buf |
||||
|| memcmp (buf, "abcdefgh\n", 10)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf) |
||||
+ if (fgets_unlocked (buf, buf_size + 1, stdin) != buf) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf) |
||||
+ if (fgets_unlocked (buf, l0 + buf_size + 1, stdin) != buf) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fread (buf, 1, sizeof (buf), stdin) != sizeof (buf) |
||||
+ if (fread (buf, 1, buf_size, stdin) != buf_size |
||||
|| memcmp (buf, "abcdefgh\nA", 10)) |
||||
FAIL (); |
||||
- if (fread (buf, sizeof (buf), 1, stdin) != 1 |
||||
+ if (fread (buf, buf_size, 1, stdin) != 1 |
||||
|| memcmp (buf, "BCDEFGHI\na", 10)) |
||||
FAIL (); |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fread (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf) |
||||
+ if (fread (buf, l0 + 1, buf_size, stdin) != buf_size |
||||
|| memcmp (buf, "abcdefgh\nA", 10)) |
||||
FAIL (); |
||||
- if (fread (buf, sizeof (buf), l0 + 1, stdin) != 1 |
||||
+ if (fread (buf, buf_size, l0 + 1, stdin) != 1 |
||||
|| memcmp (buf, "BCDEFGHI\na", 10)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (fread (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1) |
||||
+ if (fread (buf, 1, buf_size + 1, stdin) != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (fread (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1) |
||||
+ if (fread (buf, buf_size + 1, l0 + 1, stdin) != 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fread_unlocked (buf, 1, sizeof (buf), stdin) != sizeof (buf) |
||||
+ if (fread_unlocked (buf, 1, buf_size, stdin) != buf_size |
||||
|| memcmp (buf, "abcdefgh\nA", 10)) |
||||
FAIL (); |
||||
- if (fread_unlocked (buf, sizeof (buf), 1, stdin) != 1 |
||||
+ if (fread_unlocked (buf, buf_size, 1, stdin) != 1 |
||||
|| memcmp (buf, "BCDEFGHI\na", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -1048,100 +1058,100 @@ do_test (void) |
||||
|
||||
rewind (stdin); |
||||
|
||||
- if (fread_unlocked (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf) |
||||
+ if (fread_unlocked (buf, l0 + 1, buf_size, stdin) != buf_size |
||||
|| memcmp (buf, "abcdefgh\nA", 10)) |
||||
FAIL (); |
||||
- if (fread_unlocked (buf, sizeof (buf), l0 + 1, stdin) != 1 |
||||
+ if (fread_unlocked (buf, buf_size, l0 + 1, stdin) != 1 |
||||
|| memcmp (buf, "BCDEFGHI\na", 10)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (fread_unlocked (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1) |
||||
+ if (fread_unlocked (buf, 1, buf_size + 1, stdin) != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (fread_unlocked (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1) |
||||
+ if (fread_unlocked (buf, buf_size + 1, l0 + 1, stdin) != 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
lseek (fileno (stdin), 0, SEEK_SET); |
||||
|
||||
- if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 |
||||
+ if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1 |
||||
|| memcmp (buf, "abcdefgh\n", 9)) |
||||
FAIL (); |
||||
- if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 |
||||
+ if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1 |
||||
|| memcmp (buf, "ABCDEFGHI", 9)) |
||||
FAIL (); |
||||
|
||||
lseek (fileno (stdin), 0, SEEK_SET); |
||||
|
||||
- if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1 |
||||
+ if (read (fileno (stdin), buf, l0 + buf_size - 1) != buf_size - 1 |
||||
|| memcmp (buf, "abcdefgh\n", 9)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1) |
||||
+ if (read (fileno (stdin), buf, buf_size + 1) != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (read (fileno (stdin), buf, l0 + sizeof (buf) + 1) != sizeof (buf) + 1) |
||||
+ if (read (fileno (stdin), buf, l0 + buf_size + 1) != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
- if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) |
||||
- != sizeof (buf) - 1 |
||||
+ if (pread (fileno (stdin), buf, buf_size - 1, buf_size - 2) |
||||
+ != buf_size - 1 |
||||
|| memcmp (buf, "\nABCDEFGH", 9)) |
||||
FAIL (); |
||||
- if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 |
||||
+ if (pread (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1 |
||||
|| memcmp (buf, "abcdefgh\n", 9)) |
||||
FAIL (); |
||||
- if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) |
||||
- != sizeof (buf) - 1 |
||||
+ if (pread (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3) |
||||
+ != buf_size - 1 |
||||
|| memcmp (buf, "h\nABCDEFG", 9)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) |
||||
- != sizeof (buf) + 1) |
||||
+ if (pread (fileno (stdin), buf, buf_size + 1, 2 * buf_size) |
||||
+ != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (pread (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf)) |
||||
- != sizeof (buf) + 1) |
||||
+ if (pread (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size) |
||||
+ != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
- if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) |
||||
- != sizeof (buf) - 1 |
||||
+ if (pread64 (fileno (stdin), buf, buf_size - 1, buf_size - 2) |
||||
+ != buf_size - 1 |
||||
|| memcmp (buf, "\nABCDEFGH", 9)) |
||||
FAIL (); |
||||
- if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 |
||||
+ if (pread64 (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1 |
||||
|| memcmp (buf, "abcdefgh\n", 9)) |
||||
FAIL (); |
||||
- if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) |
||||
- != sizeof (buf) - 1 |
||||
+ if (pread64 (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3) |
||||
+ != buf_size - 1 |
||||
|| memcmp (buf, "h\nABCDEFG", 9)) |
||||
FAIL (); |
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
- if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) |
||||
- != sizeof (buf) + 1) |
||||
+ if (pread64 (fileno (stdin), buf, buf_size + 1, 2 * buf_size) |
||||
+ != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
|
||||
CHK_FAIL_START |
||||
- if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf)) |
||||
- != sizeof (buf) + 1) |
||||
+ if (pread64 (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size) |
||||
+ != buf_size + 1) |
||||
FAIL (); |
||||
CHK_FAIL_END |
||||
#endif |
||||
@@ -1179,7 +1189,7 @@ do_test (void) |
||||
CHK_FAIL2_END |
||||
|
||||
CHK_FAIL2_START |
||||
- snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4); |
||||
+ snprintf (buf, buf_size, "%3$d\n", 1, 2, 3, 4); |
||||
CHK_FAIL2_END |
||||
|
||||
int sp[2]; |
||||
diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c |
||||
new file mode 100644 |
||||
index 0000000000000000..2a7b32381268135c |
||||
--- /dev/null |
||||
+++ b/debug/tst-chk7.c |
||||
@@ -0,0 +1,2 @@ |
||||
+#define _FORTIFY_SOURCE 3 |
||||
+#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc |
||||
new file mode 100644 |
||||
index 0000000000000000..2a7b32381268135c |
||||
--- /dev/null |
||||
+++ b/debug/tst-chk8.cc |
||||
@@ -0,0 +1,2 @@ |
||||
+#define _FORTIFY_SOURCE 3 |
||||
+#include "tst-chk1.c" |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
commit 98ea9372cc8d60b12aa33e007fdd5f5fb042a651 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Thu Dec 16 07:19:14 2021 +0530 |
||||
|
||||
__glibc_unsafe_len: Fix comment |
||||
|
||||
We know that the length is *unsafe*. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
(cherry picked from commit ae23fa3e5fe24daf94fc7f8e5268bb8ceeda7477) |
||||
|
||||
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h |
||||
index 4825ff0351c1e5d4..3bb9f38916e30295 100644 |
||||
--- a/misc/sys/cdefs.h |
||||
+++ b/misc/sys/cdefs.h |
||||
@@ -168,7 +168,7 @@ |
||||
__s, __osz)) \ |
||||
&& __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) |
||||
|
||||
-/* Conversely, we know at compile time that the length is safe if the |
||||
+/* Conversely, we know at compile time that the length is unsafe if the |
||||
__L * __S <= __OBJSZ condition can be folded to a constant and if it is |
||||
false. */ |
||||
#define __glibc_unsafe_len(__l, __s, __osz) \ |
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
commit 10f7bdebe570e42d1f7a43de4f90eda8ccb4f0da |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Fri Dec 17 18:35:44 2021 +0530 |
||||
|
||||
fortify: Fix spurious warning with realpath |
||||
|
||||
The length and object size arguments were swapped around for realpath. |
||||
Also add a smoke test so that any changes in this area get caught in |
||||
future. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit 2bbd07c715275eb6c616988925738a0517180d57) |
||||
|
||||
diff --git a/debug/Makefile b/debug/Makefile |
||||
index 357f888246061e15..bc37e466eed490fa 100644 |
||||
--- a/debug/Makefile |
||||
+++ b/debug/Makefile |
||||
@@ -108,6 +108,7 @@ CFLAGS-tst-longjmp_chk2.c += -fexceptions -fasynchronous-unwind-tables |
||||
CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1 |
||||
CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables |
||||
CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 |
||||
+CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2 |
||||
|
||||
# We know these tests have problems with format strings, this is what |
||||
# we are testing. Disable that warning. They are also testing |
||||
@@ -155,7 +156,7 @@ tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ |
||||
tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ |
||||
tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ |
||||
tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ |
||||
- tst-backtrace4 tst-backtrace5 tst-backtrace6 |
||||
+ tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk |
||||
|
||||
ifeq ($(have-ssp),yes) |
||||
tests += tst-ssp-1 |
||||
diff --git a/debug/tst-realpath-chk.c b/debug/tst-realpath-chk.c |
||||
new file mode 100644 |
||||
index 0000000000000000..a8fcb327c43fb34d |
||||
--- /dev/null |
||||
+++ b/debug/tst-realpath-chk.c |
||||
@@ -0,0 +1,37 @@ |
||||
+/* Smoke test to verify that realpath does not cause spurious warnings. |
||||
+ Copyright The GNU Toolchain Authors. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <limits.h> |
||||
+#include <stdlib.h> |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+#ifdef PATH_MAX |
||||
+ char buf[PATH_MAX + 1]; |
||||
+ char *res = realpath (".", buf); |
||||
+ TEST_VERIFY (res == buf); |
||||
+#endif |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h |
||||
index 067115eeca123c6d..ccacbdf76a08225a 100644 |
||||
--- a/stdlib/bits/stdlib.h |
||||
+++ b/stdlib/bits/stdlib.h |
||||
@@ -42,7 +42,7 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved)) |
||||
return __realpath_alias (__name, __resolved); |
||||
|
||||
#if defined _LIBC_LIMITS_H_ && defined PATH_MAX |
||||
- if (__glibc_unsafe_len (sz, sizeof (char), PATH_MAX)) |
||||
+ if (__glibc_unsafe_len (PATH_MAX, sizeof (char), sz)) |
||||
return __realpath_chk_warn (__name, __resolved, sz); |
||||
#endif |
||||
return __realpath_chk (__name, __resolved, sz); |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
commit d6a58bd81d07322ff5da8f419d8620ef037b6a36 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed Jan 12 18:46:28 2022 +0530 |
||||
|
||||
Enable _FORTIFY_SOURCE=3 for gcc 12 and above |
||||
|
||||
gcc 12 now has support for the __builtin_dynamic_object_size builtin. |
||||
Adapt the macro checks to enable _FORTIFY_SOURCE=3 on gcc 12 and above. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit 86bf0feb0e3ec8e37872f72499d6ae33406561d7) |
||||
|
||||
diff --git a/include/features.h b/include/features.h |
||||
index d974eabfafc24ffb..933499bcff8f1449 100644 |
||||
--- a/include/features.h |
||||
+++ b/include/features.h |
||||
@@ -412,7 +412,9 @@ |
||||
# warning _FORTIFY_SOURCE requires compiling with optimization (-O) |
||||
# elif !__GNUC_PREREQ (4, 1) |
||||
# warning _FORTIFY_SOURCE requires GCC 4.1 or later |
||||
-# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0) |
||||
+# elif _FORTIFY_SOURCE > 2 && (__glibc_clang_prereq (9, 0) \ |
||||
+ || __GNUC_PREREQ (12, 0)) |
||||
+ |
||||
# if _FORTIFY_SOURCE > 3 |
||||
# warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform |
||||
# endif |
||||
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h |
||||
index 3bb9f38916e30295..515fb681a0547217 100644 |
||||
--- a/misc/sys/cdefs.h |
||||
+++ b/misc/sys/cdefs.h |
||||
@@ -142,7 +142,8 @@ |
||||
#define __bos0(ptr) __builtin_object_size (ptr, 0) |
||||
|
||||
/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ |
||||
-#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0) |
||||
+#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \ |
||||
+ || __GNUC_PREREQ (12, 0)) |
||||
# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) |
||||
# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) |
||||
#else |
@ -0,0 +1,293 @@
@@ -0,0 +1,293 @@
|
||||
commit f8c2f620f1929ad78cb0a247601bec972f140c51 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed Jan 12 23:34:23 2022 +0530 |
||||
|
||||
debug: Autogenerate _FORTIFY_SOURCE tests |
||||
|
||||
Rename debug/tst-chk1.c to debug/tst-fortify.c and add make hackery to |
||||
autogenerate tests with different macros enabled to build and run the |
||||
same test with different configurations as well as different |
||||
fortification levels. |
||||
|
||||
The change also ends up expanding the -lfs tests to include |
||||
_FORTIFY_SOURCE=3. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit db27f1251b008280a29d540b4f8ab2a38a0d80af) |
||||
|
||||
diff --git a/Makerules b/Makerules |
||||
index 596fa68376f45298..7fbe85719aacc230 100644 |
||||
--- a/Makerules |
||||
+++ b/Makerules |
||||
@@ -424,6 +424,12 @@ $(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c) |
||||
endef |
||||
object-suffixes-left := $(all-object-suffixes) |
||||
include $(o-iterator) |
||||
+ |
||||
+define o-iterator-doit |
||||
+$(objpfx)%$o: $(objpfx)%.cc $(before-compile); $$(compile-command.cc) |
||||
+endef |
||||
+object-suffixes-left := $(all-object-suffixes) |
||||
+include $(o-iterator) |
||||
endif |
||||
|
||||
# Generate .dT files as we compile. |
||||
diff --git a/debug/Makefile b/debug/Makefile |
||||
index bc37e466eed490fa..acc1b8f6ad029c62 100644 |
||||
--- a/debug/Makefile |
||||
+++ b/debug/Makefile |
||||
@@ -1,4 +1,5 @@ |
||||
-# Copyright (C) 1998-2021 Free Software Foundation, Inc. |
||||
+# Copyright (C) 1998-2022 Free Software Foundation, Inc. |
||||
+# Copyright The GNU Toolchain Authors. |
||||
# This file is part of the GNU C Library. |
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or |
||||
@@ -110,32 +111,60 @@ CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables |
||||
CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 |
||||
CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2 |
||||
|
||||
+# _FORTIFY_SOURCE tests. |
||||
+# Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and |
||||
+# preprocessor conditions based on tst-fortify.c. |
||||
+# |
||||
+# To add a new test condition, define a cflags-$(cond) make variable to set |
||||
+# CFLAGS for the file. |
||||
+ |
||||
+tests-all-chk = tst-fortify |
||||
+tests-c-chk = |
||||
+tests-cc-chk = |
||||
+ |
||||
+CFLAGS-tst-fortify.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
+ |
||||
+# No additional flags for the default tests. |
||||
+define cflags-default |
||||
+endef |
||||
+ |
||||
+define cflags-lfs |
||||
+CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64 |
||||
+endef |
||||
+ |
||||
# We know these tests have problems with format strings, this is what |
||||
# we are testing. Disable that warning. They are also testing |
||||
# deprecated functions (notably gets) so disable that warning as well. |
||||
# And they also generate warnings from warning attributes, which |
||||
# cannot be disabled via pragmas, so require -Wno-error to be used. |
||||
-CFLAGS-tst-chk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error |
||||
-LDLIBS-tst-chk4 = -lstdc++ |
||||
-LDLIBS-tst-chk5 = -lstdc++ |
||||
-LDLIBS-tst-chk6 = -lstdc++ |
||||
-LDLIBS-tst-chk8 = -lstdc++ |
||||
-LDLIBS-tst-lfschk4 = -lstdc++ |
||||
-LDLIBS-tst-lfschk5 = -lstdc++ |
||||
-LDLIBS-tst-lfschk6 = -lstdc++ |
||||
+define gen-chk-test |
||||
+tests-$(1)-chk += tst-fortify-$(1)-$(2)-$(3) |
||||
+CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \ |
||||
+ -Wno-deprecated-declarations \ |
||||
+ -Wno-error |
||||
+$(eval $(call cflags-$(2),$(1),$(3))) |
||||
+$(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile |
||||
+ ( echo "/* Autogenerated from Makefile. */"; \ |
||||
+ echo ""; \ |
||||
+ echo "#include \"tst-fortify.c\"" ) > $$@.tmp |
||||
+ mv $$@.tmp $$@ |
||||
+endef |
||||
+ |
||||
+chk-extensions = c cc |
||||
+chk-types = default lfs |
||||
+chk-levels = 1 2 3 |
||||
+ |
||||
+$(foreach e,$(chk-extensions), \ |
||||
+ $(foreach t,$(chk-types), \ |
||||
+ $(foreach l,$(chk-levels), \ |
||||
+ $(eval $(call gen-chk-test,$(e),$(t),$(l)))))) |
||||
+ |
||||
+tests-all-chk += $(tests-c-chk) $(tests-cc-chk) |
||||
+ |
||||
+define link-cc |
||||
+LDLIBS-$(1) = -lstdc++ |
||||
+endef |
||||
+$(foreach t,$(tests-cc-chk), $(eval $(call link-cc,$(t)))) |
||||
|
||||
# backtrace_symbols only works if we link with -rdynamic. backtrace |
||||
# requires unwind tables on most architectures. |
||||
@@ -152,19 +181,25 @@ LDFLAGS-tst-backtrace6 = -rdynamic |
||||
|
||||
CFLAGS-tst-ssp-1.c += -fstack-protector-all |
||||
|
||||
-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ |
||||
- tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ |
||||
- tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ |
||||
- tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ |
||||
- tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk |
||||
+tests = backtrace-tst \ |
||||
+ tst-longjmp_chk \ |
||||
+ test-strcpy_chk \ |
||||
+ test-stpcpy_chk \ |
||||
+ tst-longjmp_chk2 \ |
||||
+ tst-backtrace2 \ |
||||
+ tst-backtrace3 \ |
||||
+ tst-backtrace4 \ |
||||
+ tst-backtrace5 \ |
||||
+ tst-backtrace6 \ |
||||
+ tst-realpath-chk \ |
||||
+ $(tests-all-chk) |
||||
|
||||
ifeq ($(have-ssp),yes) |
||||
tests += tst-ssp-1 |
||||
endif |
||||
|
||||
ifeq (,$(CXX)) |
||||
-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \ |
||||
- tst-lfschk4 tst-lfschk5 tst-lfschk6 |
||||
+tests-unsupported = $(tests-cc-chk) |
||||
endif |
||||
|
||||
extra-libs = libSegFault libpcprofile |
||||
@@ -191,20 +226,10 @@ ifeq ($(run-built-tests),yes) |
||||
LOCALES := de_DE.UTF-8 |
||||
include ../gen-locales.mk |
||||
|
||||
-$(objpfx)tst-chk1.out: $(gen-locales) |
||||
-$(objpfx)tst-chk2.out: $(gen-locales) |
||||
-$(objpfx)tst-chk3.out: $(gen-locales) |
||||
-$(objpfx)tst-chk4.out: $(gen-locales) |
||||
-$(objpfx)tst-chk5.out: $(gen-locales) |
||||
-$(objpfx)tst-chk6.out: $(gen-locales) |
||||
-$(objpfx)tst-chk7.out: $(gen-locales) |
||||
-$(objpfx)tst-chk8.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk1.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk2.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk3.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk4.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk5.out: $(gen-locales) |
||||
-$(objpfx)tst-lfschk6.out: $(gen-locales) |
||||
+define chk-gen-locales |
||||
+$(objpfx)$(1).out: $(gen-locales) |
||||
+endef |
||||
+$(foreach t, $(tests-all-chk), $(eval $(call chk-gen-locales,$(t)))) |
||||
endif |
||||
|
||||
sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') |
||||
diff --git a/debug/tst-chk2.c b/debug/tst-chk2.c |
||||
deleted file mode 100644 |
||||
index be37ce2d22f0760a..0000000000000000 |
||||
--- a/debug/tst-chk2.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 1 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk3.c b/debug/tst-chk3.c |
||||
deleted file mode 100644 |
||||
index 38b8e4fb360ba722..0000000000000000 |
||||
--- a/debug/tst-chk3.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 2 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk4.cc b/debug/tst-chk4.cc |
||||
deleted file mode 100644 |
||||
index c82e6aac86038791..0000000000000000 |
||||
--- a/debug/tst-chk4.cc |
||||
+++ /dev/null |
||||
@@ -1 +0,0 @@ |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk5.cc b/debug/tst-chk5.cc |
||||
deleted file mode 100644 |
||||
index be37ce2d22f0760a..0000000000000000 |
||||
--- a/debug/tst-chk5.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 1 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk6.cc b/debug/tst-chk6.cc |
||||
deleted file mode 100644 |
||||
index 38b8e4fb360ba722..0000000000000000 |
||||
--- a/debug/tst-chk6.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 2 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c |
||||
deleted file mode 100644 |
||||
index 2a7b32381268135c..0000000000000000 |
||||
--- a/debug/tst-chk7.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 3 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc |
||||
deleted file mode 100644 |
||||
index 2a7b32381268135c..0000000000000000 |
||||
--- a/debug/tst-chk8.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FORTIFY_SOURCE 3 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-chk1.c b/debug/tst-fortify.c |
||||
similarity index 100% |
||||
rename from debug/tst-chk1.c |
||||
rename to debug/tst-fortify.c |
||||
diff --git a/debug/tst-lfschk1.c b/debug/tst-lfschk1.c |
||||
deleted file mode 100644 |
||||
index f3e6d47d5e4484c3..0000000000000000 |
||||
--- a/debug/tst-lfschk1.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-lfschk2.c b/debug/tst-lfschk2.c |
||||
deleted file mode 100644 |
||||
index 95d4db1d32d2eeb3..0000000000000000 |
||||
--- a/debug/tst-lfschk2.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk2.c" |
||||
diff --git a/debug/tst-lfschk3.c b/debug/tst-lfschk3.c |
||||
deleted file mode 100644 |
||||
index 50a1ae1258f1553d..0000000000000000 |
||||
--- a/debug/tst-lfschk3.c |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk3.c" |
||||
diff --git a/debug/tst-lfschk4.cc b/debug/tst-lfschk4.cc |
||||
deleted file mode 100644 |
||||
index f3e6d47d5e4484c3..0000000000000000 |
||||
--- a/debug/tst-lfschk4.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk1.c" |
||||
diff --git a/debug/tst-lfschk5.cc b/debug/tst-lfschk5.cc |
||||
deleted file mode 100644 |
||||
index 95d4db1d32d2eeb3..0000000000000000 |
||||
--- a/debug/tst-lfschk5.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk2.c" |
||||
diff --git a/debug/tst-lfschk6.cc b/debug/tst-lfschk6.cc |
||||
deleted file mode 100644 |
||||
index 50a1ae1258f1553d..0000000000000000 |
||||
--- a/debug/tst-lfschk6.cc |
||||
+++ /dev/null |
||||
@@ -1,2 +0,0 @@ |
||||
-#define _FILE_OFFSET_BITS 64 |
||||
-#include "tst-chk3.c" |
@ -0,0 +1,356 @@
@@ -0,0 +1,356 @@
|
||||
commit 224d8c1890b6c57c7e4e8ddbb792dd9552086704 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed Jan 12 23:34:48 2022 +0530 |
||||
|
||||
debug: Synchronize feature guards in fortified functions [BZ #28746] |
||||
|
||||
Some functions (e.g. stpcpy, pread64, etc.) had moved to POSIX in the |
||||
main headers as they got incorporated into the standard, but their |
||||
fortified variants remained under __USE_GNU. As a result, these |
||||
functions did not get fortified when _GNU_SOURCE was not defined. |
||||
|
||||
Add test wrappers that check all functions tested in tst-chk0 at all |
||||
levels with _GNU_SOURCE undefined and then use the failures to (1) |
||||
exclude checks for _GNU_SOURCE functions in these tests and (2) Fix |
||||
feature macro guards in the fortified function headers so that they're |
||||
the same as the ones in the main headers. |
||||
|
||||
This fixes BZ #28746. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit fcfc9086815bf0d277ad47a90ee3fda4c37acca8) |
||||
|
||||
diff --git a/debug/Makefile b/debug/Makefile |
||||
index acc1b8f6ad029c62..71248e0d457a5b12 100644 |
||||
--- a/debug/Makefile |
||||
+++ b/debug/Makefile |
||||
@@ -132,6 +132,12 @@ define cflags-lfs |
||||
CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64 |
||||
endef |
||||
|
||||
+define cflags-nongnu |
||||
+CFLAGS-tst-fortify-$(1)-nongnu-$(2).$(1) += -D_LARGEFILE64_SOURCE=1 |
||||
+endef |
||||
+ |
||||
+src-chk-nongnu = \#undef _GNU_SOURCE |
||||
+ |
||||
# We know these tests have problems with format strings, this is what |
||||
# we are testing. Disable that warning. They are also testing |
||||
# deprecated functions (notably gets) so disable that warning as well. |
||||
@@ -145,13 +151,13 @@ CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \ |
||||
$(eval $(call cflags-$(2),$(1),$(3))) |
||||
$(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile |
||||
( echo "/* Autogenerated from Makefile. */"; \ |
||||
- echo ""; \ |
||||
+ echo "$(src-chk-$(2))"; \ |
||||
echo "#include \"tst-fortify.c\"" ) > $$@.tmp |
||||
mv $$@.tmp $$@ |
||||
endef |
||||
|
||||
chk-extensions = c cc |
||||
-chk-types = default lfs |
||||
+chk-types = default lfs nongnu |
||||
chk-levels = 1 2 3 |
||||
|
||||
$(foreach e,$(chk-extensions), \ |
||||
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c |
||||
index 68ac00d1808382b8..8b5902423cf0ad88 100644 |
||||
--- a/debug/tst-fortify.c |
||||
+++ b/debug/tst-fortify.c |
||||
@@ -1,4 +1,5 @@ |
||||
-/* Copyright (C) 2004-2021 Free Software Foundation, Inc. |
||||
+/* Copyright (C) 2004-2022 Free Software Foundation, Inc. |
||||
+ Copyright The GNU Toolchain Authors. |
||||
This file is part of the GNU C Library. |
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. |
||||
|
||||
@@ -37,6 +38,17 @@ |
||||
#include <sys/socket.h> |
||||
#include <sys/un.h> |
||||
|
||||
+#ifndef _GNU_SOURCE |
||||
+# define MEMPCPY memcpy |
||||
+# define WMEMPCPY wmemcpy |
||||
+# define MEMPCPY_RET(x) 0 |
||||
+# define WMEMPCPY_RET(x) 0 |
||||
+#else |
||||
+# define MEMPCPY mempcpy |
||||
+# define WMEMPCPY wmempcpy |
||||
+# define MEMPCPY_RET(x) __builtin_strlen (x) |
||||
+# define WMEMPCPY_RET(x) wcslen (x) |
||||
+#endif |
||||
|
||||
#define obstack_chunk_alloc malloc |
||||
#define obstack_chunk_free free |
||||
@@ -163,7 +175,7 @@ do_test (void) |
||||
if (memcmp (buf, "aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (mempcpy (buf + 5, "abcde", 5) != buf + 10 |
||||
+ if (MEMPCPY (buf + 5, "abcde", 5) != buf + 5 + MEMPCPY_RET ("abcde") |
||||
|| memcmp (buf, "aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -208,7 +220,7 @@ do_test (void) |
||||
if (memcmp (buf, "aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 |
||||
+ if (MEMPCPY (buf + 5, "abcde", l0 + 5) != buf + 5 + MEMPCPY_RET ("abcde") |
||||
|| memcmp (buf, "aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -267,7 +279,8 @@ do_test (void) |
||||
if (memcmp (a.buf1, "aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10 |
||||
+ if (MEMPCPY (a.buf1 + 5, "abcde", l0 + 5) |
||||
+ != a.buf1 + 5 + MEMPCPY_RET ("abcde") |
||||
|| memcmp (a.buf1, "aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -348,6 +361,7 @@ do_test (void) |
||||
bcopy (buf + 1, buf + 2, l0 + 9); |
||||
CHK_FAIL_END |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
CHK_FAIL_START |
||||
p = (char *) mempcpy (buf + 6, "abcde", 5); |
||||
CHK_FAIL_END |
||||
@@ -355,6 +369,7 @@ do_test (void) |
||||
CHK_FAIL_START |
||||
p = (char *) mempcpy (buf + 6, "abcde", l0 + 5); |
||||
CHK_FAIL_END |
||||
+#endif |
||||
|
||||
CHK_FAIL_START |
||||
memset (buf + 9, 'j', 2); |
||||
@@ -465,6 +480,7 @@ do_test (void) |
||||
bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9); |
||||
CHK_FAIL_END |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
CHK_FAIL_START |
||||
p = (char *) mempcpy (a.buf1 + 6, "abcde", 5); |
||||
CHK_FAIL_END |
||||
@@ -472,6 +488,7 @@ do_test (void) |
||||
CHK_FAIL_START |
||||
p = (char *) mempcpy (a.buf1 + 6, "abcde", l0 + 5); |
||||
CHK_FAIL_END |
||||
+#endif |
||||
|
||||
CHK_FAIL_START |
||||
memset (a.buf1 + 9, 'j', 2); |
||||
@@ -551,7 +568,7 @@ do_test (void) |
||||
if (wmemcmp (wbuf, L"aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10 |
||||
+ if (WMEMPCPY (wbuf + 5, L"abcde", 5) != wbuf + 5 + WMEMPCPY_RET (L"abcde") |
||||
|| wmemcmp (wbuf, L"aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -584,7 +601,8 @@ do_test (void) |
||||
if (wmemcmp (wbuf, L"aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10 |
||||
+ if (WMEMPCPY (wbuf + 5, L"abcde", l0 + 5) |
||||
+ != wbuf + 5 + WMEMPCPY_RET (L"abcde") |
||||
|| wmemcmp (wbuf, L"aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -626,7 +644,8 @@ do_test (void) |
||||
if (wmemcmp (wa.buf1, L"aabcdefghi", 10)) |
||||
FAIL (); |
||||
|
||||
- if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10 |
||||
+ if (WMEMPCPY (wa.buf1 + 5, L"abcde", l0 + 5) |
||||
+ != wa.buf1 + 5 + WMEMPCPY_RET (L"abcde") |
||||
|| wmemcmp (wa.buf1, L"aabcdabcde", 10)) |
||||
FAIL (); |
||||
|
||||
@@ -695,6 +714,7 @@ do_test (void) |
||||
wmemmove (wbuf + 2, wbuf + 1, l0 + 9); |
||||
CHK_FAIL_END |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
CHK_FAIL_START |
||||
wp = wmempcpy (wbuf + 6, L"abcde", 5); |
||||
CHK_FAIL_END |
||||
@@ -702,6 +722,7 @@ do_test (void) |
||||
CHK_FAIL_START |
||||
wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5); |
||||
CHK_FAIL_END |
||||
+#endif |
||||
|
||||
CHK_FAIL_START |
||||
wmemset (wbuf + 9, L'j', 2); |
||||
@@ -769,6 +790,7 @@ do_test (void) |
||||
wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9); |
||||
CHK_FAIL_END |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
CHK_FAIL_START |
||||
wp = wmempcpy (wa.buf1 + 6, L"abcde", 5); |
||||
CHK_FAIL_END |
||||
@@ -776,6 +798,7 @@ do_test (void) |
||||
CHK_FAIL_START |
||||
wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5); |
||||
CHK_FAIL_END |
||||
+#endif |
||||
|
||||
CHK_FAIL_START |
||||
wmemset (wa.buf1 + 9, L'j', 2); |
||||
@@ -907,6 +930,7 @@ do_test (void) |
||||
if (fprintf (fp, buf2 + 4, str5) != 7) |
||||
FAIL (); |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
char *my_ptr = NULL; |
||||
strcpy (buf2 + 2, "%n%s%n"); |
||||
/* When the format string is writable and contains %n, |
||||
@@ -936,6 +960,7 @@ do_test (void) |
||||
if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14) |
||||
FAIL (); |
||||
obstack_free (&obs, NULL); |
||||
+#endif |
||||
|
||||
if (freopen (temp_filename, "r", stdin) == NULL) |
||||
{ |
||||
@@ -983,6 +1008,7 @@ do_test (void) |
||||
|
||||
rewind (stdin); |
||||
|
||||
+#ifdef _GNU_SOURCE |
||||
if (fgets_unlocked (buf, buf_size, stdin) != buf |
||||
|| memcmp (buf, "abcdefgh\n", 10)) |
||||
FAIL (); |
||||
@@ -1009,6 +1035,7 @@ do_test (void) |
||||
#endif |
||||
|
||||
rewind (stdin); |
||||
+#endif |
||||
|
||||
if (fread (buf, 1, buf_size, stdin) != buf_size |
||||
|| memcmp (buf, "abcdefgh\nA", 10)) |
||||
@@ -1579,7 +1606,10 @@ do_test (void) |
||||
ret = 1; |
||||
} |
||||
|
||||
- int fd = posix_openpt (O_RDWR); |
||||
+ int fd; |
||||
+ |
||||
+#ifdef _GNU_SOURCE |
||||
+ fd = posix_openpt (O_RDWR); |
||||
if (fd != -1) |
||||
{ |
||||
char enough[1000]; |
||||
@@ -1595,6 +1625,7 @@ do_test (void) |
||||
#endif |
||||
close (fd); |
||||
} |
||||
+#endif |
||||
|
||||
#if PATH_MAX > 0 |
||||
confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf)); |
||||
@@ -1712,8 +1743,9 @@ do_test (void) |
||||
poll (fds, l0 + 2, 0); |
||||
CHK_FAIL_END |
||||
#endif |
||||
+#ifdef _GNU_SOURCE |
||||
ppoll (fds, 1, NULL, NULL); |
||||
-#if __USE_FORTIFY_LEVEL >= 1 |
||||
+# if __USE_FORTIFY_LEVEL >= 1 |
||||
CHK_FAIL_START |
||||
ppoll (fds, 2, NULL, NULL); |
||||
CHK_FAIL_END |
||||
@@ -1721,6 +1753,7 @@ do_test (void) |
||||
CHK_FAIL_START |
||||
ppoll (fds, l0 + 2, NULL, NULL); |
||||
CHK_FAIL_END |
||||
+# endif |
||||
#endif |
||||
|
||||
return ret; |
||||
diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h |
||||
index 697dcbbf7b4b26f6..1df7e5ceef3e1fd4 100644 |
||||
--- a/posix/bits/unistd.h |
||||
+++ b/posix/bits/unistd.h |
||||
@@ -40,7 +40,7 @@ read (int __fd, void *__buf, size_t __nbytes) |
||||
__fd, __buf, __nbytes); |
||||
} |
||||
|
||||
-#ifdef __USE_UNIX98 |
||||
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 |
||||
extern ssize_t __pread_chk (int __fd, void *__buf, size_t __nbytes, |
||||
__off_t __offset, size_t __bufsize) |
||||
__wur __attr_access ((__write_only__, 2, 3)); |
||||
diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h |
||||
index 5731274848260ad2..218006c9ba882d9c 100644 |
||||
--- a/string/bits/string_fortified.h |
||||
+++ b/string/bits/string_fortified.h |
||||
@@ -79,7 +79,7 @@ __NTH (strcpy (char *__restrict __dest, const char *__restrict __src)) |
||||
return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest)); |
||||
} |
||||
|
||||
-#ifdef __USE_GNU |
||||
+#ifdef __USE_XOPEN2K8 |
||||
__fortify_function char * |
||||
__NTH (stpcpy (char *__restrict __dest, const char *__restrict __src)) |
||||
{ |
||||
@@ -96,14 +96,15 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src, |
||||
__glibc_objsize (__dest)); |
||||
} |
||||
|
||||
-#if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) |
||||
+#ifdef __USE_XOPEN2K8 |
||||
+# if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) |
||||
__fortify_function char * |
||||
__NTH (stpncpy (char *__dest, const char *__src, size_t __n)) |
||||
{ |
||||
return __builtin___stpncpy_chk (__dest, __src, __n, |
||||
__glibc_objsize (__dest)); |
||||
} |
||||
-#else |
||||
+# else |
||||
extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, |
||||
size_t __destlen) __THROW |
||||
__fortified_attr_access ((__write_only__, 1, 3)) |
||||
@@ -119,6 +120,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) |
||||
return __stpncpy_chk (__dest, __src, __n, __bos (__dest)); |
||||
return __stpncpy_alias (__dest, __src, __n); |
||||
} |
||||
+# endif |
||||
#endif |
||||
|
||||
|
||||
diff --git a/support/xsignal.h b/support/xsignal.h |
||||
index 8ee1fa6b4dceeadf..692e0f2c4242d848 100644 |
||||
--- a/support/xsignal.h |
||||
+++ b/support/xsignal.h |
||||
@@ -28,7 +28,9 @@ __BEGIN_DECLS |
||||
terminate the process on error. */ |
||||
|
||||
void xraise (int sig); |
||||
+#ifdef _GNU_SOURCE |
||||
sighandler_t xsignal (int sig, sighandler_t handler); |
||||
+#endif |
||||
void xsigaction (int sig, const struct sigaction *newact, |
||||
struct sigaction *oldact); |
||||
|
||||
diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h |
||||
index 26012ef9366c0b88..88c1fdfcd34292f4 100644 |
||||
--- a/wcsmbs/bits/wchar2.h |
||||
+++ b/wcsmbs/bits/wchar2.h |
||||
@@ -457,7 +457,7 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src, |
||||
} |
||||
|
||||
|
||||
-#ifdef __USE_GNU |
||||
+#ifdef __USE_XOPEN2K8 |
||||
extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst, |
||||
const char **__restrict __src, size_t __nmc, |
||||
size_t __len, mbstate_t *__restrict __ps, |
@ -0,0 +1,178 @@
@@ -0,0 +1,178 @@
|
||||
commit 738ee53f0ce5e39b9b7a6777f5d3057afbaac498 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Tue Mar 15 23:12:37 2022 +0000 |
||||
|
||||
hppa: Implement swapcontext in assembler (bug 28960) |
||||
|
||||
When swapcontext.c is compiled without -g, the following error occurs: |
||||
Error: CFI instruction used without previous .cfi_startproc |
||||
|
||||
Fix by converting swapcontext routine to assembler. |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.S b/sysdeps/unix/sysv/linux/hppa/swapcontext.S |
||||
new file mode 100644 |
||||
index 0000000000000000..94b164dc6375563e |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/swapcontext.S |
||||
@@ -0,0 +1,72 @@ |
||||
+/* Swap to new context. |
||||
+ Copyright (C) 2008-2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library. If not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <sysdep.h> |
||||
+#include "ucontext_i.h" |
||||
+ |
||||
+ .text |
||||
+ENTRY(__swapcontext) |
||||
+ |
||||
+ /* Copy rp to ret0 (r28). */ |
||||
+ copy %rp,%ret0 |
||||
+ |
||||
+ /* Create a frame. */ |
||||
+ ldo 64(%sp),%sp |
||||
+ .cfi_def_cfa_offset -64 |
||||
+ |
||||
+ /* Save the current machine context to oucp. */ |
||||
+ bl __getcontext,%rp |
||||
+ |
||||
+ /* Copy oucp to register ret1 (r29). __getcontext saves and |
||||
+ restores it on a normal return. It is restored from oR29 |
||||
+ on reactivation. */ |
||||
+ copy %r26,%ret1 |
||||
+ |
||||
+ /* Pop frame. */ |
||||
+ ldo -64(%sp),%sp |
||||
+ .cfi_def_cfa_offset 0 |
||||
+ |
||||
+ /* Load return pointer from oR28. */ |
||||
+ ldw oR28(%ret1),%rp |
||||
+ |
||||
+ /* Return if error. */ |
||||
+ or,= %r0,%ret0,%r0 |
||||
+ bv,n %r0(%rp) |
||||
+ |
||||
+ /* Load sc_sar flag. */ |
||||
+ ldb oSAR(%ret1),%r20 |
||||
+ |
||||
+ /* Return if oucp context has been reactivated. */ |
||||
+ or,= %r0,%r20,%r0 |
||||
+ bv,n %r0(%rp) |
||||
+ |
||||
+ /* Mark sc_sar flag. */ |
||||
+ ldi 1,%r20 |
||||
+ stb %r20,oSAR(%ret1) |
||||
+ |
||||
+ /* Activate the machine context in ucp. */ |
||||
+ bl __setcontext,%rp |
||||
+ ldw oR25(%ret1),%r26 |
||||
+ |
||||
+ /* Load return pointer. */ |
||||
+ ldw oR28(%ret1),%rp |
||||
+ bv,n %r0(%rp) |
||||
+ |
||||
+PSEUDO_END(__swapcontext) |
||||
+ |
||||
+weak_alias (__swapcontext, swapcontext) |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.c b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
deleted file mode 100644 |
||||
index 1664f68c7b9982e8..0000000000000000 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
||||
+++ /dev/null |
||||
@@ -1,83 +0,0 @@ |
||||
-/* Swap to new context. |
||||
- Copyright (C) 2008-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- Contributed by Helge Deller <deller@gmx.de>, 2008. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library. If not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#include <ucontext.h> |
||||
-#include "ucontext_i.h" |
||||
- |
||||
-extern int __getcontext (ucontext_t *ucp); |
||||
-extern int __setcontext (const ucontext_t *ucp); |
||||
- |
||||
-int |
||||
-__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
||||
-{ |
||||
- /* Save rp for debugger. */ |
||||
- asm ("stw %rp,-20(%sp)"); |
||||
- asm (".cfi_offset 2, -20"); |
||||
- |
||||
- /* Copy rp to ret0 (r28). */ |
||||
- asm ("copy %rp,%ret0"); |
||||
- |
||||
- /* Create a frame. */ |
||||
- asm ("ldo 64(%sp),%sp"); |
||||
- asm (".cfi_def_cfa_offset -64"); |
||||
- |
||||
- /* Save the current machine context to oucp. */ |
||||
- asm ("bl __getcontext,%rp"); |
||||
- |
||||
- /* Copy oucp to register ret1 (r29). __getcontext saves and restores it |
||||
- on a normal return. It is restored from oR29 on reactivation. */ |
||||
- asm ("copy %r26,%ret1"); |
||||
- |
||||
- /* Pop frame. */ |
||||
- asm ("ldo -64(%sp),%sp"); |
||||
- asm (".cfi_def_cfa_offset 0"); |
||||
- |
||||
- /* Load return pointer from oR28. */ |
||||
- asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28)); |
||||
- |
||||
- /* Return if error. */ |
||||
- asm ("or,= %r0,%ret0,%r0"); |
||||
- asm ("bv,n %r0(%rp)"); |
||||
- |
||||
- /* Load sc_sar flag. */ |
||||
- asm ("ldb %0(%%ret1),%%r20" : : "i" (oSAR)); |
||||
- |
||||
- /* Return if oucp context has been reactivated. */ |
||||
- asm ("or,= %r0,%r20,%r0"); |
||||
- asm ("bv,n %r0(%rp)"); |
||||
- |
||||
- /* Mark sc_sar flag. */ |
||||
- asm ("1: ldi 1,%r20"); |
||||
- asm ("stb %%r20,%0(%%ret1)" : : "i" (oSAR)); |
||||
- |
||||
- /* Activate the machine context in ucp. */ |
||||
- asm ("bl __setcontext,%rp"); |
||||
- asm ("ldw %0(%%ret1),%%r26" : : "i" (oR25)); |
||||
- |
||||
- /* Load return pointer. */ |
||||
- asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28)); |
||||
- |
||||
- /* A successful call to setcontext does not return. */ |
||||
- asm ("bv,n %r0(%rp)"); |
||||
- |
||||
- /* Make gcc happy. */ |
||||
- return 0; |
||||
-} |
||||
- |
||||
-weak_alias (__swapcontext, swapcontext) |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
commit d53b9cc391c72a1011ea8fe7a9f70dc5060a0db2 |
||||
Author: John David Anglin <danglin@gcc.gnu.org> |
||||
Date: Tue Mar 15 23:04:39 2022 +0000 |
||||
|
||||
hppa: Use END instead of PSEUDO_END in swapcontext.S |
||||
|
||||
(cherry picked from commit 7a5c440102d4ec7fafd9bbd98eca9bd90ecaaafd) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.S b/sysdeps/unix/sysv/linux/hppa/swapcontext.S |
||||
index 94b164dc6375563e..fbc22586d1195a0d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/swapcontext.S |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/swapcontext.S |
||||
@@ -67,6 +67,6 @@ ENTRY(__swapcontext) |
||||
ldw oR28(%ret1),%rp |
||||
bv,n %r0(%rp) |
||||
|
||||
-PSEUDO_END(__swapcontext) |
||||
+END(__swapcontext) |
||||
|
||||
weak_alias (__swapcontext, swapcontext) |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
commit 4b5b8a1cdf39bed02b8b973717796eccde455ed6 |
||||
Author: Fangrui Song <maskray@google.com> |
||||
Date: Mon Sep 27 10:12:50 2021 -0700 |
||||
|
||||
powerpc: Delete unneeded ELF_MACHINE_BEFORE_RTLD_RELOC |
||||
|
||||
Reviewed-by: Raphael M Zinsly <rzinsly@linux.ibm.com> |
||||
(cherry picked from commit 8e2557a2b85b2eb0ed50a9016a4ffc6b859b97e6) |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h |
||||
index ced3a7b659cfcff1..b93cf486b6cda5fd 100644 |
||||
--- a/sysdeps/powerpc/powerpc32/dl-machine.h |
||||
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h |
||||
@@ -109,8 +109,6 @@ elf_machine_load_address (void) |
||||
return runtime_dynamic - elf_machine_dynamic (); |
||||
} |
||||
|
||||
-#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */ |
||||
- |
||||
/* The PLT uses Elf32_Rela relocs. */ |
||||
#define elf_machine_relplt elf_machine_rela |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h |
||||
index b90f407119efd431..b3f3352bcf5a52b0 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/dl-machine.h |
||||
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h |
||||
@@ -116,8 +116,6 @@ elf_machine_dynamic (void) |
||||
return runtime_dynamic - elf_machine_load_address() ; |
||||
} |
||||
|
||||
-#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */ |
||||
- |
||||
/* The PLT uses Elf64_Rela relocs. */ |
||||
#define elf_machine_relplt elf_machine_rela |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,241 @@
@@ -0,0 +1,241 @@
|
||||
commit c6df39a0bd2aafd2a4280a0000ef201f30273bee |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Mon Oct 11 16:01:49 2021 -0300 |
||||
|
||||
elf: Fix elf_get_dynamic_info definition |
||||
|
||||
Before to 490e6c62aa31a8a ('elf: Avoid nested functions in the loader |
||||
[BZ #27220]'), elf_get_dynamic_info() was defined twice on rtld.c: on |
||||
the first dynamic-link.h include and later within _dl_start(). The |
||||
former definition did not define DONT_USE_BOOTSTRAP_MAP and it is used |
||||
on setup_vdso() (since it is a global definition), while the former does |
||||
define DONT_USE_BOOTSTRAP_MAP and it is used on loader self-relocation. |
||||
|
||||
With the commit change, the function is now included and defined once |
||||
instead of defined as a nested function. So rtld.c defines without |
||||
defining RTLD_BOOTSTRAP and it brokes at least powerpc32. |
||||
|
||||
This patch fixes by moving the get-dynamic-info.h include out of |
||||
dynamic-link.h, which then the caller can corirectly set the expected |
||||
semantic by defining STATIC_PIE_BOOTSTRAP, RTLD_BOOTSTRAP, and/or |
||||
RESOLVE_MAP. |
||||
|
||||
It also required to enable some asserts only for the loader bootstrap |
||||
to avoid issues when called from setup_vdso(). |
||||
|
||||
As a side note, this is another issues with nested functions: it is |
||||
not clear from pre-processed output (-E -dD) how the function will |
||||
be build and its semantic (since nested function will be local and |
||||
extra C defines may change it). |
||||
|
||||
I checked on x86_64-linux-gnu (w/o --enable-static-pie), |
||||
i686-linux-gnu, powerpc64-linux-gnu, powerpc-linux-gnu-power4, |
||||
aarch64-linux-gnu, arm-linux-gnu, sparc64-linux-gnu, and |
||||
s390x-linux-gnu. |
||||
|
||||
Reviewed-by: Fangrui Song <maskray@google.com> |
||||
(cherry picked from commit 4af6982e4c9fc465ffb7a54b794aaaa134241f05) |
||||
|
||||
Resolved conflicts: |
||||
elf/rtld.c |
||||
|
||||
diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c |
||||
index 5c8e51d19ae095d6..d54356dee3f86ae0 100644 |
||||
--- a/elf/dl-conflict.c |
||||
+++ b/elf/dl-conflict.c |
||||
@@ -17,6 +17,7 @@ |
||||
License along with the GNU C Library; see the file COPYING.LIB. If |
||||
not, see <https://www.gnu.org/licenses/>. */ |
||||
|
||||
+#include <assert.h> |
||||
#include <errno.h> |
||||
#include <libintl.h> |
||||
#include <stdlib.h> |
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index 0976977fbdf21902..eea06629a978aaf3 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -58,6 +58,7 @@ struct filebuf |
||||
}; |
||||
|
||||
#include "dynamic-link.h" |
||||
+#include "get-dynamic-info.h" |
||||
#include <abi-tag.h> |
||||
#include <stackinfo.h> |
||||
#include <sysdep.h> |
||||
@@ -1295,7 +1296,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, |
||||
if (l->l_ld != 0) |
||||
l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); |
||||
|
||||
- elf_get_dynamic_info (l); |
||||
+ elf_get_dynamic_info (l, false); |
||||
|
||||
/* Make sure we are not dlopen'ing an object that has the |
||||
DF_1_NOOPEN flag set, or a PIE object. */ |
||||
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c |
||||
index a52ba8aeb8b573cb..f323b4dd0d5ba279 100644 |
||||
--- a/elf/dl-reloc-static-pie.c |
||||
+++ b/elf/dl-reloc-static-pie.c |
||||
@@ -28,6 +28,7 @@ |
||||
#define STATIC_PIE_BOOTSTRAP |
||||
#define RESOLVE_MAP(map, scope, sym, version, flags) map |
||||
#include "dynamic-link.h" |
||||
+#include "get-dynamic-info.h" |
||||
|
||||
/* Relocate static executable with PIE. */ |
||||
|
||||
@@ -51,7 +52,7 @@ _dl_relocate_static_pie (void) |
||||
break; |
||||
} |
||||
|
||||
- elf_get_dynamic_info (main_map); |
||||
+ elf_get_dynamic_info (main_map, false); |
||||
|
||||
# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC |
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (main_map, main_map->l_info); |
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c |
||||
index 9d0d941000f6114f..61c260ddb81b586c 100644 |
||||
--- a/elf/dl-runtime.c |
||||
+++ b/elf/dl-runtime.c |
||||
@@ -19,6 +19,7 @@ |
||||
#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */ |
||||
|
||||
#include <alloca.h> |
||||
+#include <assert.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <sys/param.h> |
||||
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h |
||||
index 7cc30211649d3820..21cdfc88bbfb89ea 100644 |
||||
--- a/elf/dynamic-link.h |
||||
+++ b/elf/dynamic-link.h |
||||
@@ -93,7 +93,6 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], |
||||
|
||||
#include <dl-machine.h> |
||||
|
||||
-#include "get-dynamic-info.h" |
||||
|
||||
#ifdef RESOLVE_MAP |
||||
|
||||
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h |
||||
index 15c316b38c05a90c..d169099fbc9897cf 100644 |
||||
--- a/elf/get-dynamic-info.h |
||||
+++ b/elf/get-dynamic-info.h |
||||
@@ -25,7 +25,7 @@ |
||||
#include <libc-diag.h> |
||||
|
||||
static inline void __attribute__ ((unused, always_inline)) |
||||
-elf_get_dynamic_info (struct link_map *l) |
||||
+elf_get_dynamic_info (struct link_map *l, bool check) |
||||
{ |
||||
#if __ELF_NATIVE_CLASS == 32 |
||||
typedef Elf32_Word d_tag_utype; |
||||
@@ -112,16 +112,19 @@ elf_get_dynamic_info (struct link_map *l) |
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); |
||||
#endif |
||||
#ifdef RTLD_BOOTSTRAP |
||||
- /* Only the bind now flags are allowed. */ |
||||
- assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL |
||||
- || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); |
||||
- /* Flags must not be set for ld.so. */ |
||||
- assert (info[DT_FLAGS] == NULL |
||||
- || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); |
||||
-#endif |
||||
-#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP |
||||
- assert (info[DT_RUNPATH] == NULL); |
||||
- assert (info[DT_RPATH] == NULL); |
||||
+ if (check) |
||||
+ { |
||||
+ /* Only the bind now flags are allowed. */ |
||||
+ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL |
||||
+ || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); |
||||
+ /* Flags must not be set for ld.so. */ |
||||
+ assert (info[DT_FLAGS] == NULL |
||||
+ || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); |
||||
+# ifdef STATIC_PIE_BOOTSTRAP |
||||
+ assert (info[DT_RUNPATH] == NULL); |
||||
+ assert (info[DT_RPATH] == NULL); |
||||
+# endif |
||||
+ } |
||||
#else |
||||
if (info[DT_FLAGS] != NULL) |
||||
{ |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index ee45657aeac14f3c..352d596dedb42e79 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -514,6 +514,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) |
||||
is trivial: always the map of ld.so itself. */ |
||||
#define RTLD_BOOTSTRAP |
||||
#define RESOLVE_MAP(map, scope, sym, version, flags) map |
||||
+#include "get-dynamic-info.h" |
||||
#include "dynamic-link.h" |
||||
|
||||
static ElfW(Addr) __attribute_used__ |
||||
@@ -549,7 +550,7 @@ _dl_start (void *arg) |
||||
/* Read our own dynamic section and fill in the info array. */ |
||||
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); |
||||
bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION; |
||||
- elf_get_dynamic_info (&bootstrap_map); |
||||
+ elf_get_dynamic_info (&bootstrap_map, true); |
||||
|
||||
#if NO_TLS_OFFSET != 0 |
||||
bootstrap_map.l_tls_offset = NO_TLS_OFFSET; |
||||
@@ -1653,7 +1654,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
if (! rtld_is_main) |
||||
{ |
||||
/* Extract the contents of the dynamic section for easy access. */ |
||||
- elf_get_dynamic_info (main_map); |
||||
+ elf_get_dynamic_info (main_map, false); |
||||
|
||||
/* If the main map is libc.so, update the base namespace to |
||||
refer to this map. If libc.so is loaded later, this happens |
||||
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h |
||||
index f44748bc9858e5fd..6fdffafcca5e9916 100644 |
||||
--- a/elf/setup-vdso.h |
||||
+++ b/elf/setup-vdso.h |
||||
@@ -64,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), |
||||
l->l_map_end += l->l_addr; |
||||
l->l_text_end += l->l_addr; |
||||
l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr); |
||||
- elf_get_dynamic_info (l); |
||||
+ elf_get_dynamic_info (l, false); |
||||
_dl_setup_hash (l); |
||||
l->l_relocated = 1; |
||||
|
||||
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h |
||||
index 7e6761bbe87540d5..86f866ca7c17bd9b 100644 |
||||
--- a/sysdeps/arm/dl-machine.h |
||||
+++ b/sysdeps/arm/dl-machine.h |
||||
@@ -21,6 +21,7 @@ |
||||
|
||||
#define ELF_MACHINE_NAME "ARM" |
||||
|
||||
+#include <assert.h> |
||||
#include <sys/param.h> |
||||
#include <tls.h> |
||||
#include <dl-tlsdesc.h> |
||||
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h |
||||
index 78ce890c0ff333ca..fa902612ca8557f9 100644 |
||||
--- a/sysdeps/i386/dl-machine.h |
||||
+++ b/sysdeps/i386/dl-machine.h |
||||
@@ -21,6 +21,7 @@ |
||||
|
||||
#define ELF_MACHINE_NAME "i386" |
||||
|
||||
+#include <assert.h> |
||||
#include <sys/param.h> |
||||
#include <sysdep.h> |
||||
#include <tls.h> |
||||
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h |
||||
index d3fcbb37bf1f4f7c..90c77cfea1de8d63 100644 |
||||
--- a/sysdeps/x86_64/dl-machine.h |
||||
+++ b/sysdeps/x86_64/dl-machine.h |
||||
@@ -22,6 +22,7 @@ |
||||
|
||||
#define ELF_MACHINE_NAME "x86_64" |
||||
|
||||
+#include <assert.h> |
||||
#include <sys/param.h> |
||||
#include <sysdep.h> |
||||
#include <tls.h> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,221 @@
@@ -0,0 +1,221 @@
|
||||
commit f6a54a304223666ea4af73260c99c830d7726eca |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Fri Oct 15 14:35:31 2021 -0300 |
||||
|
||||
elf: Fix elf_get_dynamic_info() for bootstrap |
||||
|
||||
THe d6d89608ac8c broke powerpc for --enable-bind-now because it turned |
||||
out that different than patch assumption rtld elf_get_dynamic_info() |
||||
does require to handle RTLD_BOOTSTRAP to avoid DT_FLAGS and |
||||
DT_RUNPATH (more specially the GLRO usage which is not reallocate |
||||
yet). |
||||
|
||||
This patch fixes by passing two arguments to elf_get_dynamic_info() |
||||
to inform that by rtld (bootstrap) or static pie initialization |
||||
(static_pie_bootstrap). I think using explicit argument is way more |
||||
clear and burried C preprocessor, and compiler should remove the |
||||
dead code. |
||||
|
||||
I checked on x86_64 and i686 with default options, --enable-bind-now, |
||||
and --enable-bind-now and --enable--static-pie. I also check on |
||||
aarch64, armhf, powerpc64, and powerpc with default and |
||||
--enable-bind-now. |
||||
|
||||
(cherry picked from commit 5118dcac68c4eadfd6304bb33adde63d062dc07f) |
||||
|
||||
Resolved conflicts: |
||||
elf/rtld.c - Manual merge. |
||||
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index fb3da5aa565908a6..a920b12a906a9dec 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -1296,7 +1296,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, |
||||
if (l->l_ld != 0) |
||||
l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); |
||||
|
||||
- elf_get_dynamic_info (l); |
||||
+ elf_get_dynamic_info (l, false, false); |
||||
|
||||
/* Make sure we are not dlopen'ing an object that has the |
||||
DF_1_NOOPEN flag set, or a PIE object. */ |
||||
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c |
||||
index ababafcf98f9945d..757205affe65d9e1 100644 |
||||
--- a/elf/dl-reloc-static-pie.c |
||||
+++ b/elf/dl-reloc-static-pie.c |
||||
@@ -25,7 +25,6 @@ |
||||
|
||||
#include <dl-machine.h> |
||||
|
||||
-#define STATIC_PIE_BOOTSTRAP |
||||
#define RESOLVE_MAP(map, scope, sym, version, flags) map |
||||
#include "dynamic-link.h" |
||||
#include "get-dynamic-info.h" |
||||
@@ -52,7 +51,7 @@ _dl_relocate_static_pie (void) |
||||
break; |
||||
} |
||||
|
||||
- elf_get_dynamic_info (main_map); |
||||
+ elf_get_dynamic_info (main_map, false, true); |
||||
|
||||
# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC |
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (main_map, main_map->l_info); |
||||
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h |
||||
index 1ac0663d1ff5de24..f63e07dc6d2cd5e6 100644 |
||||
--- a/elf/get-dynamic-info.h |
||||
+++ b/elf/get-dynamic-info.h |
||||
@@ -26,7 +26,8 @@ |
||||
#include <libc-diag.h> |
||||
|
||||
static inline void __attribute__ ((unused, always_inline)) |
||||
-elf_get_dynamic_info (struct link_map *l) |
||||
+elf_get_dynamic_info (struct link_map *l, bool bootstrap, |
||||
+ bool static_pie_bootstrap) |
||||
{ |
||||
#if __ELF_NATIVE_CLASS == 32 |
||||
typedef Elf32_Word d_tag_utype; |
||||
@@ -35,7 +36,7 @@ elf_get_dynamic_info (struct link_map *l) |
||||
#endif |
||||
|
||||
#ifndef STATIC_PIE_BOOTSTRAP |
||||
- if (l->l_ld == NULL) |
||||
+ if (!bootstrap && l->l_ld == NULL) |
||||
return; |
||||
#endif |
||||
|
||||
@@ -112,47 +113,63 @@ elf_get_dynamic_info (struct link_map *l) |
||||
if (info[DT_REL] != NULL) |
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); |
||||
#endif |
||||
-#ifdef STATIC_PIE_BOOTSTRAP |
||||
- assert (info[DT_RUNPATH] == NULL); |
||||
- assert (info[DT_RPATH] == NULL); |
||||
-#endif |
||||
- if (info[DT_FLAGS] != NULL) |
||||
+ if (bootstrap || static_pie_bootstrap) |
||||
{ |
||||
- /* Flags are used. Translate to the old form where available. |
||||
- Since these l_info entries are only tested for NULL pointers it |
||||
- is ok if they point to the DT_FLAGS entry. */ |
||||
- l->l_flags = info[DT_FLAGS]->d_un.d_val; |
||||
- |
||||
- if (l->l_flags & DF_SYMBOLIC) |
||||
- info[DT_SYMBOLIC] = info[DT_FLAGS]; |
||||
- if (l->l_flags & DF_TEXTREL) |
||||
- info[DT_TEXTREL] = info[DT_FLAGS]; |
||||
- if (l->l_flags & DF_BIND_NOW) |
||||
- info[DT_BIND_NOW] = info[DT_FLAGS]; |
||||
+ assert (info[DT_RUNPATH] == NULL); |
||||
+ assert (info[DT_RPATH] == NULL); |
||||
} |
||||
- if (info[VERSYMIDX (DT_FLAGS_1)] != NULL) |
||||
+ if (bootstrap) |
||||
{ |
||||
- l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; |
||||
- if (l->l_flags_1 & DF_1_NODELETE) |
||||
- l->l_nodelete_pending = true; |
||||
- |
||||
- /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like |
||||
- to assert this, but we can't. Users have been setting |
||||
- unsupported DF_1_* flags for a long time and glibc has ignored |
||||
- them. Therefore to avoid breaking existing applications the |
||||
- best we can do is add a warning during debugging with the |
||||
- intent of notifying the user of the problem. */ |
||||
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) |
||||
- && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) |
||||
- _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n", |
||||
- l->l_flags_1 & ~DT_1_SUPPORTED_MASK); |
||||
- |
||||
- if (l->l_flags_1 & DF_1_NOW) |
||||
- info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)]; |
||||
+ /* Only the bind now flags are allowed. */ |
||||
+ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL |
||||
+ || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); |
||||
+ /* Flags must not be set for ld.so. */ |
||||
+ assert (info[DT_FLAGS] == NULL |
||||
+ || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); |
||||
} |
||||
- if (info[DT_RUNPATH] != NULL) |
||||
- /* If both RUNPATH and RPATH are given, the latter is ignored. */ |
||||
- info[DT_RPATH] = NULL; |
||||
+ else |
||||
+ { |
||||
+ if (info[DT_FLAGS] != NULL) |
||||
+ { |
||||
+ /* Flags are used. Translate to the old form where available. |
||||
+ Since these l_info entries are only tested for NULL pointers it |
||||
+ is ok if they point to the DT_FLAGS entry. */ |
||||
+ l->l_flags = info[DT_FLAGS]->d_un.d_val; |
||||
+ |
||||
+ if (l->l_flags & DF_SYMBOLIC) |
||||
+ info[DT_SYMBOLIC] = info[DT_FLAGS]; |
||||
+ if (l->l_flags & DF_TEXTREL) |
||||
+ info[DT_TEXTREL] = info[DT_FLAGS]; |
||||
+ if (l->l_flags & DF_BIND_NOW) |
||||
+ info[DT_BIND_NOW] = info[DT_FLAGS]; |
||||
+ } |
||||
+ |
||||
+ if (info[VERSYMIDX (DT_FLAGS_1)] != NULL) |
||||
+ { |
||||
+ l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; |
||||
+ if (l->l_flags_1 & DF_1_NODELETE) |
||||
+ l->l_nodelete_pending = true; |
||||
+ |
||||
+ /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like |
||||
+ to assert this, but we can't. Users have been setting |
||||
+ unsupported DF_1_* flags for a long time and glibc has ignored |
||||
+ them. Therefore to avoid breaking existing applications the |
||||
+ best we can do is add a warning during debugging with the |
||||
+ intent of notifying the user of the problem. */ |
||||
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) |
||||
+ && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) |
||||
+ _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x " |
||||
+ "in DT_FLAGS_1.\n", |
||||
+ l->l_flags_1 & ~DT_1_SUPPORTED_MASK); |
||||
+ |
||||
+ if (l->l_flags_1 & DF_1_NOW) |
||||
+ info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)]; |
||||
+ } |
||||
+ |
||||
+ if (info[DT_RUNPATH] != NULL) |
||||
+ /* If both RUNPATH and RPATH are given, the latter is ignored. */ |
||||
+ info[DT_RPATH] = NULL; |
||||
+ } |
||||
} |
||||
|
||||
#endif |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index 37d28d5a66d7b5d6..ad5ddb2a0ab94e7f 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -549,7 +549,7 @@ _dl_start (void *arg) |
||||
/* Read our own dynamic section and fill in the info array. */ |
||||
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); |
||||
bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION; |
||||
- elf_get_dynamic_info (&bootstrap_map); |
||||
+ elf_get_dynamic_info (&bootstrap_map, true, false); |
||||
|
||||
#if NO_TLS_OFFSET != 0 |
||||
bootstrap_map.l_tls_offset = NO_TLS_OFFSET; |
||||
@@ -1653,7 +1653,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
if (! rtld_is_main) |
||||
{ |
||||
/* Extract the contents of the dynamic section for easy access. */ |
||||
- elf_get_dynamic_info (main_map); |
||||
+ elf_get_dynamic_info (main_map, false, false); |
||||
|
||||
/* If the main map is libc.so, update the base namespace to |
||||
refer to this map. If libc.so is loaded later, this happens |
||||
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h |
||||
index f44748bc9858e5fd..3f20578046de76ed 100644 |
||||
--- a/elf/setup-vdso.h |
||||
+++ b/elf/setup-vdso.h |
||||
@@ -64,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), |
||||
l->l_map_end += l->l_addr; |
||||
l->l_text_end += l->l_addr; |
||||
l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr); |
||||
- elf_get_dynamic_info (l); |
||||
+ elf_get_dynamic_info (l, false, false); |
||||
_dl_setup_hash (l); |
||||
l->l_relocated = 1; |
||||
|
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
commit a31bbe3242266aaea423e5879f38aed69aea1d5e |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Jul 29 11:13:57 2021 -0300 |
||||
|
||||
elf: Move LAV_CURRENT to link_lavcurrent.h |
||||
|
||||
No functional change. |
||||
|
||||
(cherry picked from commit 54816ae98d57930b7c945f17485714a5574bfe47) |
||||
|
||||
Resolved conflicts: |
||||
elf/Makefile |
||||
|
||||
diff --git a/bits/link_lavcurrent.h b/bits/link_lavcurrent.h |
||||
new file mode 100644 |
||||
index 0000000000000000..44fbea1e8060997f |
||||
--- /dev/null |
||||
+++ b/bits/link_lavcurrent.h |
||||
@@ -0,0 +1,25 @@ |
||||
+/* Data structure for communication from the run-time dynamic linker for |
||||
+ loaded ELF shared objects. LAV_CURRENT definition. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef _LINK_H |
||||
+# error "Never include <bits/link_lavcurrent.h> directly; use <link.h> instead." |
||||
+#endif |
||||
+ |
||||
+/* Version numbers for la_version handshake interface. */ |
||||
+#define LAV_CURRENT 1 |
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index cd8725c76f4cfb48..7fa80946ff3aae42 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -24,6 +24,7 @@ include ../Makeconfig |
||||
headers = \ |
||||
bits/elfclass.h \ |
||||
bits/link.h \ |
||||
+ bits/link_lavcurrent.h \ |
||||
elf.h \ |
||||
link.h \ |
||||
# headers |
||||
diff --git a/elf/link.h b/elf/link.h |
||||
index ff3a85c847930b9b..21a351686b9bf7c8 100644 |
||||
--- a/elf/link.h |
||||
+++ b/elf/link.h |
||||
@@ -96,7 +96,7 @@ struct link_map |
||||
#ifdef __USE_GNU |
||||
|
||||
/* Version numbers for la_version handshake interface. */ |
||||
-#define LAV_CURRENT 1 |
||||
+#include <bits/link_lavcurrent.h> |
||||
|
||||
/* Activity types signaled through la_activity. */ |
||||
enum |
@ -0,0 +1,390 @@
@@ -0,0 +1,390 @@
|
||||
commit e25fe992132c460fecc1ab9fade185d5dd3f91ff |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Nov 11 09:28:21 2021 -0300 |
||||
|
||||
elf: Move la_activity (LA_ACT_ADD) after _dl_add_to_namespace_list() (BZ #28062) |
||||
|
||||
It ensures that the the namespace is guaranteed to not be empty. |
||||
|
||||
Checked on x86_64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit ed3ce71f5c64c5f07cbde0ef03554ea8950d8f2c) |
||||
|
||||
Resolved conflicts: |
||||
elf/Makefile |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 7fa80946ff3aae42..bf6da98bdd15a18d 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -363,6 +363,7 @@ tests += \ |
||||
tst-audit15 \ |
||||
tst-audit16 \ |
||||
tst-audit17 \ |
||||
+ tst-audit18 \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
tst-auxobj-dlopen \ |
||||
@@ -623,6 +624,7 @@ modules-names = \ |
||||
tst-audit12mod2 \ |
||||
tst-audit12mod3 \ |
||||
tst-audit13mod1 \ |
||||
+ tst-audit18mod \ |
||||
tst-auditlogmod-1 \ |
||||
tst-auditlogmod-2 \ |
||||
tst-auditlogmod-3 \ |
||||
@@ -640,6 +642,7 @@ modules-names = \ |
||||
tst-auditmod9b \ |
||||
tst-auditmod11 \ |
||||
tst-auditmod12 \ |
||||
+ tst-auditmod18 \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
tst-deep1mod1 \ |
||||
@@ -1999,6 +2002,10 @@ $(objpfx)tst-auditmod17.so: $(objpfx)tst-auditmod17.os |
||||
CFLAGS-.os += $(call elide-stack-protector,.os,tst-auditmod17) |
||||
tst-audit17-ENV = LD_AUDIT=$(objpfx)tst-auditmod17.so |
||||
|
||||
+$(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \ |
||||
+ $(objpfx)tst-audit18mod.so |
||||
+tst-audit18-ARGS = -- $(host-test-program-cmd) |
||||
+ |
||||
# tst-sonamemove links against an older implementation of the library. |
||||
LDFLAGS-tst-sonamemove-linkmod1.so = \ |
||||
-Wl,--version-script=tst-sonamemove-linkmod1.map \ |
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index a920b12a906a9dec..a8c6df3959f2b331 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -1054,42 +1054,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, |
||||
/* This is the ELF header. We read it in `open_verify'. */ |
||||
header = (void *) fbp->buf; |
||||
|
||||
- /* Signal that we are going to add new objects. */ |
||||
- if (r->r_state == RT_CONSISTENT) |
||||
- { |
||||
-#ifdef SHARED |
||||
- /* Auditing checkpoint: we are going to add new objects. */ |
||||
- if ((mode & __RTLD_AUDIT) == 0 |
||||
- && __glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; |
||||
- /* Do not call the functions for any auditing object. */ |
||||
- if (head->l_auditing == 0) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- afct->activity (&link_map_audit_state (head, cnt)->cookie, |
||||
- LA_ACT_ADD); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
-#endif |
||||
- |
||||
- /* Notify the debugger we have added some objects. We need to |
||||
- call _dl_debug_initialize in a static program in case dynamic |
||||
- linking has not been used before. */ |
||||
- r->r_state = RT_ADD; |
||||
- _dl_debug_state (); |
||||
- LIBC_PROBE (map_start, 2, nsid, r); |
||||
- make_consistent = true; |
||||
- } |
||||
- else |
||||
- assert (r->r_state == RT_ADD); |
||||
- |
||||
/* Enter the new object in the list of loaded objects. */ |
||||
l = _dl_new_object (realname, name, l_type, loader, mode, nsid); |
||||
if (__glibc_unlikely (l == NULL)) |
||||
@@ -1511,6 +1475,44 @@ cannot enable executable stack as shared object requires"); |
||||
/* Now that the object is fully initialized add it to the object list. */ |
||||
_dl_add_to_namespace_list (l, nsid); |
||||
|
||||
+ /* Signal that we are going to add new objects. */ |
||||
+ if (r->r_state == RT_CONSISTENT) |
||||
+ { |
||||
+#ifdef SHARED |
||||
+ /* Auditing checkpoint: we are going to add new objects. Since this |
||||
+ is called after _dl_add_to_namespace_list the namespace is guaranteed |
||||
+ to not be empty. */ |
||||
+ if ((mode & __RTLD_AUDIT) == 0 |
||||
+ && __glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
+ { |
||||
+ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; |
||||
+ /* Do not call the functions for any auditing object. */ |
||||
+ if (head->l_auditing == 0) |
||||
+ { |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->activity != NULL) |
||||
+ afct->activity (&link_map_audit_state (head, cnt)->cookie, |
||||
+ LA_ACT_ADD); |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+#endif |
||||
+ |
||||
+ /* Notify the debugger we have added some objects. We need to |
||||
+ call _dl_debug_initialize in a static program in case dynamic |
||||
+ linking has not been used before. */ |
||||
+ r->r_state = RT_ADD; |
||||
+ _dl_debug_state (); |
||||
+ LIBC_PROBE (map_start, 2, nsid, r); |
||||
+ make_consistent = true; |
||||
+ } |
||||
+ else |
||||
+ assert (r->r_state == RT_ADD); |
||||
+ |
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we have a new object. */ |
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0) |
||||
diff --git a/elf/tst-audit18.c b/elf/tst-audit18.c |
||||
new file mode 100644 |
||||
index 0000000000000000..ef784908f60d50aa |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit18.c |
||||
@@ -0,0 +1,129 @@ |
||||
+/* Check DT_AUDIT with dlmopen. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <getopt.h> |
||||
+#include <string.h> |
||||
+#include <stdlib.h> |
||||
+#include <unistd.h> |
||||
+#include <gnu/lib-names.h> |
||||
+#include <support/capture_subprocess.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+#include <support/xstdio.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+static int restart; |
||||
+#define CMDLINE_OPTIONS \ |
||||
+ { "restart", no_argument, &restart, 1 }, |
||||
+ |
||||
+static int |
||||
+handle_restart (void) |
||||
+{ |
||||
+ { |
||||
+ void *h = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); |
||||
+ |
||||
+ pid_t (*s) (void) = xdlsym (h, "getpid"); |
||||
+ TEST_COMPARE (s (), getpid ()); |
||||
+ |
||||
+ xdlclose (h); |
||||
+ } |
||||
+ |
||||
+ { |
||||
+ void *h = xdlmopen (LM_ID_NEWLM, "tst-audit18mod.so", RTLD_NOW); |
||||
+ |
||||
+ int (*foo) (void) = xdlsym (h, "foo"); |
||||
+ TEST_COMPARE (foo (), 10); |
||||
+ |
||||
+ xdlclose (h); |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (int argc, char *argv[]) |
||||
+{ |
||||
+ /* We must have either: |
||||
+ - One our fource parameters left if called initially: |
||||
+ + path to ld.so optional |
||||
+ + "--library-path" optional |
||||
+ + the library path optional |
||||
+ + the application name */ |
||||
+ |
||||
+ if (restart) |
||||
+ return handle_restart (); |
||||
+ |
||||
+ char *spargv[9]; |
||||
+ int i = 0; |
||||
+ for (; i < argc - 1; i++) |
||||
+ spargv[i] = argv[i + 1]; |
||||
+ spargv[i++] = (char *) "--direct"; |
||||
+ spargv[i++] = (char *) "--restart"; |
||||
+ spargv[i] = NULL; |
||||
+ |
||||
+ setenv ("LD_AUDIT", "tst-auditmod18.so", 0); |
||||
+ struct support_capture_subprocess result |
||||
+ = support_capture_subprogram (spargv[0], spargv); |
||||
+ support_capture_subprocess_check (&result, "tst-audit18", 0, sc_allow_stderr); |
||||
+ |
||||
+ struct |
||||
+ { |
||||
+ const char *name; |
||||
+ bool found; |
||||
+ } audit_iface[] = |
||||
+ { |
||||
+ { "la_version", false }, |
||||
+ { "la_objsearch", false }, |
||||
+ { "la_activity", false }, |
||||
+ { "la_objopen", false }, |
||||
+ { "la_objclose", false }, |
||||
+ { "la_preinit", false }, |
||||
+#if __WORDSIZE == 32 |
||||
+ { "la_symbind32", false }, |
||||
+#elif __WORDSIZE == 64 |
||||
+ { "la_symbind64", false }, |
||||
+#endif |
||||
+ }; |
||||
+ |
||||
+ /* Some hooks are called more than once but the test only check if any |
||||
+ is called at least once. */ |
||||
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); |
||||
+ TEST_VERIFY (out != NULL); |
||||
+ char *buffer = NULL; |
||||
+ size_t buffer_length = 0; |
||||
+ while (xgetline (&buffer, &buffer_length, out)) |
||||
+ { |
||||
+ for (int i = 0; i < array_length (audit_iface); i++) |
||||
+ if (strncmp (buffer, audit_iface[i].name, |
||||
+ strlen (audit_iface[i].name)) == 0) |
||||
+ audit_iface[i].found = true; |
||||
+ } |
||||
+ free (buffer); |
||||
+ xfclose (out); |
||||
+ |
||||
+ for (int i = 0; i < array_length (audit_iface); i++) |
||||
+ TEST_COMPARE (audit_iface[i].found, true); |
||||
+ |
||||
+ support_capture_subprocess_free (&result); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#define TEST_FUNCTION_ARGV do_test |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-audit18mod.c b/elf/tst-audit18mod.c |
||||
new file mode 100644 |
||||
index 0000000000000000..096a9167c9f8353f |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit18mod.c |
||||
@@ -0,0 +1,23 @@ |
||||
+/* Check DT_AUDIT with dlmopen. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+int |
||||
+foo (void) |
||||
+{ |
||||
+ return 10; |
||||
+} |
||||
diff --git a/elf/tst-auditmod18.c b/elf/tst-auditmod18.c |
||||
new file mode 100644 |
||||
index 0000000000000000..182992e9fdb1620c |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod18.c |
||||
@@ -0,0 +1,73 @@ |
||||
+/* Check DT_AUDIT with dlmopen. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <link.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+char * |
||||
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+ return (char *) name; |
||||
+} |
||||
+ |
||||
+void |
||||
+la_activity (uintptr_t *cookie, unsigned int flag) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objclose (uintptr_t *cookie) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+void |
||||
+la_preinit (uintptr_t *cookie) |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+} |
||||
+ |
||||
+uintptr_t |
||||
+#if __ELF_NATIVE_CLASS == 32 |
||||
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, |
||||
+ uintptr_t *defcook, unsigned int *flags, const char *symname) |
||||
+#else |
||||
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, |
||||
+ uintptr_t *defcook, unsigned int *flags, const char *symname) |
||||
+#endif |
||||
+{ |
||||
+ fprintf (stderr, "%s\n", __func__); |
||||
+ return sym->st_value; |
||||
+} |
@ -0,0 +1,159 @@
@@ -0,0 +1,159 @@
|
||||
commit ce0cb6d1d2daac2d58006a41c3d19c551b86f255 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Mon Jul 19 15:47:51 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_objopen |
||||
|
||||
It consolidates the code required to call la_objopen audit callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit aee6e90f93e285016b6cd9c8bd00402c19ba271b) |
||||
|
||||
Resolved conflicts: |
||||
elf/Makefile |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index bf6da98bdd15a18d..85165c0591412a45 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -118,6 +118,7 @@ elide-routines.os = \ |
||||
# interpreter and operating independent of libc. |
||||
rtld-routines = \ |
||||
$(all-dl-routines) \ |
||||
+ dl-audit \ |
||||
dl-compat \ |
||||
dl-conflict \ |
||||
dl-diagnostics \ |
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
new file mode 100644 |
||||
index 0000000000000000..4066dfe85146b9d4 |
||||
--- /dev/null |
||||
+++ b/elf/dl-audit.c |
||||
@@ -0,0 +1,39 @@ |
||||
+/* Audit common functions. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <ldsodefs.h> |
||||
+ |
||||
+void |
||||
+_dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
+{ |
||||
+ if (__glibc_likely (GLRO(dl_naudit) == 0)) |
||||
+ return; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->objopen != NULL) |
||||
+ { |
||||
+ struct auditstate *state = link_map_audit_state (l, cnt); |
||||
+ state->bindflags = afct->objopen (l, nsid, &state->cookie); |
||||
+ l->l_audit_any_plt |= state->bindflags != 0; |
||||
+ } |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+} |
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index a8c6df3959f2b331..a2d73d025c65cd79 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -1515,22 +1515,8 @@ cannot enable executable stack as shared object requires"); |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we have a new object. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0) |
||||
- && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->objopen != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (l, cnt); |
||||
- state->bindflags = afct->objopen (l, nsid, &state->cookie); |
||||
- l->l_audit_any_plt |= state->bindflags != 0; |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
+ if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) |
||||
+ _dl_audit_objopen (l, nsid); |
||||
#endif |
||||
|
||||
return l; |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index ad5ddb2a0ab94e7f..45fec0df3043b90a 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -1064,25 +1064,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); |
||||
dlmargs.map->l_auditing = 1; |
||||
} |
||||
|
||||
-/* Notify the the audit modules that the object MAP has already been |
||||
- loaded. */ |
||||
-static void |
||||
-notify_audit_modules_of_loaded_object (struct link_map *map) |
||||
-{ |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->objopen != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (map, cnt); |
||||
- state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie); |
||||
- map->l_audit_any_plt |= state->bindflags != 0; |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
-} |
||||
- |
||||
/* Load all audit modules. */ |
||||
static void |
||||
load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) |
||||
@@ -1101,8 +1082,8 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) |
||||
program and the dynamic linker itself). */ |
||||
if (GLRO(dl_naudit) > 0) |
||||
{ |
||||
- notify_audit_modules_of_loaded_object (main_map); |
||||
- notify_audit_modules_of_loaded_object (&GL(dl_rtld_map)); |
||||
+ _dl_audit_objopen (main_map, LM_ID_BASE); |
||||
+ _dl_audit_objopen (&GL(dl_rtld_map), LM_ID_BASE); |
||||
} |
||||
} |
||||
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index bcf1f199c5985c65..5709e4e48dff4355 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1372,6 +1372,11 @@ link_map_audit_state (struct link_map *l, size_t index) |
||||
return &base[index]; |
||||
} |
||||
} |
||||
+ |
||||
+/* Call the la_objopen from the audit modules for the link_map L on the |
||||
+ namespace identification NSID. */ |
||||
+void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
+ attribute_hidden; |
||||
#endif /* SHARED */ |
||||
|
||||
#if PTHREAD_IN_LIBC && defined SHARED |
@ -0,0 +1,254 @@
@@ -0,0 +1,254 @@
|
||||
commit 66e9d27a090874ab93030a908eb86fc29f856151 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Tue Jul 20 11:03:34 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid |
||||
|
||||
It consolidates the code required to call la_activity audit |
||||
callback. |
||||
|
||||
Also for a new Lmid_t the namespace link_map list are empty, so it |
||||
requires to check if before using it. This can happen for when audit |
||||
module is used along with dlmopen. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit 3dac3959a5cb585b065cef2cb8a8d909c907e202) |
||||
|
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 4066dfe85146b9d4..74b87f4b39be75e1 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -18,6 +18,32 @@ |
||||
|
||||
#include <ldsodefs.h> |
||||
|
||||
+void |
||||
+_dl_audit_activity_map (struct link_map *l, int action) |
||||
+{ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->activity != NULL) |
||||
+ afct->activity (&link_map_audit_state (l, cnt)->cookie, action); |
||||
+ afct = afct->next; |
||||
+ } |
||||
+} |
||||
+ |
||||
+void |
||||
+_dl_audit_activity_nsid (Lmid_t nsid, int action) |
||||
+{ |
||||
+ /* If head is NULL, the namespace has become empty, and the audit interface |
||||
+ does not give us a way to signal LA_ACT_CONSISTENT for it because the |
||||
+ first loaded module is used to identify the namespace. */ |
||||
+ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; |
||||
+ if (__glibc_likely (GLRO(dl_naudit) == 0) |
||||
+ || head == NULL || head->l_auditing) |
||||
+ return; |
||||
+ |
||||
+ _dl_audit_activity_map (head, action); |
||||
+} |
||||
+ |
||||
void |
||||
_dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
{ |
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c |
||||
index f6fbf9de7d78555b..5a8cc9e7cb5186cc 100644 |
||||
--- a/elf/dl-close.c |
||||
+++ b/elf/dl-close.c |
||||
@@ -472,25 +472,7 @@ _dl_close_worker (struct link_map *map, bool force) |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we will start deleting objects. */ |
||||
- if (__glibc_unlikely (do_audit)) |
||||
- { |
||||
- struct link_map *head = ns->_ns_loaded; |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- /* Do not call the functions for any auditing object. */ |
||||
- if (head->l_auditing == 0) |
||||
- { |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (head, cnt); |
||||
- afct->activity (&state->cookie, LA_ACT_DELETE); |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
+ _dl_audit_activity_nsid (nsid, LA_ACT_DELETE); |
||||
#endif |
||||
|
||||
/* Notify the debugger we are about to remove some loaded objects. */ |
||||
@@ -785,32 +767,9 @@ _dl_close_worker (struct link_map *map, bool force) |
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); |
||||
|
||||
#ifdef SHARED |
||||
- /* Auditing checkpoint: we have deleted all objects. */ |
||||
- if (__glibc_unlikely (do_audit)) |
||||
- { |
||||
- struct link_map *head = ns->_ns_loaded; |
||||
- /* If head is NULL, the namespace has become empty, and the |
||||
- audit interface does not give us a way to signal |
||||
- LA_ACT_CONSISTENT for it because the first loaded module is |
||||
- used to identify the namespace. |
||||
- |
||||
- Furthermore, do not notify auditors of the cleanup of a |
||||
- failed audit module loading attempt. */ |
||||
- if (head != NULL && head->l_auditing == 0) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (head, cnt); |
||||
- afct->activity (&state->cookie, LA_ACT_CONSISTENT); |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
+ /* Auditing checkpoint: we have deleted all objects. Also, do not notify |
||||
+ auditors of the cleanup of a failed audit module loading attempt. */ |
||||
+ _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT); |
||||
#endif |
||||
|
||||
if (__builtin_expect (ns->_ns_loaded == NULL, 0) |
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index a2d73d025c65cd79..baf0a926053deaed 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -1482,24 +1482,8 @@ cannot enable executable stack as shared object requires"); |
||||
/* Auditing checkpoint: we are going to add new objects. Since this |
||||
is called after _dl_add_to_namespace_list the namespace is guaranteed |
||||
to not be empty. */ |
||||
- if ((mode & __RTLD_AUDIT) == 0 |
||||
- && __glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; |
||||
- /* Do not call the functions for any auditing object. */ |
||||
- if (head->l_auditing == 0) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- afct->activity (&link_map_audit_state (head, cnt)->cookie, |
||||
- LA_ACT_ADD); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
+ if ((mode & __RTLD_AUDIT) == 0) |
||||
+ _dl_audit_activity_nsid (nsid, LA_ACT_ADD); |
||||
#endif |
||||
|
||||
/* Notify the debugger we have added some objects. We need to |
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c |
||||
index bc68e2c376debd71..3f01aa480730da13 100644 |
||||
--- a/elf/dl-open.c |
||||
+++ b/elf/dl-open.c |
||||
@@ -611,25 +611,7 @@ dl_open_worker_begin (void *a) |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we have added all objects. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded; |
||||
- /* Do not call the functions for any auditing object. */ |
||||
- if (head->l_auditing == 0) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (head, cnt); |
||||
- afct->activity (&state->cookie, LA_ACT_CONSISTENT); |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
+ _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT); |
||||
#endif |
||||
|
||||
/* Notify the debugger all new objects are now ready to go. */ |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index 45fec0df3043b90a..b6bb46ca97b7972f 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -1804,18 +1804,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
|
||||
/* Auditing checkpoint: we are ready to signal that the initial map |
||||
is being constructed. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- afct->activity (&link_map_audit_state (main_map, cnt)->cookie, |
||||
- LA_ACT_ADD); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
+ _dl_audit_activity_map (main_map, LA_ACT_ADD); |
||||
|
||||
/* We have two ways to specify objects to preload: via environment |
||||
variable and via the file /etc/ld.so.preload. The latter can also |
||||
@@ -2496,23 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we have added all objects. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded; |
||||
- /* Do not call the functions for any auditing object. */ |
||||
- if (head->l_auditing == 0) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->activity != NULL) |
||||
- afct->activity (&link_map_audit_state (head, cnt)->cookie, |
||||
- LA_ACT_CONSISTENT); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
- } |
||||
+ _dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT); |
||||
#endif |
||||
|
||||
/* Notify the debugger all new objects are now ready to go. We must re-get |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 5709e4e48dff4355..7384abcf5e0e8e24 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1373,6 +1373,16 @@ link_map_audit_state (struct link_map *l, size_t index) |
||||
} |
||||
} |
||||
|
||||
+/* Call the la_activity from the audit modules from the link map L and issues |
||||
+ the ACTION argument. */ |
||||
+void _dl_audit_activity_map (struct link_map *l, int action) |
||||
+ attribute_hidden; |
||||
+ |
||||
+/* Call the la_activity from the audit modules from the link map from the |
||||
+ namespace NSID and issues the ACTION argument. */ |
||||
+void _dl_audit_activity_nsid (Lmid_t nsid, int action) |
||||
+ attribute_hidden; |
||||
+ |
||||
/* Call the la_objopen from the audit modules for the link_map L on the |
||||
namespace identification NSID. */ |
||||
void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
@ -0,0 +1,157 @@
@@ -0,0 +1,157 @@
|
||||
commit ec0fc2a15358dc5f7191f9994f04b1385d14377d |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Tue Jul 20 13:47:36 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_objsearch |
||||
|
||||
It consolidates the code required to call la_objsearch audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit c91008d3490e4e3ce29520068405f081f0d368ca) |
||||
|
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 74b87f4b39be75e1..5682427220569d90 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -44,6 +44,28 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action) |
||||
_dl_audit_activity_map (head, action); |
||||
} |
||||
|
||||
+const char * |
||||
+_dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code) |
||||
+{ |
||||
+ if (l == NULL || l->l_auditing || code == 0) |
||||
+ return name; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->objsearch != NULL) |
||||
+ { |
||||
+ struct auditstate *state = link_map_audit_state (l, cnt); |
||||
+ name = afct->objsearch (name, &state->cookie, code); |
||||
+ if (name == NULL) |
||||
+ return NULL; |
||||
+ } |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ |
||||
+ return name; |
||||
+} |
||||
+ |
||||
void |
||||
_dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
{ |
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c |
||||
index baf0a926053deaed..eb6b658b698f5694 100644 |
||||
--- a/elf/dl-load.c |
||||
+++ b/elf/dl-load.c |
||||
@@ -1596,32 +1596,20 @@ open_verify (const char *name, int fd, |
||||
|
||||
#ifdef SHARED |
||||
/* Give the auditing libraries a chance. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0 |
||||
- && loader->l_auditing == 0) |
||||
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
{ |
||||
const char *original_name = name; |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->objsearch != NULL) |
||||
- { |
||||
- struct auditstate *state = link_map_audit_state (loader, cnt); |
||||
- name = afct->objsearch (name, &state->cookie, whatcode); |
||||
- if (name == NULL) |
||||
- /* Ignore the path. */ |
||||
- return -1; |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
+ name = _dl_audit_objsearch (name, loader, whatcode); |
||||
+ if (name == NULL) |
||||
+ return -1; |
||||
|
||||
if (fd != -1 && name != original_name && strcmp (name, original_name)) |
||||
- { |
||||
- /* An audit library changed what we're supposed to open, |
||||
- so FD no longer matches it. */ |
||||
- __close_nocancel (fd); |
||||
- fd = -1; |
||||
- } |
||||
+ { |
||||
+ /* An audit library changed what we're supposed to open, |
||||
+ so FD no longer matches it. */ |
||||
+ __close_nocancel (fd); |
||||
+ fd = -1; |
||||
+ } |
||||
} |
||||
#endif |
||||
|
||||
@@ -2060,36 +2048,17 @@ _dl_map_object (struct link_map *loader, const char *name, |
||||
#ifdef SHARED |
||||
/* Give the auditing libraries a chance to change the name before we |
||||
try anything. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0) |
||||
- && (loader == NULL || loader->l_auditing == 0)) |
||||
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
{ |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ const char *before = name; |
||||
+ name = _dl_audit_objsearch (name, loader, LA_SER_ORIG); |
||||
+ if (name == NULL) |
||||
{ |
||||
- if (afct->objsearch != NULL) |
||||
- { |
||||
- const char *before = name; |
||||
- struct auditstate *state = link_map_audit_state (loader, cnt); |
||||
- name = afct->objsearch (name, &state->cookie, LA_SER_ORIG); |
||||
- if (name == NULL) |
||||
- { |
||||
- /* Do not try anything further. */ |
||||
- fd = -1; |
||||
- goto no_file; |
||||
- } |
||||
- if (before != name && strcmp (before, name) != 0) |
||||
- { |
||||
- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) |
||||
- _dl_debug_printf ("audit changed filename %s -> %s\n", |
||||
- before, name); |
||||
- |
||||
- if (origname == NULL) |
||||
- origname = before; |
||||
- } |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
+ fd = -1; |
||||
+ goto no_file; |
||||
} |
||||
+ if (before != name && strcmp (before, name) != 0) |
||||
+ origname = before; |
||||
} |
||||
#endif |
||||
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 7384abcf5e0e8e24..1f212a18d7bfc440 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1373,6 +1373,13 @@ link_map_audit_state (struct link_map *l, size_t index) |
||||
} |
||||
} |
||||
|
||||
+/* Call the la_objsearch from the audit modules from the link map L. If |
||||
+ ORIGNAME is non NULL, it is updated with the revious name prior calling |
||||
+ la_objsearch. */ |
||||
+const char *_dl_audit_objsearch (const char *name, struct link_map *l, |
||||
+ unsigned int code) |
||||
+ attribute_hidden; |
||||
+ |
||||
/* Call the la_activity from the audit modules from the link map L and issues |
||||
the ACTION argument. */ |
||||
void _dl_audit_activity_map (struct link_map *l, int action) |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
commit 198660741b23ec9defb19e22951d4a721de603c8 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Tue Jul 20 14:04:51 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_objclose |
||||
|
||||
It consolidates the code required to call la_objclose audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit 311c9ee54ea963ff69bd3a2e6981c37e893b4c3e) |
||||
|
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 5682427220569d90..cb1c3de93cba447b 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -85,3 +85,24 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
afct = afct->next; |
||||
} |
||||
} |
||||
+ |
||||
+void |
||||
+_dl_audit_objclose (struct link_map *l) |
||||
+{ |
||||
+ if (__glibc_likely (GLRO(dl_naudit) == 0) |
||||
+ || GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) |
||||
+ return; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->objclose != NULL) |
||||
+ { |
||||
+ struct auditstate *state= link_map_audit_state (l, cnt); |
||||
+ /* Return value is ignored. */ |
||||
+ afct->objclose (&state->cookie); |
||||
+ } |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+} |
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c |
||||
index 5a8cc9e7cb5186cc..985cd4e2821436af 100644 |
||||
--- a/elf/dl-close.c |
||||
+++ b/elf/dl-close.c |
||||
@@ -260,9 +260,6 @@ _dl_close_worker (struct link_map *map, bool force) |
||||
_dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true); |
||||
|
||||
/* Call all termination functions at once. */ |
||||
-#ifdef SHARED |
||||
- bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing; |
||||
-#endif |
||||
bool unload_any = false; |
||||
bool scope_mem_left = false; |
||||
unsigned int unload_global = 0; |
||||
@@ -296,22 +293,7 @@ _dl_close_worker (struct link_map *map, bool force) |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: we remove an object. */ |
||||
- if (__glibc_unlikely (do_audit)) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->objclose != NULL) |
||||
- { |
||||
- struct auditstate *state |
||||
- = link_map_audit_state (imap, cnt); |
||||
- /* Return value is ignored. */ |
||||
- (void) afct->objclose (&state->cookie); |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
+ _dl_audit_objclose (imap); |
||||
#endif |
||||
|
||||
/* This object must not be used anymore. */ |
||||
diff --git a/elf/dl-fini.c b/elf/dl-fini.c |
||||
index c683884c355dfd52..b789cfb9f2ac6c85 100644 |
||||
--- a/elf/dl-fini.c |
||||
+++ b/elf/dl-fini.c |
||||
@@ -146,21 +146,7 @@ _dl_fini (void) |
||||
|
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: another object closed. */ |
||||
- if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0)) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->objclose != NULL) |
||||
- { |
||||
- struct auditstate *state |
||||
- = link_map_audit_state (l, cnt); |
||||
- /* Return value is ignored. */ |
||||
- (void) afct->objclose (&state->cookie); |
||||
- } |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
+ _dl_audit_objclose (l); |
||||
#endif |
||||
} |
||||
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 1f212a18d7bfc440..982f23c0287955fe 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1394,6 +1394,10 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action) |
||||
namespace identification NSID. */ |
||||
void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
attribute_hidden; |
||||
+ |
||||
+/* Call the la_objclose from the audit modules for the link_map L. */ |
||||
+void _dl_audit_objclose (struct link_map *l) |
||||
+ attribute_hidden; |
||||
#endif /* SHARED */ |
||||
|
||||
#if PTHREAD_IN_LIBC && defined SHARED |
@ -0,0 +1,334 @@
@@ -0,0 +1,334 @@
|
||||
commit b2d99731b6d27c719a30b8ffa931e91c73a6bb4b |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Tue Jul 20 15:58:35 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_symbind_alt and _dl_audit_symbind |
||||
|
||||
It consolidates the code required to call la_symbind{32,64} audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit cda4f265c65fb6c4ce38ca1cf0a7e527c5e77cd5) |
||||
|
||||
diff --git a/elf/Versions b/elf/Versions |
||||
index 2af210b8f771c950..164682eaeaa9a1da 100644 |
||||
--- a/elf/Versions |
||||
+++ b/elf/Versions |
||||
@@ -58,6 +58,7 @@ ld { |
||||
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; |
||||
_dl_deallocate_tls; _dl_make_stack_executable; |
||||
_dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf; |
||||
+ _dl_audit_symbind_alt; |
||||
_rtld_global; _rtld_global_ro; |
||||
|
||||
# Only here for gdb while a better method is developed. |
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index cb1c3de93cba447b..a21530f30bc5524b 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -16,6 +16,7 @@ |
||||
License along with the GNU C Library; if not, see |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
+#include <assert.h> |
||||
#include <ldsodefs.h> |
||||
|
||||
void |
||||
@@ -106,3 +107,124 @@ _dl_audit_objclose (struct link_map *l) |
||||
afct = afct->next; |
||||
} |
||||
} |
||||
+ |
||||
+void |
||||
+_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value, |
||||
+ lookup_t result) |
||||
+{ |
||||
+ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) |
||||
+ return; |
||||
+ |
||||
+ const char *strtab = (const char *) D_PTR (result, l_info[DT_STRTAB]); |
||||
+ /* Compute index of the symbol entry in the symbol table of the DSO with |
||||
+ the definition. */ |
||||
+ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, l_info[DT_SYMTAB])); |
||||
+ |
||||
+ unsigned int altvalue = 0; |
||||
+ /* Synthesize a symbol record where the st_value field is the result. */ |
||||
+ ElfW(Sym) sym = *ref; |
||||
+ sym.st_value = (ElfW(Addr)) *value; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ struct auditstate *match_audit = link_map_audit_state (l, cnt); |
||||
+ struct auditstate *result_audit = link_map_audit_state (result, cnt); |
||||
+ if (afct->symbind != NULL |
||||
+ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 |
||||
+ || ((result_audit->bindflags & LA_FLG_BINDTO) |
||||
+ != 0))) |
||||
+ { |
||||
+ unsigned int flags = altvalue | LA_SYMB_DLSYM; |
||||
+ uintptr_t new_value = afct->symbind (&sym, ndx, |
||||
+ &match_audit->cookie, |
||||
+ &result_audit->cookie, |
||||
+ &flags, strtab + ref->st_name); |
||||
+ if (new_value != (uintptr_t) sym.st_value) |
||||
+ { |
||||
+ altvalue = LA_SYMB_ALTVALUE; |
||||
+ sym.st_value = new_value; |
||||
+ } |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ |
||||
+ *value = (void *) sym.st_value; |
||||
+ } |
||||
+} |
||||
+rtld_hidden_def (_dl_audit_symbind_alt) |
||||
+ |
||||
+void |
||||
+_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
+ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, |
||||
+ lookup_t result) |
||||
+{ |
||||
+ reloc_result->bound = result; |
||||
+ /* Compute index of the symbol entry in the symbol table of the DSO with the |
||||
+ definition. */ |
||||
+ reloc_result->boundndx = (defsym - (ElfW(Sym) *) D_PTR (result, |
||||
+ l_info[DT_SYMTAB])); |
||||
+ |
||||
+ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) |
||||
+ { |
||||
+ /* Set all bits since this symbol binding is not interesting. */ |
||||
+ reloc_result->enterexit = (1u << DL_NNS) - 1; |
||||
+ return; |
||||
+ } |
||||
+ |
||||
+ /* Synthesize a symbol record where the st_value field is the result. */ |
||||
+ ElfW(Sym) sym = *defsym; |
||||
+ sym.st_value = DL_FIXUP_VALUE_ADDR (*value); |
||||
+ |
||||
+ /* Keep track whether there is any interest in tracing the call in the lower |
||||
+ two bits. */ |
||||
+ assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); |
||||
+ assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); |
||||
+ reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; |
||||
+ |
||||
+ const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]); |
||||
+ |
||||
+ unsigned int flags = 0; |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ /* XXX Check whether both DSOs must request action or only one */ |
||||
+ struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
+ struct auditstate *result_state = link_map_audit_state (result, cnt); |
||||
+ if ((l_state->bindflags & LA_FLG_BINDFROM) != 0 |
||||
+ && (result_state->bindflags & LA_FLG_BINDTO) != 0) |
||||
+ { |
||||
+ if (afct->symbind != NULL) |
||||
+ { |
||||
+ uintptr_t new_value = afct->symbind (&sym, |
||||
+ reloc_result->boundndx, |
||||
+ &l_state->cookie, |
||||
+ &result_state->cookie, |
||||
+ &flags, |
||||
+ strtab2 + defsym->st_name); |
||||
+ if (new_value != (uintptr_t) sym.st_value) |
||||
+ { |
||||
+ flags |= LA_SYMB_ALTVALUE; |
||||
+ sym.st_value = new_value; |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ /* Remember the results for every audit library and store a summary |
||||
+ in the first two bits. */ |
||||
+ reloc_result->enterexit &= flags & (LA_SYMB_NOPLTENTER |
||||
+ | LA_SYMB_NOPLTEXIT); |
||||
+ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER |
||||
+ | LA_SYMB_NOPLTEXIT)) |
||||
+ << ((cnt + 1) * 2)); |
||||
+ } |
||||
+ else |
||||
+ /* If the bind flags say this auditor is not interested, set the bits |
||||
+ manually. */ |
||||
+ reloc_result->enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) |
||||
+ << ((cnt + 1) * 2)); |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ |
||||
+ reloc_result->flags = flags; |
||||
+ *value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
+} |
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c |
||||
index 61c260ddb81b586c..c4413c9165cec8cb 100644 |
||||
--- a/elf/dl-runtime.c |
||||
+++ b/elf/dl-runtime.c |
||||
@@ -297,84 +297,7 @@ _dl_profile_fixup ( |
||||
auditing libraries the possibility to change the value and |
||||
tell us whether further auditing is wanted. */ |
||||
if (defsym != NULL && GLRO(dl_naudit) > 0) |
||||
- { |
||||
- reloc_result->bound = result; |
||||
- /* Compute index of the symbol entry in the symbol table of |
||||
- the DSO with the definition. */ |
||||
- reloc_result->boundndx = (defsym |
||||
- - (ElfW(Sym) *) D_PTR (result, |
||||
- l_info[DT_SYMTAB])); |
||||
- |
||||
- /* Determine whether any of the two participating DSOs is |
||||
- interested in auditing. */ |
||||
- if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0) |
||||
- { |
||||
- unsigned int flags = 0; |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- /* Synthesize a symbol record where the st_value field is |
||||
- the result. */ |
||||
- ElfW(Sym) sym = *defsym; |
||||
- sym.st_value = DL_FIXUP_VALUE_ADDR (value); |
||||
- |
||||
- /* Keep track whether there is any interest in tracing |
||||
- the call in the lower two bits. */ |
||||
- assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); |
||||
- assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); |
||||
- reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; |
||||
- |
||||
- const char *strtab2 = (const void *) D_PTR (result, |
||||
- l_info[DT_STRTAB]); |
||||
- |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- /* XXX Check whether both DSOs must request action or |
||||
- only one */ |
||||
- struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
- struct auditstate *result_state |
||||
- = link_map_audit_state (result, cnt); |
||||
- if ((l_state->bindflags & LA_FLG_BINDFROM) != 0 |
||||
- && (result_state->bindflags & LA_FLG_BINDTO) != 0) |
||||
- { |
||||
- if (afct->symbind != NULL) |
||||
- { |
||||
- uintptr_t new_value |
||||
- = afct->symbind (&sym, reloc_result->boundndx, |
||||
- &l_state->cookie, |
||||
- &result_state->cookie, |
||||
- &flags, |
||||
- strtab2 + defsym->st_name); |
||||
- if (new_value != (uintptr_t) sym.st_value) |
||||
- { |
||||
- flags |= LA_SYMB_ALTVALUE; |
||||
- sym.st_value = new_value; |
||||
- } |
||||
- } |
||||
- |
||||
- /* Remember the results for every audit library and |
||||
- store a summary in the first two bits. */ |
||||
- reloc_result->enterexit |
||||
- &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); |
||||
- reloc_result->enterexit |
||||
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) |
||||
- << ((cnt + 1) * 2)); |
||||
- } |
||||
- else |
||||
- /* If the bind flags say this auditor is not interested, |
||||
- set the bits manually. */ |
||||
- reloc_result->enterexit |
||||
- |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) |
||||
- << ((cnt + 1) * 2)); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- |
||||
- reloc_result->flags = flags; |
||||
- value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
- } |
||||
- else |
||||
- /* Set all bits since this symbol binding is not interesting. */ |
||||
- reloc_result->enterexit = (1u << DL_NNS) - 1; |
||||
- } |
||||
+ _dl_audit_symbind (l, reloc_result, defsym, &value, result); |
||||
#endif |
||||
|
||||
/* Store the result for later runs. */ |
||||
diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h |
||||
index d68c2d2b1cd43c9b..a11095d3e8c3c937 100644 |
||||
--- a/elf/dl-sym-post.h |
||||
+++ b/elf/dl-sym-post.h |
||||
@@ -52,54 +52,9 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value, |
||||
tell us whether further auditing is wanted. */ |
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
{ |
||||
- const char *strtab = (const char *) D_PTR (result, |
||||
- l_info[DT_STRTAB]); |
||||
- /* Compute index of the symbol entry in the symbol table of |
||||
- the DSO with the definition. */ |
||||
- unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, |
||||
- l_info[DT_SYMTAB])); |
||||
- |
||||
if (match == NULL) |
||||
match = _dl_sym_find_caller_link_map (caller); |
||||
- |
||||
- if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) |
||||
- { |
||||
- unsigned int altvalue = 0; |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- /* Synthesize a symbol record where the st_value field is |
||||
- the result. */ |
||||
- ElfW(Sym) sym = *ref; |
||||
- sym.st_value = (ElfW(Addr)) value; |
||||
- |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- struct auditstate *match_audit |
||||
- = link_map_audit_state (match, cnt); |
||||
- struct auditstate *result_audit |
||||
- = link_map_audit_state (result, cnt); |
||||
- if (afct->symbind != NULL |
||||
- && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 |
||||
- || ((result_audit->bindflags & LA_FLG_BINDTO) |
||||
- != 0))) |
||||
- { |
||||
- unsigned int flags = altvalue | LA_SYMB_DLSYM; |
||||
- uintptr_t new_value |
||||
- = afct->symbind (&sym, ndx, |
||||
- &match_audit->cookie, |
||||
- &result_audit->cookie, |
||||
- &flags, strtab + ref->st_name); |
||||
- if (new_value != (uintptr_t) sym.st_value) |
||||
- { |
||||
- altvalue = LA_SYMB_ALTVALUE; |
||||
- sym.st_value = new_value; |
||||
- } |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- |
||||
- value = (void *) sym.st_value; |
||||
- } |
||||
+ _dl_audit_symbind_alt (match, ref, &value, result); |
||||
} |
||||
#endif |
||||
return value; |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 982f23c0287955fe..61f1dfb3f79a613a 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1398,6 +1398,16 @@ void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
/* Call the la_objclose from the audit modules for the link_map L. */ |
||||
void _dl_audit_objclose (struct link_map *l) |
||||
attribute_hidden; |
||||
+ |
||||
+/* Call the la_symbind{32,64} from the audit modules for the link_map L. */ |
||||
+void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
+ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, |
||||
+ lookup_t result) |
||||
+ attribute_hidden; |
||||
+/* Same as _dl_audit_symbind, but also sets LA_SYMB_DLSYM flag. */ |
||||
+void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, |
||||
+ void **value, lookup_t result); |
||||
+rtld_hidden_proto (_dl_audit_symbind_alt) |
||||
#endif /* SHARED */ |
||||
|
||||
#if PTHREAD_IN_LIBC && defined SHARED |
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
commit 31473c273be14270f8eef68e35c03fd2305eb2c3 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Jul 22 17:10:57 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_preinit |
||||
|
||||
It consolidates the code required to call la_preinit audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit 0b98a8748759e88b58927882a8714109abe0a2d6) |
||||
|
||||
diff --git a/csu/libc-start.c b/csu/libc-start.c |
||||
index 0350b006fdcc22d2..d01e57ea59ceb880 100644 |
||||
--- a/csu/libc-start.c |
||||
+++ b/csu/libc-start.c |
||||
@@ -377,32 +377,15 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), |
||||
/* This is a current program. Use the dynamic segment to find |
||||
constructors. */ |
||||
call_init (argc, argv, __environ); |
||||
-#else /* !SHARED */ |
||||
- call_init (argc, argv, __environ); |
||||
-#endif /* SHARED */ |
||||
|
||||
-#ifdef SHARED |
||||
/* Auditing checkpoint: we have a new object. */ |
||||
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) |
||||
- { |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded; |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->preinit != NULL) |
||||
- afct->preinit (&link_map_audit_state (head, cnt)->cookie); |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- } |
||||
-#endif |
||||
+ _dl_audit_preinit (GL(dl_ns)[LM_ID_BASE]._ns_loaded); |
||||
|
||||
-#ifdef SHARED |
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) |
||||
GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); |
||||
-#endif |
||||
+#else /* !SHARED */ |
||||
+ call_init (argc, argv, __environ); |
||||
|
||||
-#ifndef SHARED |
||||
_dl_debug_initialize (0, LM_ID_BASE); |
||||
#endif |
||||
|
||||
diff --git a/elf/Versions b/elf/Versions |
||||
index 164682eaeaa9a1da..bb6697647b397772 100644 |
||||
--- a/elf/Versions |
||||
+++ b/elf/Versions |
||||
@@ -58,7 +58,7 @@ ld { |
||||
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; |
||||
_dl_deallocate_tls; _dl_make_stack_executable; |
||||
_dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf; |
||||
- _dl_audit_symbind_alt; |
||||
+ _dl_audit_symbind_alt; _dl_audit_preinit; |
||||
_rtld_global; _rtld_global_ro; |
||||
|
||||
# Only here for gdb while a better method is developed. |
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index a21530f30bc5524b..0b6fac8e48877c93 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -108,6 +108,21 @@ _dl_audit_objclose (struct link_map *l) |
||||
} |
||||
} |
||||
|
||||
+void |
||||
+_dl_audit_preinit (struct link_map *l) |
||||
+{ |
||||
+ if (__glibc_likely (GLRO(dl_naudit) == 0)) |
||||
+ return; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->preinit != NULL) |
||||
+ afct->preinit (&link_map_audit_state (l, cnt)->cookie); |
||||
+ afct = afct->next; |
||||
+ } |
||||
+} |
||||
+ |
||||
void |
||||
_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value, |
||||
lookup_t result) |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 61f1dfb3f79a613a..91193a036fc5c6ef 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1399,6 +1399,9 @@ void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) |
||||
void _dl_audit_objclose (struct link_map *l) |
||||
attribute_hidden; |
||||
|
||||
+/* Call the la_preinit from the audit modules for the link_map L. */ |
||||
+void _dl_audit_preinit (struct link_map *l); |
||||
+ |
||||
/* Call the la_symbind{32,64} from the audit modules for the link_map L. */ |
||||
void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, |
@ -0,0 +1,206 @@
@@ -0,0 +1,206 @@
|
||||
commit fd9c4e8a1b72fa1372855051217f9480680d882a |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Jul 22 17:45:33 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_pltenter |
||||
|
||||
It consolidates the code required to call la_pltenter audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit eff687e8462b0eaf65992a6031b54a4b1cd16796) |
||||
|
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 0b6fac8e48877c93..15250c67e8ac1658 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -17,7 +17,9 @@ |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
#include <assert.h> |
||||
+#include <link.h> |
||||
#include <ldsodefs.h> |
||||
+#include <dl-machine.h> |
||||
|
||||
void |
||||
_dl_audit_activity_map (struct link_map *l, int action) |
||||
@@ -243,3 +245,78 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
reloc_result->flags = flags; |
||||
*value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
} |
||||
+ |
||||
+void |
||||
+_dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, |
||||
+ DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize) |
||||
+{ |
||||
+ /* Don't do anything if no auditor wants to intercept this call. */ |
||||
+ if (GLRO(dl_naudit) == 0 |
||||
+ || (reloc_result->enterexit & LA_SYMB_NOPLTENTER)) |
||||
+ return; |
||||
+ |
||||
+ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been |
||||
+ initialized earlier in this function or in another thread. */ |
||||
+ assert (DL_FIXUP_VALUE_CODE_ADDR (*value) != 0); |
||||
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, |
||||
+ l_info[DT_SYMTAB]) |
||||
+ + reloc_result->boundndx); |
||||
+ |
||||
+ /* Set up the sym parameter. */ |
||||
+ ElfW(Sym) sym = *defsym; |
||||
+ sym.st_value = DL_FIXUP_VALUE_ADDR (*value); |
||||
+ |
||||
+ /* Get the symbol name. */ |
||||
+ const char *strtab = (const void *) D_PTR (reloc_result->bound, |
||||
+ l_info[DT_STRTAB]); |
||||
+ const char *symname = strtab + sym.st_name; |
||||
+ |
||||
+ /* Keep track of overwritten addresses. */ |
||||
+ unsigned int flags = reloc_result->flags; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->ARCH_LA_PLTENTER != NULL |
||||
+ && (reloc_result->enterexit |
||||
+ & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) |
||||
+ { |
||||
+ long int new_framesize = -1; |
||||
+ struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
+ struct auditstate *bound_state |
||||
+ = link_map_audit_state (reloc_result->bound, cnt); |
||||
+ uintptr_t new_value |
||||
+ = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, |
||||
+ &l_state->cookie, &bound_state->cookie, |
||||
+ regs, &flags, symname, &new_framesize); |
||||
+ if (new_value != (uintptr_t) sym.st_value) |
||||
+ { |
||||
+ flags |= LA_SYMB_ALTVALUE; |
||||
+ sym.st_value = new_value; |
||||
+ } |
||||
+ |
||||
+ /* Remember the results for every audit library and store a summary |
||||
+ in the first two bits. */ |
||||
+ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER |
||||
+ | LA_SYMB_NOPLTEXIT)) |
||||
+ << (2 * (cnt + 1))); |
||||
+ |
||||
+ if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT |
||||
+ << (2 * (cnt + 1)))) |
||||
+ == 0 && new_framesize != -1 && *framesize != -2) |
||||
+ { |
||||
+ /* If this is the first call providing information, use it. */ |
||||
+ if (*framesize == -1) |
||||
+ *framesize = new_framesize; |
||||
+ /* If two pltenter calls provide conflicting information, use |
||||
+ the larger value. */ |
||||
+ else if (new_framesize != *framesize) |
||||
+ *framesize = MAX (new_framesize, *framesize); |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ |
||||
+ *value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
+} |
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c |
||||
index c4413c9165cec8cb..dfedeaf2dd1c7253 100644 |
||||
--- a/elf/dl-runtime.c |
||||
+++ b/elf/dl-runtime.c |
||||
@@ -320,78 +320,7 @@ _dl_profile_fixup ( |
||||
#ifdef SHARED |
||||
/* Auditing checkpoint: report the PLT entering and allow the |
||||
auditors to change the value. */ |
||||
- if (GLRO(dl_naudit) > 0 |
||||
- /* Don't do anything if no auditor wants to intercept this call. */ |
||||
- && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) |
||||
- { |
||||
- /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been |
||||
- initialized earlier in this function or in another thread. */ |
||||
- assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); |
||||
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, |
||||
- l_info[DT_SYMTAB]) |
||||
- + reloc_result->boundndx); |
||||
- |
||||
- /* Set up the sym parameter. */ |
||||
- ElfW(Sym) sym = *defsym; |
||||
- sym.st_value = DL_FIXUP_VALUE_ADDR (value); |
||||
- |
||||
- /* Get the symbol name. */ |
||||
- const char *strtab = (const void *) D_PTR (reloc_result->bound, |
||||
- l_info[DT_STRTAB]); |
||||
- const char *symname = strtab + sym.st_name; |
||||
- |
||||
- /* Keep track of overwritten addresses. */ |
||||
- unsigned int flags = reloc_result->flags; |
||||
- |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->ARCH_LA_PLTENTER != NULL |
||||
- && (reloc_result->enterexit |
||||
- & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) |
||||
- { |
||||
- long int new_framesize = -1; |
||||
- struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
- struct auditstate *bound_state |
||||
- = link_map_audit_state (reloc_result->bound, cnt); |
||||
- uintptr_t new_value |
||||
- = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, |
||||
- &l_state->cookie, |
||||
- &bound_state->cookie, |
||||
- regs, &flags, symname, |
||||
- &new_framesize); |
||||
- if (new_value != (uintptr_t) sym.st_value) |
||||
- { |
||||
- flags |= LA_SYMB_ALTVALUE; |
||||
- sym.st_value = new_value; |
||||
- } |
||||
- |
||||
- /* Remember the results for every audit library and |
||||
- store a summary in the first two bits. */ |
||||
- reloc_result->enterexit |
||||
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) |
||||
- << (2 * (cnt + 1))); |
||||
- |
||||
- if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT |
||||
- << (2 * (cnt + 1)))) |
||||
- == 0 && new_framesize != -1 && framesize != -2) |
||||
- { |
||||
- /* If this is the first call providing information, |
||||
- use it. */ |
||||
- if (framesize == -1) |
||||
- framesize = new_framesize; |
||||
- /* If two pltenter calls provide conflicting information, |
||||
- use the larger value. */ |
||||
- else if (new_framesize != framesize) |
||||
- framesize = MAX (new_framesize, framesize); |
||||
- } |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
- |
||||
- value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
- } |
||||
+ _dl_audit_pltenter (l, reloc_result, &value, regs, &framesize); |
||||
#endif |
||||
|
||||
/* Store the frame size information. */ |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 91193a036fc5c6ef..ea187dd266f14e06 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1411,6 +1411,10 @@ void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, |
||||
void **value, lookup_t result); |
||||
rtld_hidden_proto (_dl_audit_symbind_alt) |
||||
+void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, |
||||
+ DL_FIXUP_VALUE_TYPE *value, void *regs, |
||||
+ long int *framesize) |
||||
+ attribute_hidden; |
||||
#endif /* SHARED */ |
||||
|
||||
#if PTHREAD_IN_LIBC && defined SHARED |
@ -0,0 +1,715 @@
@@ -0,0 +1,715 @@
|
||||
commit a8e211daea6bdb505b10319ed3492e7d871c1e75 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Jul 22 18:02:42 2021 -0300 |
||||
|
||||
elf: Add _dl_audit_pltexit |
||||
|
||||
It consolidates the code required to call la_pltexit audit |
||||
callback. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit 8c0664e2b861fd3789602cc0b0b1922b0e20cb3a) |
||||
|
||||
Resolved conflicts: |
||||
sysdeps/hppa/dl-runtime.c |
||||
|
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 15250c67e8ac1658..152712b12fed6de2 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -20,6 +20,8 @@ |
||||
#include <link.h> |
||||
#include <ldsodefs.h> |
||||
#include <dl-machine.h> |
||||
+#include <dl-runtime.h> |
||||
+#include <dl-fixup-attribute.h> |
||||
|
||||
void |
||||
_dl_audit_activity_map (struct link_map *l, int action) |
||||
@@ -320,3 +322,48 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, |
||||
|
||||
*value = DL_FIXUP_ADDR_VALUE (sym.st_value); |
||||
} |
||||
+ |
||||
+void |
||||
+DL_ARCH_FIXUP_ATTRIBUTE |
||||
+_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg, |
||||
+ const void *inregs, void *outregs) |
||||
+{ |
||||
+ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); |
||||
+ |
||||
+ /* This is the address in the array where we store the result of previous |
||||
+ relocations. */ |
||||
+ // XXX Maybe the bound information must be stored on the stack since |
||||
+ // XXX with bind_not a new value could have been stored in the meantime. |
||||
+ struct reloc_result *reloc_result = |
||||
+ &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; |
||||
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, |
||||
+ l_info[DT_SYMTAB]) |
||||
+ + reloc_result->boundndx); |
||||
+ |
||||
+ /* Set up the sym parameter. */ |
||||
+ ElfW(Sym) sym = *defsym; |
||||
+ sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr); |
||||
+ |
||||
+ /* Get the symbol name. */ |
||||
+ const char *strtab = (const void *) D_PTR (reloc_result->bound, |
||||
+ l_info[DT_STRTAB]); |
||||
+ const char *symname = strtab + sym.st_name; |
||||
+ |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ if (afct->ARCH_LA_PLTEXIT != NULL |
||||
+ && (reloc_result->enterexit |
||||
+ & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) |
||||
+ { |
||||
+ struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
+ struct auditstate *bound_state |
||||
+ = link_map_audit_state (reloc_result->bound, cnt); |
||||
+ afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, |
||||
+ &l_state->cookie, &bound_state->cookie, |
||||
+ inregs, outregs, symname); |
||||
+ } |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+} |
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c |
||||
index dfedeaf2dd1c7253..e42f6e8b8dfca08e 100644 |
||||
--- a/elf/dl-runtime.c |
||||
+++ b/elf/dl-runtime.c |
||||
@@ -16,8 +16,6 @@ |
||||
License along with the GNU C Library; if not, see |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
-#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */ |
||||
- |
||||
#include <alloca.h> |
||||
#include <assert.h> |
||||
#include <stdlib.h> |
||||
@@ -31,19 +29,6 @@ |
||||
#include <dl-runtime.h> |
||||
|
||||
|
||||
-#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ |
||||
- || ELF_MACHINE_NO_REL |
||||
-# define PLTREL ElfW(Rela) |
||||
-#else |
||||
-# define PLTREL ElfW(Rel) |
||||
-#endif |
||||
- |
||||
-/* The fixup functions might have need special attributes. If none |
||||
- are provided define the macro as empty. */ |
||||
-#ifndef ARCH_FIXUP_ATTRIBUTE |
||||
-# define ARCH_FIXUP_ATTRIBUTE |
||||
-#endif |
||||
- |
||||
/* This function is called through a special trampoline from the PLT the |
||||
first time each PLT entry is called. We must perform the relocation |
||||
specified in the PLT of the given shared object, and return the resolved |
||||
@@ -52,7 +37,7 @@ |
||||
function. */ |
||||
|
||||
DL_FIXUP_VALUE_TYPE |
||||
-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE |
||||
+attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE |
||||
_dl_fixup ( |
||||
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS |
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS, |
||||
@@ -148,7 +133,8 @@ _dl_fixup ( |
||||
|
||||
#ifndef PROF |
||||
DL_FIXUP_VALUE_TYPE |
||||
-__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE |
||||
+__attribute ((noinline)) |
||||
+DL_ARCH_FIXUP_ATTRIBUTE |
||||
_dl_profile_fixup ( |
||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS |
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS, |
||||
@@ -332,52 +318,3 @@ _dl_profile_fixup ( |
||||
} |
||||
|
||||
#endif /* PROF */ |
||||
- |
||||
- |
||||
-#include <stdio.h> |
||||
-void |
||||
-ARCH_FIXUP_ATTRIBUTE |
||||
-_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, |
||||
- const void *inregs, void *outregs) |
||||
-{ |
||||
-#ifdef SHARED |
||||
- const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); |
||||
- |
||||
- /* This is the address in the array where we store the result of previous |
||||
- relocations. */ |
||||
- // XXX Maybe the bound information must be stored on the stack since |
||||
- // XXX with bind_not a new value could have been stored in the meantime. |
||||
- struct reloc_result *reloc_result = |
||||
- &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; |
||||
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, |
||||
- l_info[DT_SYMTAB]) |
||||
- + reloc_result->boundndx); |
||||
- |
||||
- /* Set up the sym parameter. */ |
||||
- ElfW(Sym) sym = *defsym; |
||||
- sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr); |
||||
- |
||||
- /* Get the symbol name. */ |
||||
- const char *strtab = (const void *) D_PTR (reloc_result->bound, |
||||
- l_info[DT_STRTAB]); |
||||
- const char *symname = strtab + sym.st_name; |
||||
- |
||||
- struct audit_ifaces *afct = GLRO(dl_audit); |
||||
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
- { |
||||
- if (afct->ARCH_LA_PLTEXIT != NULL |
||||
- && (reloc_result->enterexit |
||||
- & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) |
||||
- { |
||||
- struct auditstate *l_state = link_map_audit_state (l, cnt); |
||||
- struct auditstate *bound_state |
||||
- = link_map_audit_state (reloc_result->bound, cnt); |
||||
- afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, |
||||
- &l_state->cookie, &bound_state->cookie, |
||||
- inregs, outregs, symname); |
||||
- } |
||||
- |
||||
- afct = afct->next; |
||||
- } |
||||
-#endif |
||||
-} |
||||
diff --git a/elf/dl-support.c b/elf/dl-support.c |
||||
index c5ee5d33aa7e1d65..f29dc965f4d10648 100644 |
||||
--- a/elf/dl-support.c |
||||
+++ b/elf/dl-support.c |
||||
@@ -437,3 +437,11 @@ _dl_get_dl_main_map (void) |
||||
return &_dl_main_map; |
||||
} |
||||
#endif |
||||
+ |
||||
+/* This is used by _dl_runtime_profile, not used on static code. */ |
||||
+void |
||||
+DL_ARCH_FIXUP_ATTRIBUTE |
||||
+_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg, |
||||
+ const void *inregs, void *outregs) |
||||
+{ |
||||
+} |
||||
diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S |
||||
index a7e9267c1c6a4863..9b352b1d0f7d62e7 100644 |
||||
--- a/sysdeps/aarch64/dl-trampoline.S |
||||
+++ b/sysdeps/aarch64/dl-trampoline.S |
||||
@@ -293,7 +293,7 @@ _dl_runtime_profile: |
||||
ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] |
||||
add x2, x29, #OFFSET_RG |
||||
add x3, x29, #OFFSET_RV |
||||
- bl _dl_call_pltexit |
||||
+ bl _dl_audit_pltexit |
||||
|
||||
ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] |
||||
ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] |
||||
diff --git a/sysdeps/alpha/dl-trampoline.S b/sysdeps/alpha/dl-trampoline.S |
||||
index 9dfce5b0839dc122..55380d48ad8536ee 100644 |
||||
--- a/sysdeps/alpha/dl-trampoline.S |
||||
+++ b/sysdeps/alpha/dl-trampoline.S |
||||
@@ -187,7 +187,7 @@ _dl_runtime_profile_new: |
||||
jsr $26, ($27), 0 |
||||
ldgp $29, 0($26) |
||||
|
||||
- /* Set up for call to _dl_call_pltexit. */ |
||||
+ /* Set up for call to _dl_audit_pltexit. */ |
||||
ldq $16, 16*8($15) |
||||
ldq $17, 17*8($15) |
||||
stq $0, 16*8($15) |
||||
@@ -196,7 +196,7 @@ _dl_runtime_profile_new: |
||||
lda $19, 16*8($15) |
||||
stt $f0, 18*8($15) |
||||
stt $f1, 19*8($15) |
||||
- bsr $26, _dl_call_pltexit !samegp |
||||
+ bsr $26, _dl_audit_pltexit !samegp |
||||
|
||||
mov $15, $30 |
||||
cfi_def_cfa_register (30) |
||||
@@ -518,7 +518,7 @@ _dl_runtime_profile_old: |
||||
jsr $26, ($27), 0 |
||||
ldgp $29, 0($26) |
||||
|
||||
- /* Set up for call to _dl_call_pltexit. */ |
||||
+ /* Set up for call to _dl_audit_pltexit. */ |
||||
ldq $16, 48*8($15) |
||||
ldq $17, 49*8($15) |
||||
stq $0, 46*8($15) |
||||
@@ -527,7 +527,7 @@ _dl_runtime_profile_old: |
||||
lda $19, 46*8($15) |
||||
stt $f0, 48*8($15) |
||||
stt $f1, 49*8($15) |
||||
- bsr $26, _dl_call_pltexit !samegp |
||||
+ bsr $26, _dl_audit_pltexit !samegp |
||||
|
||||
mov $15, $30 |
||||
cfi_def_cfa_register (30) |
||||
diff --git a/sysdeps/arm/dl-machine-rel.h b/sysdeps/arm/dl-machine-rel.h |
||||
index bec114706cd027a4..a9ee25a6b1d381ac 100644 |
||||
--- a/sysdeps/arm/dl-machine-rel.h |
||||
+++ b/sysdeps/arm/dl-machine-rel.h |
||||
@@ -28,4 +28,6 @@ |
||||
Prelinked libraries may use Elf32_Rela though. */ |
||||
#define ELF_MACHINE_PLT_REL 1 |
||||
|
||||
+#define PLTREL ElfW(Rel) |
||||
+ |
||||
#endif |
||||
diff --git a/sysdeps/arm/dl-trampoline.S b/sysdeps/arm/dl-trampoline.S |
||||
index 70105308ca7df934..a2d322706db77981 100644 |
||||
--- a/sysdeps/arm/dl-trampoline.S |
||||
+++ b/sysdeps/arm/dl-trampoline.S |
||||
@@ -194,7 +194,7 @@ _dl_runtime_profile: |
||||
ldmia ip, {r0,r1} |
||||
add r2, r7, #72 |
||||
add r3, r7, #0 |
||||
- bl _dl_call_pltexit |
||||
+ bl _dl_audit_pltexit |
||||
|
||||
@ Return to caller. |
||||
ldmia r7, {r0-r3} |
||||
diff --git a/sysdeps/generic/dl-fixup-attribute.h b/sysdeps/generic/dl-fixup-attribute.h |
||||
new file mode 100644 |
||||
index 0000000000000000..aa92169b709b3fea |
||||
--- /dev/null |
||||
+++ b/sysdeps/generic/dl-fixup-attribute.h |
||||
@@ -0,0 +1,24 @@ |
||||
+/* ABI specifics for lazy resolution functions. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef _DL_FIXUP_ATTRIBUTE_H |
||||
+#define _DL_FIXUP_ATTRIBUTE_H |
||||
+ |
||||
+#define DL_ARCH_FIXUP_ATTRIBUTE |
||||
+ |
||||
+#endif |
||||
diff --git a/sysdeps/generic/dl-machine-rel.h b/sysdeps/generic/dl-machine-rel.h |
||||
index 9167a1dffc715704..9d5b7bb749e69e63 100644 |
||||
--- a/sysdeps/generic/dl-machine-rel.h |
||||
+++ b/sysdeps/generic/dl-machine-rel.h |
||||
@@ -23,5 +23,7 @@ |
||||
#define ELF_MACHINE_NO_REL 1 |
||||
/* Defined if the architecture supports Elf{32,64}_Rela relocations. */ |
||||
#define ELF_MACHINE_NO_RELA 0 |
||||
+/* Used to calculate the index of link_map l_reloc_result. */ |
||||
+#define PLTREL ElfW(Rela) |
||||
|
||||
#endif |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index ea187dd266f14e06..686f0a7b9709eb10 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -35,6 +35,7 @@ |
||||
#include <link.h> |
||||
#include <dl-lookupcfg.h> |
||||
#include <dl-sysdep.h> |
||||
+#include <dl-fixup-attribute.h> |
||||
#include <libc-lock.h> |
||||
#include <hp-timing.h> |
||||
#include <tls.h> |
||||
@@ -1415,6 +1416,11 @@ void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, |
||||
DL_FIXUP_VALUE_TYPE *value, void *regs, |
||||
long int *framesize) |
||||
attribute_hidden; |
||||
+void DL_ARCH_FIXUP_ATTRIBUTE _dl_audit_pltexit (struct link_map *l, |
||||
+ ElfW(Word) reloc_arg, |
||||
+ const void *inregs, |
||||
+ void *outregs) |
||||
+ attribute_hidden; |
||||
#endif /* SHARED */ |
||||
|
||||
#if PTHREAD_IN_LIBC && defined SHARED |
||||
diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c |
||||
index a71b5b2013abf723..8699171930f51489 100644 |
||||
--- a/sysdeps/hppa/dl-runtime.c |
||||
+++ b/sysdeps/hppa/dl-runtime.c |
||||
@@ -25,7 +25,7 @@ |
||||
return that to the caller. The caller will continue on to call |
||||
_dl_fixup with the relocation offset. */ |
||||
|
||||
-ElfW(Word) __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE |
||||
+ElfW(Word) __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE |
||||
_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) |
||||
{ |
||||
Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type; |
||||
diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S |
||||
index cb18ea7eabba41ed..c54879bae0148012 100644 |
||||
--- a/sysdeps/hppa/dl-trampoline.S |
||||
+++ b/sysdeps/hppa/dl-trampoline.S |
||||
@@ -300,7 +300,7 @@ L(cont): |
||||
ldw -4(%sp),%r1 |
||||
copy %r1, %sp |
||||
|
||||
- /* Arguments to _dl_call_pltexit */ |
||||
+ /* Arguments to _dl_audit_pltexit */ |
||||
ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ |
||||
ldw -120(%sp), %r25 /* (2) reloc offsets */ |
||||
ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ |
||||
@@ -312,8 +312,8 @@ L(cont): |
||||
ldo -128(%sp), %r1 |
||||
fstd %fr4,0(%r1) |
||||
|
||||
- /* Call _dl_call_pltexit */ |
||||
- bl _dl_call_pltexit,%rp |
||||
+ /* Call _dl_audit_pltexit */ |
||||
+ bl _dl_audit_pltexit,%rp |
||||
nop |
||||
|
||||
/* Restore *La_hppa_retval */ |
||||
diff --git a/sysdeps/i386/dl-fixup-attribute.h b/sysdeps/i386/dl-fixup-attribute.h |
||||
new file mode 100644 |
||||
index 0000000000000000..c10e9936f4db7254 |
||||
--- /dev/null |
||||
+++ b/sysdeps/i386/dl-fixup-attribute.h |
||||
@@ -0,0 +1,30 @@ |
||||
+/* ABI specifics for lazy resolution functions. i386 version. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef _DL_FIXUP_ATTRIBUTE_H |
||||
+#define _DL_FIXUP_ATTRIBUTE_H |
||||
+ |
||||
+/* We cannot use this scheme for profiling because the _mcount call destroys |
||||
+ the passed register information. */ |
||||
+#ifndef PROF |
||||
+# define DL_ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused)) |
||||
+#else |
||||
+# define DL_ARCH_FIXUP_ATTRIBUTE |
||||
+#endif |
||||
+ |
||||
+#endif |
||||
diff --git a/sysdeps/i386/dl-machine-rel.h b/sysdeps/i386/dl-machine-rel.h |
||||
index 7ac46f78a69fbf98..bb3480d45415d761 100644 |
||||
--- a/sysdeps/i386/dl-machine-rel.h |
||||
+++ b/sysdeps/i386/dl-machine-rel.h |
||||
@@ -28,4 +28,6 @@ |
||||
Prelinked libraries may use Elf32_Rela though. */ |
||||
#define ELF_MACHINE_PLT_REL 1 |
||||
|
||||
+#define PLTREL ElfW(Rel) |
||||
+ |
||||
#endif |
||||
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h |
||||
index c55c9a3d64bed1f2..5483e903d81e85c6 100644 |
||||
--- a/sysdeps/i386/dl-machine.h |
||||
+++ b/sysdeps/i386/dl-machine.h |
||||
@@ -122,29 +122,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], |
||||
return lazy; |
||||
} |
||||
|
||||
-#ifdef IN_DL_RUNTIME |
||||
- |
||||
-# ifndef PROF |
||||
-/* We add a declaration of this function here so that in dl-runtime.c |
||||
- the ELF_MACHINE_RUNTIME_TRAMPOLINE macro really can pass the parameters |
||||
- in registers. |
||||
- |
||||
- We cannot use this scheme for profiling because the _mcount call |
||||
- destroys the passed register information. */ |
||||
-#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused)) |
||||
- |
||||
-extern ElfW(Addr) _dl_fixup (struct link_map *l, |
||||
- ElfW(Word) reloc_offset) |
||||
- ARCH_FIXUP_ATTRIBUTE; |
||||
-extern ElfW(Addr) _dl_profile_fixup (struct link_map *l, |
||||
- ElfW(Word) reloc_offset, |
||||
- ElfW(Addr) retaddr, void *regs, |
||||
- long int *framesizep) |
||||
- ARCH_FIXUP_ATTRIBUTE; |
||||
-# endif |
||||
- |
||||
-#endif |
||||
- |
||||
/* Mask identifying addresses reserved for the user program, |
||||
where the dynamic linker should not map anything. */ |
||||
#define ELF_MACHINE_USER_ADDRESS_MASK 0xf0000000UL |
||||
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S |
||||
index b5ec0326df94f0fd..3a33051c52da9cde 100644 |
||||
--- a/sysdeps/i386/dl-trampoline.S |
||||
+++ b/sysdeps/i386/dl-trampoline.S |
||||
@@ -265,7 +265,7 @@ _dl_runtime_profile: |
||||
movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax |
||||
# PLT1 |
||||
movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx |
||||
- call _dl_call_pltexit |
||||
+ call _dl_audit_pltexit |
||||
movl LRV_EAX_OFFSET(%esp), %eax |
||||
movl LRV_EDX_OFFSET(%esp), %edx |
||||
fldt LRV_ST1_OFFSET(%esp) |
||||
diff --git a/sysdeps/ia64/dl-trampoline.S b/sysdeps/ia64/dl-trampoline.S |
||||
index 3053405a3a21d62e..11e86932c75d5b6b 100644 |
||||
--- a/sysdeps/ia64/dl-trampoline.S |
||||
+++ b/sysdeps/ia64/dl-trampoline.S |
||||
@@ -133,7 +133,7 @@ END(_dl_runtime_resolve) |
||||
|
||||
|
||||
/* The fourth argument to _dl_profile_fixup and the third one to |
||||
- _dl_call_pltexit are a pointer to La_ia64_regs: |
||||
+ _dl_audit_pltexit are a pointer to La_ia64_regs: |
||||
|
||||
8byte r8 |
||||
8byte r9 |
||||
@@ -159,7 +159,7 @@ END(_dl_runtime_resolve) |
||||
8byte sp |
||||
|
||||
The fifth argument to _dl_profile_fixup is a pointer to long int. |
||||
- The fourth argument to _dl_call_pltexit is a pointer to |
||||
+ The fourth argument to _dl_audit_pltexit is a pointer to |
||||
La_ia64_retval: |
||||
|
||||
8byte r8 |
||||
@@ -261,7 +261,7 @@ ENTRY(_dl_runtime_profile) |
||||
} |
||||
{ .mii |
||||
mov r18 = ar.unat /* save it in La_ia64_regs */ |
||||
- mov loc7 = out3 /* save it for _dl_call_pltexit */ |
||||
+ mov loc7 = out3 /* save it for _dl_audit_pltexit */ |
||||
mov loc5 = r11 /* preserve language specific register */ |
||||
} |
||||
{ .mmi |
||||
@@ -272,7 +272,7 @@ ENTRY(_dl_runtime_profile) |
||||
} |
||||
{ .mii |
||||
mov ar.unat = r17 /* restore it for function call */ |
||||
- mov loc8 = r16 /* save it for _dl_call_pltexit */ |
||||
+ mov loc8 = r16 /* save it for _dl_audit_pltexit */ |
||||
nop.i 0x0 |
||||
} |
||||
{ .mmi |
||||
@@ -291,7 +291,7 @@ ENTRY(_dl_runtime_profile) |
||||
{ .mmi |
||||
stf.spill [r2] = f14, 32 |
||||
stf.spill [r3] = f15, 24 |
||||
- mov loc9 = out1 /* save it for _dl_call_pltexit */ |
||||
+ mov loc9 = out1 /* save it for _dl_audit_pltexit */ |
||||
;; |
||||
} |
||||
{ .mmb |
||||
@@ -426,7 +426,7 @@ ENTRY(_dl_runtime_profile) |
||||
br.call.sptk.many b0 = b6 |
||||
} |
||||
{ .mii |
||||
- /* Prepare stack for _dl_call_pltexit. Loc10 has the original |
||||
+ /* Prepare stack for _dl_audit_pltexit. Loc10 has the original |
||||
stack pointer. */ |
||||
adds r12 = -PLTEXIT_FRAME_SIZE, loc10 |
||||
adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10 |
||||
@@ -461,14 +461,14 @@ ENTRY(_dl_runtime_profile) |
||||
{ .mmi |
||||
stf.spill [r2] = f12, 32 |
||||
stf.spill [r3] = f13, 32 |
||||
- /* We need to restore gp for _dl_call_pltexit. */ |
||||
+ /* We need to restore gp for _dl_audit_pltexit. */ |
||||
mov gp = loc11 |
||||
;; |
||||
} |
||||
{ .mmb |
||||
stf.spill [r2] = f14 |
||||
stf.spill [r3] = f15 |
||||
- br.call.sptk.many b0 = _dl_call_pltexit |
||||
+ br.call.sptk.many b0 = _dl_audit_pltexit |
||||
} |
||||
{ .mmi |
||||
/* Load all the non-floating and floating return values. Skip |
||||
diff --git a/sysdeps/m68k/dl-trampoline.S b/sysdeps/m68k/dl-trampoline.S |
||||
index a51a5f7f573c6330..72bde664c31c4256 100644 |
||||
--- a/sysdeps/m68k/dl-trampoline.S |
||||
+++ b/sysdeps/m68k/dl-trampoline.S |
||||
@@ -202,7 +202,7 @@ _dl_runtime_profile: |
||||
cfi_adjust_cfa_offset (4) |
||||
move.l (32+FPSPACE)(%sp), -(%sp) |
||||
cfi_adjust_cfa_offset (4) |
||||
- jbsr _dl_call_pltexit |
||||
+ jbsr _dl_audit_pltexit |
||||
lea 16(%sp), %sp |
||||
cfi_adjust_cfa_offset (-16) |
||||
move.l (%sp)+, %d0 |
||||
diff --git a/sysdeps/mips/dl-machine-rel.h b/sysdeps/mips/dl-machine-rel.h |
||||
index ed396180412bc723..3d0dfec01f6b193e 100644 |
||||
--- a/sysdeps/mips/dl-machine-rel.h |
||||
+++ b/sysdeps/mips/dl-machine-rel.h |
||||
@@ -22,5 +22,6 @@ |
||||
#define ELF_MACHINE_PLT_REL 1 |
||||
#define ELF_MACHINE_NO_REL 0 |
||||
#define ELF_MACHINE_NO_RELA 0 |
||||
+#define PLTREL ElfW(Rel) |
||||
|
||||
#endif |
||||
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S |
||||
index 61bd8571fcc93caa..97f0105ce780514e 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S |
||||
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S |
||||
@@ -197,7 +197,7 @@ END(_dl_runtime_resolve) |
||||
#ifndef PROF |
||||
ENTRY (_dl_profile_resolve, 4) |
||||
/* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we |
||||
- need to call _dl_call_pltexit. */ |
||||
+ need to call _dl_audit_pltexit. */ |
||||
std r31,-8(r1) |
||||
std r30,-16(r1) |
||||
/* We need to save the registers used to pass parameters, ie. r3 thru |
||||
@@ -452,7 +452,7 @@ L(restoreFXR2): |
||||
L(callpltexit): |
||||
addi r5,r1,INT_PARMS |
||||
addi r6,r1,INT_RTN |
||||
- bl JUMPTARGET(_dl_call_pltexit) |
||||
+ bl JUMPTARGET(_dl_audit_pltexit) |
||||
#ifndef SHARED |
||||
nop |
||||
#endif |
||||
diff --git a/sysdeps/s390/s390-32/dl-trampoline.h b/sysdeps/s390/s390-32/dl-trampoline.h |
||||
index c224a2b92832af9b..9e4cd1055fe6ab20 100644 |
||||
--- a/sysdeps/s390/s390-32/dl-trampoline.h |
||||
+++ b/sysdeps/s390/s390-32/dl-trampoline.h |
||||
@@ -282,7 +282,7 @@ _dl_runtime_profile: |
||||
basr %r1,0 |
||||
5: l %r14,7f-5b(%r1) |
||||
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_32_retval * |
||||
- bas %r14,0(%r14,%r1) # call _dl_call_pltexit |
||||
+ bas %r14,0(%r14,%r1) # call _dl_audit_pltexit |
||||
|
||||
lr %r15,%r12 # remove stack frame |
||||
# undef FRAME_SIZE |
||||
@@ -301,7 +301,7 @@ _dl_runtime_profile: |
||||
br %r14 |
||||
|
||||
6: .long _dl_profile_fixup - 0b |
||||
-7: .long _dl_call_pltexit - 5b |
||||
+7: .long _dl_audit_pltexit - 5b |
||||
cfi_endproc |
||||
.size _dl_runtime_profile, .-_dl_runtime_profile |
||||
# undef SIZEOF_STRUCT_LA_S390_32_REGS |
||||
diff --git a/sysdeps/s390/s390-64/dl-trampoline.h b/sysdeps/s390/s390-64/dl-trampoline.h |
||||
index ae741a3bad5ec77e..6e5bad40459ec765 100644 |
||||
--- a/sysdeps/s390/s390-64/dl-trampoline.h |
||||
+++ b/sysdeps/s390/s390-64/dl-trampoline.h |
||||
@@ -284,7 +284,7 @@ _dl_runtime_profile: |
||||
lmg %r2,%r4,CFA_OFF+PLT1_OFF(%r12) # r2, r3: args saved by PLT |
||||
# r4: struct La_s390_64_regs * |
||||
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_64_retval * |
||||
- brasl %r14,_dl_call_pltexit |
||||
+ brasl %r14,_dl_audit_pltexit |
||||
|
||||
lgr %r15,%r12 # remove stack frame |
||||
# undef FRAME_SIZE |
||||
diff --git a/sysdeps/sh/dl-trampoline.S b/sysdeps/sh/dl-trampoline.S |
||||
index 824ac84ba1830ce5..f9038cd10ed5286f 100644 |
||||
--- a/sysdeps/sh/dl-trampoline.S |
||||
+++ b/sysdeps/sh/dl-trampoline.S |
||||
@@ -423,8 +423,8 @@ _dl_runtime_profile: |
||||
.align 2 |
||||
#ifdef SHARED |
||||
7: .long _GLOBAL_OFFSET_TABLE_ |
||||
-8: .long _dl_call_pltexit@GOTOFF |
||||
+8: .long _dl_audit_pltexit@GOTOFF |
||||
#else |
||||
-8: .long _dl_call_pltexit |
||||
+8: .long _dl_audit_pltexit |
||||
#endif |
||||
.size _dl_runtime_profile, .-_dl_runtime_profile |
||||
diff --git a/sysdeps/sparc/sparc32/dl-trampoline.S b/sysdeps/sparc/sparc32/dl-trampoline.S |
||||
index 426f90c99a7ed369..2f64809731c865a2 100644 |
||||
--- a/sysdeps/sparc/sparc32/dl-trampoline.S |
||||
+++ b/sysdeps/sparc/sparc32/dl-trampoline.S |
||||
@@ -127,7 +127,7 @@ _dl_profile_invoke: |
||||
mov %l5, %o0 |
||||
mov %l6, %o1 |
||||
add %sp, (11 * 8), %o2 |
||||
- call _dl_call_pltexit |
||||
+ call _dl_audit_pltexit |
||||
add %sp, ( 9 * 8), %o3 |
||||
|
||||
ldd [%sp + ( 9 * 8)], %i0 |
||||
diff --git a/sysdeps/sparc/sparc64/dl-trampoline.S b/sysdeps/sparc/sparc64/dl-trampoline.S |
||||
index 8d59fa67209cd8ab..86605e37acd929fd 100644 |
||||
--- a/sysdeps/sparc/sparc64/dl-trampoline.S |
||||
+++ b/sysdeps/sparc/sparc64/dl-trampoline.S |
||||
@@ -196,7 +196,7 @@ _dl_profile_invoke: |
||||
mov %l5, %o0 |
||||
mov %l6, %o1 |
||||
add %sp, STACK_BIAS + (24 * 8), %o2 |
||||
- call _dl_call_pltexit |
||||
+ call _dl_audit_pltexit |
||||
add %sp, STACK_BIAS + (16 * 8), %o3 |
||||
|
||||
ldx [%sp + STACK_BIAS + (16 * 8)], %i0 |
||||
diff --git a/sysdeps/x86_64/dl-runtime.h b/sysdeps/x86_64/dl-runtime.h |
||||
index 9c8d3977eee27069..19ba33ef30970c20 100644 |
||||
--- a/sysdeps/x86_64/dl-runtime.h |
||||
+++ b/sysdeps/x86_64/dl-runtime.h |
||||
@@ -18,7 +18,7 @@ |
||||
02111-1307 USA. */ |
||||
|
||||
/* The ABI calls for the PLT stubs to pass the index of the relocation |
||||
- and not its offset. In _dl_profile_fixup and _dl_call_pltexit we |
||||
+ and not its offset. In _dl_profile_fixup and _dl_audit_pltexit we |
||||
also use the index. Therefore it is wasteful to compute the offset |
||||
in the trampoline just to reverse the operation immediately |
||||
afterwards. */ |
||||
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h |
||||
index b9a12970cd6206ee..b5de7efff778559e 100644 |
||||
--- a/sysdeps/x86_64/dl-trampoline.h |
||||
+++ b/sysdeps/x86_64/dl-trampoline.h |
||||
@@ -388,7 +388,7 @@ _dl_runtime_profile: |
||||
jns 3f |
||||
|
||||
/* There's nothing in the frame size, so there |
||||
- will be no call to the _dl_call_pltexit. */ |
||||
+ will be no call to the _dl_audit_pltexit. */ |
||||
|
||||
/* Get back registers content. */ |
||||
movq LR_RCX_OFFSET(%rsp), %rcx |
||||
@@ -436,7 +436,7 @@ _dl_runtime_profile: |
||||
mov 24(%rbx), %RSP_LP # Drop the copied stack content |
||||
|
||||
/* Now we have to prepare the La_x86_64_retval structure for the |
||||
- _dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now, |
||||
+ _dl_audit_pltexit. The La_x86_64_regs is being pointed by rsp now, |
||||
so we just need to allocate the sizeof(La_x86_64_retval) space on |
||||
the stack, since the alignment has already been taken care of. */ |
||||
# ifdef RESTORE_AVX |
||||
@@ -491,7 +491,7 @@ _dl_runtime_profile: |
||||
movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx. |
||||
movq 40(%rbx), %rsi # Copy args pushed by PLT in register. |
||||
movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index |
||||
- call _dl_call_pltexit |
||||
+ call _dl_audit_pltexit |
||||
|
||||
/* Restore return registers. */ |
||||
movq LRV_RAX_OFFSET(%rsp), %rax |
@ -0,0 +1,454 @@
@@ -0,0 +1,454 @@
|
||||
commit 29496b3103ff13aa3c1d8b62552a98f39da0fe59 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Jun 30 10:24:09 2021 -0300 |
||||
|
||||
elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) |
||||
|
||||
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 063f9ba220f434c7f30dd65c4cff17c0c458a7cf) |
||||
|
||||
Resolved conflicts: |
||||
NEWS |
||||
elf/Makefile |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 85165c0591412a45..eab9d46b6165e6be 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -365,6 +365,7 @@ tests += \ |
||||
tst-audit16 \ |
||||
tst-audit17 \ |
||||
tst-audit18 \ |
||||
+ tst-audit19b \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
tst-auxobj-dlopen \ |
||||
@@ -454,6 +455,7 @@ tests-internal += \ |
||||
neededtest2 \ |
||||
neededtest3 \ |
||||
neededtest4 \ |
||||
+ tst-audit19a \ |
||||
tst-create_format1 \ |
||||
tst-dl-hwcaps_split \ |
||||
tst-dlmopen2 \ |
||||
@@ -626,6 +628,7 @@ modules-names = \ |
||||
tst-audit12mod3 \ |
||||
tst-audit13mod1 \ |
||||
tst-audit18mod \ |
||||
+ tst-audit19bmod \ |
||||
tst-auditlogmod-1 \ |
||||
tst-auditlogmod-2 \ |
||||
tst-auditlogmod-3 \ |
||||
@@ -644,6 +647,8 @@ modules-names = \ |
||||
tst-auditmod11 \ |
||||
tst-auditmod12 \ |
||||
tst-auditmod18 \ |
||||
+ tst-auditmod19a \ |
||||
+ tst-auditmod19b \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
tst-deep1mod1 \ |
||||
@@ -2007,6 +2012,13 @@ $(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \ |
||||
$(objpfx)tst-audit18mod.so |
||||
tst-audit18-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
+$(objpfx)tst-audit19a.out: $(objpfx)tst-auditmod19a.so |
||||
+tst-audit19a-ENV = LD_AUDIT=$(objpfx)tst-auditmod19a.so |
||||
+ |
||||
+$(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so |
||||
+$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so |
||||
+tst-audit19b-ARGS = -- $(host-test-program-cmd) |
||||
+ |
||||
# tst-sonamemove links against an older implementation of the library. |
||||
LDFLAGS-tst-sonamemove-linkmod1.so = \ |
||||
-Wl,--version-script=tst-sonamemove-linkmod1.map \ |
||||
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c |
||||
index 3447de7f3536cd70..5b69321bda1f2b27 100644 |
||||
--- a/elf/dl-reloc.c |
||||
+++ b/elf/dl-reloc.c |
||||
@@ -205,12 +205,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], |
||||
int skip_ifunc = reloc_mode & __RTLD_NOIFUNC; |
||||
|
||||
#ifdef SHARED |
||||
+ bool consider_symbind = false; |
||||
/* If we are auditing, install the same handlers we need for profiling. */ |
||||
if ((reloc_mode & __RTLD_AUDIT) == 0) |
||||
- consider_profiling |= GLRO(dl_audit) != NULL; |
||||
+ { |
||||
+ struct audit_ifaces *afct = GLRO(dl_audit); |
||||
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) |
||||
+ { |
||||
+ /* Profiling is needed only if PLT hooks are provided. */ |
||||
+ if (afct->ARCH_LA_PLTENTER != NULL |
||||
+ || afct->ARCH_LA_PLTEXIT != NULL) |
||||
+ consider_profiling = 1; |
||||
+ if (afct->symbind != NULL) |
||||
+ consider_symbind = true; |
||||
+ |
||||
+ afct = afct->next; |
||||
+ } |
||||
+ } |
||||
#elif defined PROF |
||||
/* Never use dynamic linker profiling for gprof profiling code. */ |
||||
# define consider_profiling 0 |
||||
+#else |
||||
+# define consider_symbind 0 |
||||
#endif |
||||
|
||||
if (l->l_relocated) |
||||
@@ -272,7 +288,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], |
||||
ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); |
||||
|
||||
#ifndef PROF |
||||
- if (__glibc_unlikely (consider_profiling) |
||||
+ if ((consider_profiling || consider_symbind) |
||||
&& l->l_info[DT_PLTRELSZ] != NULL) |
||||
{ |
||||
/* Allocate the array which will contain the already found |
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c |
||||
index e42f6e8b8dfca08e..77a5cccdcbcb9293 100644 |
||||
--- a/elf/dl-runtime.c |
||||
+++ b/elf/dl-runtime.c |
||||
@@ -124,6 +124,37 @@ _dl_fixup ( |
||||
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) |
||||
value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value)); |
||||
|
||||
+#ifdef SHARED |
||||
+ /* Auditing checkpoint: we have a new binding. Provide the auditing |
||||
+ libraries the possibility to change the value and tell us whether further |
||||
+ auditing is wanted. |
||||
+ The l_reloc_result is only allocated if there is an audit module which |
||||
+ provides a la_symbind. */ |
||||
+ if (l->l_reloc_result != NULL) |
||||
+ { |
||||
+ /* This is the address in the array where we store the result of previous |
||||
+ relocations. */ |
||||
+ struct reloc_result *reloc_result |
||||
+ = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; |
||||
+ unsigned int init = atomic_load_acquire (&reloc_result->init); |
||||
+ if (init == 0) |
||||
+ { |
||||
+ _dl_audit_symbind (l, reloc_result, sym, &value, result); |
||||
+ |
||||
+ /* Store the result for later runs. */ |
||||
+ if (__glibc_likely (! GLRO(dl_bind_not))) |
||||
+ { |
||||
+ reloc_result->addr = value; |
||||
+ /* Guarantee all previous writes complete before init is |
||||
+ updated. See CONCURRENCY NOTES below. */ |
||||
+ atomic_store_release (&reloc_result->init, 1); |
||||
+ } |
||||
+ } |
||||
+ else |
||||
+ value = reloc_result->addr; |
||||
+ } |
||||
+#endif |
||||
+ |
||||
/* Finally, fix up the plt itself. */ |
||||
if (__glibc_unlikely (GLRO(dl_bind_not))) |
||||
return value; |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index b6bb46ca97b7972f..f632a767d7a269ef 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -1016,13 +1016,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); |
||||
"la_objsearch\0" |
||||
"la_objopen\0" |
||||
"la_preinit\0" |
||||
-#if __ELF_NATIVE_CLASS == 32 |
||||
- "la_symbind32\0" |
||||
-#elif __ELF_NATIVE_CLASS == 64 |
||||
- "la_symbind64\0" |
||||
-#else |
||||
-# error "__ELF_NATIVE_CLASS must be defined" |
||||
-#endif |
||||
+ LA_SYMBIND "\0" |
||||
#define STRING(s) __STRING (s) |
||||
"la_" STRING (ARCH_LA_PLTENTER) "\0" |
||||
"la_" STRING (ARCH_LA_PLTEXIT) "\0" |
||||
diff --git a/elf/tst-audit19a.c b/elf/tst-audit19a.c |
||||
new file mode 100644 |
||||
index 0000000000000000..035cde9351c2711b |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit19a.c |
||||
@@ -0,0 +1,38 @@ |
||||
+/* Check if DT_AUDIT a module without la_plt{enter,exit} symbols does not incur |
||||
+ in profiling (BZ#15533). |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+#include <support/xdlfcn.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ void *h = xdlopen ("tst-auditmod19a.so", RTLD_NOW); |
||||
+ |
||||
+ struct link_map *lmap; |
||||
+ TEST_VERIFY_EXIT (dlinfo (h, RTLD_DI_LINKMAP, &lmap) == 0); |
||||
+ |
||||
+ /* The internal array is only allocated if profiling is enabled. */ |
||||
+ TEST_VERIFY (lmap->l_reloc_result == NULL); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-audit19b.c b/elf/tst-audit19b.c |
||||
new file mode 100644 |
||||
index 0000000000000000..da015734f24e0d79 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit19b.c |
||||
@@ -0,0 +1,94 @@ |
||||
+/* Check if DT_AUDIT a module with la_plt{enter,exit} call la_symbind |
||||
+ for lazy resolution. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <getopt.h> |
||||
+#include <support/capture_subprocess.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xstdio.h> |
||||
+#include <stdlib.h> |
||||
+#include <string.h> |
||||
+#include <stdbool.h> |
||||
+ |
||||
+static int restart; |
||||
+#define CMDLINE_OPTIONS \ |
||||
+ { "restart", no_argument, &restart, 1 }, |
||||
+ |
||||
+int tst_audit18bmod1_func (void); |
||||
+ |
||||
+static int |
||||
+handle_restart (void) |
||||
+{ |
||||
+ TEST_COMPARE (tst_audit18bmod1_func (), 10); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+startswith (const char *str, const char *pre) |
||||
+{ |
||||
+ size_t lenpre = strlen (pre); |
||||
+ size_t lenstr = strlen (str); |
||||
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (int argc, char *argv[]) |
||||
+{ |
||||
+ /* We must have either: |
||||
+ - One our fource parameters left if called initially: |
||||
+ + path to ld.so optional |
||||
+ + "--library-path" optional |
||||
+ + the library path optional |
||||
+ + the application name */ |
||||
+ |
||||
+ if (restart) |
||||
+ return handle_restart (); |
||||
+ |
||||
+ char *spargv[9]; |
||||
+ int i = 0; |
||||
+ for (; i < argc - 1; i++) |
||||
+ spargv[i] = argv[i + 1]; |
||||
+ spargv[i++] = (char *) "--direct"; |
||||
+ spargv[i++] = (char *) "--restart"; |
||||
+ spargv[i] = NULL; |
||||
+ |
||||
+ setenv ("LD_AUDIT", "tst-auditmod18b.so", 0); |
||||
+ struct support_capture_subprocess result |
||||
+ = support_capture_subprogram (spargv[0], spargv); |
||||
+ support_capture_subprocess_check (&result, "tst-audit18b", 0, sc_allow_stderr); |
||||
+ |
||||
+ bool find_symbind = false; |
||||
+ |
||||
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); |
||||
+ TEST_VERIFY (out != NULL); |
||||
+ char *buffer = NULL; |
||||
+ size_t buffer_length = 0; |
||||
+ while (xgetline (&buffer, &buffer_length, out)) |
||||
+ if (startswith (buffer, "la_symbind: tst_audit18bmod1_func") == 0) |
||||
+ find_symbind = true; |
||||
+ |
||||
+ TEST_COMPARE (find_symbind, true); |
||||
+ |
||||
+ free (buffer); |
||||
+ xfclose (out); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#define TEST_FUNCTION_ARGV do_test |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-audit19bmod.c b/elf/tst-audit19bmod.c |
||||
new file mode 100644 |
||||
index 0000000000000000..9ffdcd8f3ffbc38e |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit19bmod.c |
||||
@@ -0,0 +1,23 @@ |
||||
+/* Extra module for tst-audit18b. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+int |
||||
+tst_audit18bmod1_func (void) |
||||
+{ |
||||
+ return 10; |
||||
+} |
||||
diff --git a/elf/tst-auditmod19a.c b/elf/tst-auditmod19a.c |
||||
new file mode 100644 |
||||
index 0000000000000000..f58204099457743d |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod19a.c |
||||
@@ -0,0 +1,25 @@ |
||||
+/* Audit module for tst-audit18a. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
diff --git a/elf/tst-auditmod19b.c b/elf/tst-auditmod19b.c |
||||
new file mode 100644 |
||||
index 0000000000000000..e2248b2a75946746 |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod19b.c |
||||
@@ -0,0 +1,46 @@ |
||||
+/* Audit module for tst-audit18b. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+#include <string.h> |
||||
+#include <stdio.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) |
||||
+{ |
||||
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM; |
||||
+} |
||||
+ |
||||
+uintptr_t |
||||
+#if __ELF_NATIVE_CLASS == 32 |
||||
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, |
||||
+ uintptr_t *defcook, unsigned int *flags, const char *symname) |
||||
+#else |
||||
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, |
||||
+ uintptr_t *defcook, unsigned int *flags, const char *symname) |
||||
+#endif |
||||
+{ |
||||
+ fprintf (stderr, "la_symbind: %s\n", symname); |
||||
+ return sym->st_value; |
||||
+} |
||||
diff --git a/include/link.h b/include/link.h |
||||
index 4dcf01d8aea90bc2..b3f160c278222b3c 100644 |
||||
--- a/include/link.h |
||||
+++ b/include/link.h |
||||
@@ -363,8 +363,10 @@ struct auditstate |
||||
|
||||
#if __ELF_NATIVE_CLASS == 32 |
||||
# define symbind symbind32 |
||||
+# define LA_SYMBIND "la_symbind32" |
||||
#elif __ELF_NATIVE_CLASS == 64 |
||||
# define symbind symbind64 |
||||
+# define LA_SYMBIND "la_symbind64" |
||||
#else |
||||
# error "__ELF_NATIVE_CLASS must be defined" |
||||
#endif |
@ -0,0 +1,294 @@
@@ -0,0 +1,294 @@
|
||||
commit 02c6a3d35316d360ae08623f617b1873d2f6159a |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Jun 30 15:51:31 2021 -0300 |
||||
|
||||
elf: Add audit tests for modules with TLSDESC |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit d1b38173c9255b1a4ae00018ad9b35404a7c74d0) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index eab9d46b6165e6be..29f545d2272bf6e2 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -807,6 +807,22 @@ modules-names += tst-gnu2-tls1mod |
||||
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so |
||||
tst-gnu2-tls1mod.so-no-z-defs = yes |
||||
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2 |
||||
+ |
||||
+tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen |
||||
+modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc |
||||
+$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \ |
||||
+ $(objpfx)tst-audit-tlsdesc-mod2.so \ |
||||
+ $(shared-thread-library) |
||||
+CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2 |
||||
+CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2 |
||||
+$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library) |
||||
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \ |
||||
+ $(objpfx)tst-audit-tlsdesc-mod2.so |
||||
+$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so |
||||
+$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so |
||||
+tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so |
||||
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so |
||||
+tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so |
||||
endif |
||||
ifeq (yes,$(have-protected-data)) |
||||
modules-names += tst-protected1moda tst-protected1modb |
||||
diff --git a/elf/tst-audit-tlsdesc-dlopen.c b/elf/tst-audit-tlsdesc-dlopen.c |
||||
new file mode 100644 |
||||
index 0000000000000000..9c16bb087aca1b77 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit-tlsdesc-dlopen.c |
||||
@@ -0,0 +1,67 @@ |
||||
+/* DT_AUDIT with modules with TLSDESC. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/xthread.h> |
||||
+#include <support/xdlfcn.h> |
||||
+ |
||||
+static void * |
||||
+thr_func (void *mod) |
||||
+{ |
||||
+ int* (*get_global1)(void) = xdlsym (mod, "get_global1"); |
||||
+ int* (*get_global2)(void) = xdlsym (mod, "get_global2"); |
||||
+ void (*set_global2)(int) = xdlsym (mod, "set_global2"); |
||||
+ int* (*get_local1)(void) = xdlsym (mod, "get_local1"); |
||||
+ int* (*get_local2)(void) = xdlsym (mod, "get_local2"); |
||||
+ |
||||
+ int *global1 = get_global1 (); |
||||
+ TEST_COMPARE (*global1, 0); |
||||
+ ++*global1; |
||||
+ |
||||
+ int *global2 = get_global2 (); |
||||
+ TEST_COMPARE (*global2, 0); |
||||
+ ++*global2; |
||||
+ TEST_COMPARE (*global2, 1); |
||||
+ |
||||
+ set_global2 (10); |
||||
+ TEST_COMPARE (*global2, 10); |
||||
+ |
||||
+ int *local1 = get_local1 (); |
||||
+ TEST_COMPARE (*local1, 0); |
||||
+ ++*local1; |
||||
+ |
||||
+ int *local2 = get_local2 (); |
||||
+ TEST_COMPARE (*local2, 0); |
||||
+ ++*local2; |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ void *mod = xdlopen ("tst-audit-tlsdesc-mod1.so", RTLD_LAZY); |
||||
+ |
||||
+ pthread_t thr = xpthread_create (NULL, thr_func, mod); |
||||
+ void *r = xpthread_join (thr); |
||||
+ TEST_VERIFY (r == NULL); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-audit-tlsdesc-mod1.c b/elf/tst-audit-tlsdesc-mod1.c |
||||
new file mode 100644 |
||||
index 0000000000000000..61c7dd99a2fb5e28 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit-tlsdesc-mod1.c |
||||
@@ -0,0 +1,41 @@ |
||||
+/* DT_AUDIT with modules with TLSDESC. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+__thread int global1; |
||||
+ |
||||
+int * |
||||
+get_global1 (void) |
||||
+{ |
||||
+ return &global1; |
||||
+} |
||||
+ |
||||
+static __thread int local1; |
||||
+ |
||||
+void * |
||||
+get_local1 (void) |
||||
+{ |
||||
+ return &local1; |
||||
+} |
||||
+ |
||||
+extern __thread int global2; |
||||
+ |
||||
+void |
||||
+set_global2 (int v) |
||||
+{ |
||||
+ global2 = v; |
||||
+} |
||||
diff --git a/elf/tst-audit-tlsdesc-mod2.c b/elf/tst-audit-tlsdesc-mod2.c |
||||
new file mode 100644 |
||||
index 0000000000000000..28aef635f688ee03 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit-tlsdesc-mod2.c |
||||
@@ -0,0 +1,33 @@ |
||||
+/* DT_AUDIT with modules with TLSDESC. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+__thread int global2; |
||||
+ |
||||
+int * |
||||
+get_global2 (void) |
||||
+{ |
||||
+ return &global2; |
||||
+} |
||||
+ |
||||
+static __thread int local2; |
||||
+ |
||||
+void * |
||||
+get_local2 (void) |
||||
+{ |
||||
+ return &local2; |
||||
+} |
||||
diff --git a/elf/tst-audit-tlsdesc.c b/elf/tst-audit-tlsdesc.c |
||||
new file mode 100644 |
||||
index 0000000000000000..3c8be81c95528f47 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit-tlsdesc.c |
||||
@@ -0,0 +1,60 @@ |
||||
+/* DT_AUDIT with modules with TLSDESC. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/xthread.h> |
||||
+ |
||||
+extern __thread int global1; |
||||
+extern __thread int global2; |
||||
+void *get_local1 (void); |
||||
+void set_global2 (int v); |
||||
+void *get_local2 (void); |
||||
+ |
||||
+static void * |
||||
+thr_func (void *clousure) |
||||
+{ |
||||
+ TEST_COMPARE (global1, 0); |
||||
+ ++global1; |
||||
+ TEST_COMPARE (global2, 0); |
||||
+ ++global2; |
||||
+ TEST_COMPARE (global2, 1); |
||||
+ |
||||
+ set_global2 (10); |
||||
+ TEST_COMPARE (global2, 10); |
||||
+ |
||||
+ int *local1 = get_local1 (); |
||||
+ TEST_COMPARE (*local1, 0); |
||||
+ ++*local1; |
||||
+ |
||||
+ int *local2 = get_local2 (); |
||||
+ TEST_COMPARE (*local2, 0); |
||||
+ ++*local2; |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ pthread_t thr = xpthread_create (NULL, thr_func, NULL); |
||||
+ void *r = xpthread_join (thr); |
||||
+ TEST_VERIFY (r == NULL); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-auditmod-tlsdesc.c b/elf/tst-auditmod-tlsdesc.c |
||||
new file mode 100644 |
||||
index 0000000000000000..e4b835d1f1fb6f73 |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod-tlsdesc.c |
||||
@@ -0,0 +1,25 @@ |
||||
+/* DT_AUDIT with modules with TLSDESC. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
@ -0,0 +1,314 @@
@@ -0,0 +1,314 @@
|
||||
commit d1b9bee29a1c4e0b80db53f228e22550c3604894 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Mon Jul 19 18:42:26 2021 -0300 |
||||
|
||||
elf: Issue audit la_objopen for vDSO |
||||
|
||||
The vDSO is is listed in the link_map chain, but is never the subject of |
||||
an la_objopen call. A new internal flag __RTLD_VDSO is added that |
||||
acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate' |
||||
extra space for the 'struct link_map'. |
||||
|
||||
The return value from the callback is currently ignored, since there |
||||
is no PLT call involved by glibc when using the vDSO, neither the vDSO |
||||
are exported directly. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit f0e23d34a7bdf6b90fba954ee741419171ac41b2) |
||||
|
||||
Resolved conflicts: |
||||
elf/Makefile |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 29f545d2272bf6e2..465442bf59fa9794 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -366,6 +366,7 @@ tests += \ |
||||
tst-audit17 \ |
||||
tst-audit18 \ |
||||
tst-audit19b \ |
||||
+ tst-audit22 \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
tst-auxobj-dlopen \ |
||||
@@ -649,6 +650,7 @@ modules-names = \ |
||||
tst-auditmod18 \ |
||||
tst-auditmod19a \ |
||||
tst-auditmod19b \ |
||||
+ tst-auditmod22 \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
tst-deep1mod1 \ |
||||
@@ -2035,6 +2037,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so |
||||
$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so |
||||
tst-audit19b-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
+$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so |
||||
+tst-audit22-ARGS = -- $(host-test-program-cmd) |
||||
+ |
||||
# tst-sonamemove links against an older implementation of the library. |
||||
LDFLAGS-tst-sonamemove-linkmod1.so = \ |
||||
-Wl,--version-script=tst-sonamemove-linkmod1.map \ |
||||
diff --git a/elf/dl-object.c b/elf/dl-object.c |
||||
index 1875599eb274dc35..dee49a32d4fdf07d 100644 |
||||
--- a/elf/dl-object.c |
||||
+++ b/elf/dl-object.c |
||||
@@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type, |
||||
{ |
||||
#ifdef SHARED |
||||
unsigned int naudit; |
||||
- if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0)) |
||||
+ if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0)) |
||||
{ |
||||
- assert (type == lt_executable); |
||||
- assert (nsid == LM_ID_BASE); |
||||
+ if (mode & __RTLD_OPENEXEC) |
||||
+ { |
||||
+ assert (type == lt_executable); |
||||
+ assert (nsid == LM_ID_BASE); |
||||
|
||||
- /* Ignore the specified libname for the main executable. It is |
||||
- only known with an explicit loader invocation. */ |
||||
- libname = ""; |
||||
+ /* Ignore the specified libname for the main executable. It is |
||||
+ only known with an explicit loader invocation. */ |
||||
+ libname = ""; |
||||
+ } |
||||
|
||||
- /* We create the map for the executable before we know whether |
||||
+ /* We create the map for the executable and vDSO before we know whether |
||||
we have auditing libraries and if yes, how many. Assume the |
||||
worst. */ |
||||
naudit = DL_NNS; |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index f632a767d7a269ef..b089e5cf4740443e 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -1922,6 +1922,12 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
assert (i == npreloads); |
||||
} |
||||
|
||||
+#ifdef NEED_DL_SYSINFO_DSO |
||||
+ /* Now that the audit modules are opened, call la_objopen for the vDSO. */ |
||||
+ if (GLRO(dl_sysinfo_map) != NULL) |
||||
+ _dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE); |
||||
+#endif |
||||
+ |
||||
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD |
||||
specified some libraries to load, these are inserted before the actual |
||||
dependencies in the executable's searchlist for symbol resolution. */ |
||||
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h |
||||
index 3f20578046de76ed..2b013d974a377a83 100644 |
||||
--- a/elf/setup-vdso.h |
||||
+++ b/elf/setup-vdso.h |
||||
@@ -30,7 +30,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), |
||||
We just want our data structures to describe it as if we had just |
||||
mapped and relocated it normally. */ |
||||
struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, |
||||
- 0, LM_ID_BASE); |
||||
+ __RTLD_VDSO, LM_ID_BASE); |
||||
if (__glibc_likely (l != NULL)) |
||||
{ |
||||
l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso) |
||||
diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c |
||||
new file mode 100644 |
||||
index 0000000000000000..18fd22a760ddc3d8 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit22.c |
||||
@@ -0,0 +1,124 @@ |
||||
+/* Check DTAUDIT and vDSO interaction. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <errno.h> |
||||
+#include <getopt.h> |
||||
+#include <limits.h> |
||||
+#include <inttypes.h> |
||||
+#include <string.h> |
||||
+#include <stdlib.h> |
||||
+#include <support/capture_subprocess.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xstdio.h> |
||||
+#include <support/support.h> |
||||
+#include <sys/auxv.h> |
||||
+ |
||||
+static int restart; |
||||
+#define CMDLINE_OPTIONS \ |
||||
+ { "restart", no_argument, &restart, 1 }, |
||||
+ |
||||
+static uintptr_t vdso_addr; |
||||
+ |
||||
+static int |
||||
+handle_restart (void) |
||||
+{ |
||||
+ fprintf (stderr, "vdso: %p\n", (void*) vdso_addr); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static uintptr_t |
||||
+parse_address (const char *str) |
||||
+{ |
||||
+ void *r; |
||||
+ TEST_COMPARE (sscanf (str, "%p\n", &r), 1); |
||||
+ return (uintptr_t) r; |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+startswith (const char *str, const char *pre) |
||||
+{ |
||||
+ size_t lenpre = strlen (pre); |
||||
+ size_t lenstr = strlen (str); |
||||
+ return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (int argc, char *argv[]) |
||||
+{ |
||||
+ vdso_addr = getauxval (AT_SYSINFO_EHDR); |
||||
+ if (vdso_addr == 0) |
||||
+ FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0"); |
||||
+ |
||||
+ /* We must have either: |
||||
+ - One our fource parameters left if called initially: |
||||
+ + path to ld.so optional |
||||
+ + "--library-path" optional |
||||
+ + the library path optional |
||||
+ + the application name */ |
||||
+ if (restart) |
||||
+ return handle_restart (); |
||||
+ |
||||
+ char *spargv[9]; |
||||
+ int i = 0; |
||||
+ for (; i < argc - 1; i++) |
||||
+ spargv[i] = argv[i + 1]; |
||||
+ spargv[i++] = (char *) "--direct"; |
||||
+ spargv[i++] = (char *) "--restart"; |
||||
+ spargv[i] = NULL; |
||||
+ |
||||
+ setenv ("LD_AUDIT", "tst-auditmod22.so", 0); |
||||
+ struct support_capture_subprocess result |
||||
+ = support_capture_subprogram (spargv[0], spargv); |
||||
+ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); |
||||
+ |
||||
+ /* The respawned process should always print the vDSO address (otherwise it |
||||
+ will fails as unsupported). However, on some architectures the audit |
||||
+ module might see the vDSO with l_addr being 0, meaning a fixed mapping |
||||
+ (linux-gate.so). In this case we don't check its value against |
||||
+ AT_SYSINFO_EHDR one. */ |
||||
+ uintptr_t vdso_process = 0; |
||||
+ bool vdso_audit_found = false; |
||||
+ uintptr_t vdso_audit = 0; |
||||
+ |
||||
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); |
||||
+ TEST_VERIFY (out != NULL); |
||||
+ char *buffer = NULL; |
||||
+ size_t buffer_length = 0; |
||||
+ while (xgetline (&buffer, &buffer_length, out)) |
||||
+ { |
||||
+ if (startswith (buffer, "vdso: ")) |
||||
+ vdso_process = parse_address (buffer + strlen ("vdso: ")); |
||||
+ else if (startswith (buffer, "vdso found: ")) |
||||
+ { |
||||
+ vdso_audit = parse_address (buffer + strlen ("vdso found: ")); |
||||
+ vdso_audit_found = true; |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ TEST_COMPARE (vdso_audit_found, true); |
||||
+ if (vdso_audit != 0) |
||||
+ TEST_COMPARE (vdso_process, vdso_audit); |
||||
+ |
||||
+ free (buffer); |
||||
+ xfclose (out); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#define TEST_FUNCTION_ARGV do_test |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c |
||||
new file mode 100644 |
||||
index 0000000000000000..8e05ce8cbb215dd5 |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod22.c |
||||
@@ -0,0 +1,51 @@ |
||||
+/* Check DTAUDIT and vDSO interaction. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+#include <inttypes.h> |
||||
+#include <stdbool.h> |
||||
+#include <string.h> |
||||
+#include <stdio.h> |
||||
+#include <sys/auxv.h> |
||||
+ |
||||
+static inline bool |
||||
+startswith (const char *str, const char *pre) |
||||
+{ |
||||
+ size_t lenpre = strlen (pre); |
||||
+ size_t lenstr = strlen (str); |
||||
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) |
||||
+{ |
||||
+ /* The linux-gate.so is placed at a fixed address, thus l_addr being 0, |
||||
+ and it might be the value reported as the AT_SYSINFO_EHDR. */ |
||||
+ if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so")) |
||||
+ fprintf (stderr, "vdso found: %p\n", NULL); |
||||
+ else if (map->l_addr == getauxval (AT_SYSINFO_EHDR)) |
||||
+ fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
diff --git a/include/dlfcn.h b/include/dlfcn.h |
||||
index a4c283728f94deb4..e73294b0af587913 100644 |
||||
--- a/include/dlfcn.h |
||||
+++ b/include/dlfcn.h |
||||
@@ -12,6 +12,8 @@ |
||||
#define __RTLD_AUDIT 0x08000000 |
||||
#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */ |
||||
#define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */ |
||||
+#define __RTLD_VDSO 0x01000000 /* Tell _dl_new_object the object is |
||||
+ system-loaded. */ |
||||
|
||||
#define __LM_ID_CALLER -2 |
||||
|
@ -0,0 +1,167 @@
@@ -0,0 +1,167 @@
|
||||
commit 2255621f0e2cd07f7a6147928ce644e13526ffb6 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Jun 30 17:33:57 2021 -0300 |
||||
|
||||
elf: Do not fail for failed dlmopen on audit modules (BZ #28061) |
||||
|
||||
The dl_main sets the LM_ID_BASE to RT_ADD just before starting to |
||||
add load new shared objects. The state is set to RT_CONSISTENT just |
||||
after all objects are loaded. |
||||
|
||||
However if a audit modules tries to dlmopen an inexistent module, |
||||
the _dl_open will assert that the namespace is in an inconsistent |
||||
state. |
||||
|
||||
This is different than dlopen, since first it will not use |
||||
LM_ID_BASE and second _dl_map_object_from_fd is the sole responsible |
||||
to set and reset the r_state value. |
||||
|
||||
So the assert on _dl_open can not really be seen if the state is |
||||
consistent, since _dt_main resets it. This patch removes the assert. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
(cherry picked from commit 484e672ddabe0a919a692520e6ac8f2580866235) |
||||
|
||||
Resolved conflicts: |
||||
elf/Makefile |
||||
elf/dl-open.c |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 465442bf59fa9794..91b2269257523a64 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -366,6 +366,7 @@ tests += \ |
||||
tst-audit17 \ |
||||
tst-audit18 \ |
||||
tst-audit19b \ |
||||
+ tst-audit20 \ |
||||
tst-audit22 \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
@@ -650,6 +651,7 @@ modules-names = \ |
||||
tst-auditmod18 \ |
||||
tst-auditmod19a \ |
||||
tst-auditmod19b \ |
||||
+ tst-auditmod20 \ |
||||
tst-auditmod22 \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
@@ -2037,6 +2039,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so |
||||
$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so |
||||
tst-audit19b-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
+$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so |
||||
+tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so |
||||
+ |
||||
$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so |
||||
tst-audit22-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c |
||||
index 3f01aa480730da13..bc6872632880634e 100644 |
||||
--- a/elf/dl-open.c |
||||
+++ b/elf/dl-open.c |
||||
@@ -914,8 +914,6 @@ no more namespaces available for dlmopen()")); |
||||
the flag here. */ |
||||
} |
||||
|
||||
- assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); |
||||
- |
||||
/* Release the lock. */ |
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock)); |
||||
|
||||
diff --git a/elf/tst-audit20.c b/elf/tst-audit20.c |
||||
new file mode 100644 |
||||
index 0000000000000000..6f39ccee865b012b |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit20.c |
||||
@@ -0,0 +1,25 @@ |
||||
+/* Check dlopen failure on audit modules. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-auditmod20.c b/elf/tst-auditmod20.c |
||||
new file mode 100644 |
||||
index 0000000000000000..c57e50ee4e88dd6b |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod20.c |
||||
@@ -0,0 +1,57 @@ |
||||
+/* Check dlopen failure on audit modules. |
||||
+ Copyright (C) 2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <dlfcn.h> |
||||
+#include <link.h> |
||||
+#include <stdlib.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int v) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+static void |
||||
+check (void) |
||||
+{ |
||||
+ { |
||||
+ void *mod = dlopen ("nonexistent.so", RTLD_NOW); |
||||
+ if (mod != NULL) |
||||
+ abort (); |
||||
+ } |
||||
+ |
||||
+ { |
||||
+ void *mod = dlmopen (LM_ID_BASE, "nonexistent.so", RTLD_NOW); |
||||
+ if (mod != NULL) |
||||
+ abort (); |
||||
+ } |
||||
+} |
||||
+ |
||||
+void |
||||
+la_activity (uintptr_t *cookie, unsigned int flag) |
||||
+{ |
||||
+ if (flag != LA_ACT_CONSISTENT) |
||||
+ return; |
||||
+ check (); |
||||
+} |
||||
+ |
||||
+void |
||||
+la_preinit (uintptr_t *cookie) |
||||
+{ |
||||
+ check (); |
||||
+} |
@ -0,0 +1,434 @@
@@ -0,0 +1,434 @@
|
||||
commit 98047ba95caf9ed596908ca73a22070c5e27597b |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Mon Jan 24 10:46:15 2022 -0300 |
||||
|
||||
elf: Add la_activity during application exit |
||||
|
||||
la_activity is not called during application exit, even though |
||||
la_objclose is. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
Tested-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 5fa11a2bc94c912c3b25860065086902674537ba) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 91b2269257523a64..407aaeaeb8c84020 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -368,6 +368,7 @@ tests += \ |
||||
tst-audit19b \ |
||||
tst-audit20 \ |
||||
tst-audit22 \ |
||||
+ tst-audit23 \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
tst-auxobj-dlopen \ |
||||
@@ -631,6 +632,7 @@ modules-names = \ |
||||
tst-audit13mod1 \ |
||||
tst-audit18mod \ |
||||
tst-audit19bmod \ |
||||
+ tst-audit23mod \ |
||||
tst-auditlogmod-1 \ |
||||
tst-auditlogmod-2 \ |
||||
tst-auditlogmod-3 \ |
||||
@@ -653,6 +655,7 @@ modules-names = \ |
||||
tst-auditmod19b \ |
||||
tst-auditmod20 \ |
||||
tst-auditmod22 \ |
||||
+ tst-auditmod23 \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
tst-deep1mod1 \ |
||||
@@ -2045,6 +2048,10 @@ tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so |
||||
$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so |
||||
tst-audit22-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
+$(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \ |
||||
+ $(objpfx)tst-audit23mod.so |
||||
+tst-audit23-ARGS = -- $(host-test-program-cmd) |
||||
+ |
||||
# tst-sonamemove links against an older implementation of the library. |
||||
LDFLAGS-tst-sonamemove-linkmod1.so = \ |
||||
-Wl,--version-script=tst-sonamemove-linkmod1.map \ |
||||
diff --git a/elf/dl-fini.c b/elf/dl-fini.c |
||||
index b789cfb9f2ac6c85..fa876da0ffa1cf97 100644 |
||||
--- a/elf/dl-fini.c |
||||
+++ b/elf/dl-fini.c |
||||
@@ -64,6 +64,10 @@ _dl_fini (void) |
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock)); |
||||
else |
||||
{ |
||||
+#ifdef SHARED |
||||
+ _dl_audit_activity_nsid (ns, LA_ACT_DELETE); |
||||
+#endif |
||||
+ |
||||
/* Now we can allocate an array to hold all the pointers and |
||||
copy the pointers in. */ |
||||
struct link_map *maps[nloaded]; |
||||
@@ -153,6 +157,10 @@ _dl_fini (void) |
||||
/* Correct the previous increment. */ |
||||
--l->l_direct_opencount; |
||||
} |
||||
+ |
||||
+#ifdef SHARED |
||||
+ _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT); |
||||
+#endif |
||||
} |
||||
} |
||||
|
||||
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c |
||||
new file mode 100644 |
||||
index 0000000000000000..4904cf1340a97ee1 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit23.c |
||||
@@ -0,0 +1,239 @@ |
||||
+/* Check for expected la_objopen and la_objeclose for all objects. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <errno.h> |
||||
+#include <getopt.h> |
||||
+#include <link.h> |
||||
+#include <limits.h> |
||||
+#include <inttypes.h> |
||||
+#include <gnu/lib-names.h> |
||||
+#include <string.h> |
||||
+#include <stdlib.h> |
||||
+#include <support/capture_subprocess.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xstdio.h> |
||||
+#include <support/xdlfcn.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+static int restart; |
||||
+#define CMDLINE_OPTIONS \ |
||||
+ { "restart", no_argument, &restart, 1 }, |
||||
+ |
||||
+static int |
||||
+handle_restart (void) |
||||
+{ |
||||
+ xdlopen ("tst-audit23mod.so", RTLD_NOW); |
||||
+ xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+startswith (const char *str, const char *pre) |
||||
+{ |
||||
+ size_t lenpre = strlen (pre); |
||||
+ size_t lenstr = strlen (str); |
||||
+ return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+is_vdso (const char *str) |
||||
+{ |
||||
+ return startswith (str, "linux-gate") |
||||
+ || startswith (str, "linux-vdso"); |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (int argc, char *argv[]) |
||||
+{ |
||||
+ /* We must have either: |
||||
+ - One or four parameters left if called initially: |
||||
+ + path to ld.so optional |
||||
+ + "--library-path" optional |
||||
+ + the library path optional |
||||
+ + the application name */ |
||||
+ if (restart) |
||||
+ return handle_restart (); |
||||
+ |
||||
+ char *spargv[9]; |
||||
+ TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv)); |
||||
+ int i = 0; |
||||
+ for (; i < argc - 1; i++) |
||||
+ spargv[i] = argv[i + 1]; |
||||
+ spargv[i++] = (char *) "--direct"; |
||||
+ spargv[i++] = (char *) "--restart"; |
||||
+ spargv[i] = NULL; |
||||
+ |
||||
+ setenv ("LD_AUDIT", "tst-auditmod23.so", 0); |
||||
+ struct support_capture_subprocess result |
||||
+ = support_capture_subprogram (spargv[0], spargv); |
||||
+ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); |
||||
+ |
||||
+ /* The expected la_objopen/la_objclose: |
||||
+ 1. executable |
||||
+ 2. loader |
||||
+ 3. libc.so |
||||
+ 4. tst-audit23mod.so |
||||
+ 5. libc.so (LM_ID_NEWLM). |
||||
+ 6. vdso (optional and ignored). */ |
||||
+ enum { max_objs = 6 }; |
||||
+ struct la_obj_t |
||||
+ { |
||||
+ char *lname; |
||||
+ uintptr_t laddr; |
||||
+ Lmid_t lmid; |
||||
+ bool closed; |
||||
+ } objs[max_objs] = { [0 ... max_objs-1] = { .closed = false } }; |
||||
+ size_t nobjs = 0; |
||||
+ |
||||
+ /* The expected namespaces are one for the audit module, one for the |
||||
+ application, and another for the dlmopen on handle_restart. */ |
||||
+ enum { max_ns = 3 }; |
||||
+ uintptr_t acts[max_ns] = { 0 }; |
||||
+ size_t nacts = 0; |
||||
+ int last_act = -1; |
||||
+ uintptr_t last_act_cookie = -1; |
||||
+ bool seen_first_objclose = false; |
||||
+ |
||||
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); |
||||
+ TEST_VERIFY (out != NULL); |
||||
+ char *buffer = NULL; |
||||
+ size_t buffer_length = 0; |
||||
+ while (xgetline (&buffer, &buffer_length, out)) |
||||
+ { |
||||
+ if (startswith (buffer, "la_activity: ")) |
||||
+ { |
||||
+ uintptr_t cookie; |
||||
+ int this_act; |
||||
+ int r = sscanf (buffer, "la_activity: %d %"SCNxPTR"", &this_act, |
||||
+ &cookie); |
||||
+ TEST_COMPARE (r, 2); |
||||
+ |
||||
+ /* The cookie identifies the object at the head of the link map, |
||||
+ so we only add a new namespace if it changes from the previous |
||||
+ one. This works since dlmopen is the last in the test body. */ |
||||
+ if (cookie != last_act_cookie && last_act_cookie != -1) |
||||
+ TEST_COMPARE (last_act, LA_ACT_CONSISTENT); |
||||
+ |
||||
+ if (this_act == LA_ACT_ADD && acts[nacts] != cookie) |
||||
+ { |
||||
+ acts[nacts++] = cookie; |
||||
+ last_act_cookie = cookie; |
||||
+ } |
||||
+ /* The LA_ACT_DELETE is called in the reverse order of LA_ACT_ADD |
||||
+ at program termination (if the tests adds a dlclose or a library |
||||
+ with extra dependencies this will need to be adapted). */ |
||||
+ else if (this_act == LA_ACT_DELETE) |
||||
+ { |
||||
+ last_act_cookie = acts[--nacts]; |
||||
+ TEST_COMPARE (acts[nacts], cookie); |
||||
+ acts[nacts] = 0; |
||||
+ } |
||||
+ else if (this_act == LA_ACT_CONSISTENT) |
||||
+ { |
||||
+ TEST_COMPARE (cookie, last_act_cookie); |
||||
+ |
||||
+ /* LA_ACT_DELETE must always be followed by an la_objclose. */ |
||||
+ if (last_act == LA_ACT_DELETE) |
||||
+ TEST_COMPARE (seen_first_objclose, true); |
||||
+ else |
||||
+ TEST_COMPARE (last_act, LA_ACT_ADD); |
||||
+ } |
||||
+ |
||||
+ last_act = this_act; |
||||
+ seen_first_objclose = false; |
||||
+ } |
||||
+ else if (startswith (buffer, "la_objopen: ")) |
||||
+ { |
||||
+ char *lname; |
||||
+ uintptr_t laddr; |
||||
+ Lmid_t lmid; |
||||
+ uintptr_t cookie; |
||||
+ int r = sscanf (buffer, "la_objopen: %"SCNxPTR" %ms %"SCNxPTR" %ld", |
||||
+ &cookie, &lname, &laddr, &lmid); |
||||
+ TEST_COMPARE (r, 4); |
||||
+ |
||||
+ /* la_objclose is not triggered by vDSO because glibc does not |
||||
+ unload it. */ |
||||
+ if (is_vdso (lname)) |
||||
+ continue; |
||||
+ if (nobjs == max_objs) |
||||
+ FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld", |
||||
+ lname, laddr, lmid); |
||||
+ objs[nobjs].lname = lname; |
||||
+ objs[nobjs].laddr = laddr; |
||||
+ objs[nobjs].lmid = lmid; |
||||
+ objs[nobjs].closed = false; |
||||
+ nobjs++; |
||||
+ |
||||
+ /* This indirectly checks that la_objopen always comes before |
||||
+ la_objclose btween la_activity calls. */ |
||||
+ seen_first_objclose = false; |
||||
+ } |
||||
+ else if (startswith (buffer, "la_objclose: ")) |
||||
+ { |
||||
+ char *lname; |
||||
+ uintptr_t laddr; |
||||
+ Lmid_t lmid; |
||||
+ uintptr_t cookie; |
||||
+ int r = sscanf (buffer, "la_objclose: %"SCNxPTR" %ms %"SCNxPTR" %ld", |
||||
+ &cookie, &lname, &laddr, &lmid); |
||||
+ TEST_COMPARE (r, 4); |
||||
+ |
||||
+ for (size_t i = 0; i < nobjs; i++) |
||||
+ { |
||||
+ if (strcmp (lname, objs[i].lname) == 0 && lmid == objs[i].lmid) |
||||
+ { |
||||
+ TEST_COMPARE (objs[i].closed, false); |
||||
+ objs[i].closed = true; |
||||
+ break; |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ /* la_objclose should be called after la_activity(LA_ACT_DELETE) for |
||||
+ the closed object's namespace. */ |
||||
+ TEST_COMPARE (last_act, LA_ACT_DELETE); |
||||
+ if (!seen_first_objclose) |
||||
+ { |
||||
+ TEST_COMPARE (last_act_cookie, cookie); |
||||
+ seen_first_objclose = true; |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ for (size_t i = 0; i < nobjs; i++) |
||||
+ { |
||||
+ TEST_COMPARE (objs[i].closed, true); |
||||
+ free (objs[i].lname); |
||||
+ } |
||||
+ |
||||
+ /* la_activity(LA_ACT_CONSISTENT) should be the last callback received. |
||||
+ Since only one link map may be not-CONSISTENT at a time, this also |
||||
+ ensures la_activity(LA_ACT_CONSISTENT) is the last callback received |
||||
+ for every namespace. */ |
||||
+ TEST_COMPARE (last_act, LA_ACT_CONSISTENT); |
||||
+ |
||||
+ free (buffer); |
||||
+ xfclose (out); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#define TEST_FUNCTION_ARGV do_test |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-audit23mod.c b/elf/tst-audit23mod.c |
||||
new file mode 100644 |
||||
index 0000000000000000..30315687037d25e8 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit23mod.c |
||||
@@ -0,0 +1,23 @@ |
||||
+/* Extra module for tst-audit23 |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+int |
||||
+foo (void) |
||||
+{ |
||||
+ return 0; |
||||
+} |
||||
diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c |
||||
new file mode 100644 |
||||
index 0000000000000000..d7c60d7a5cbc4f8a |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod23.c |
||||
@@ -0,0 +1,74 @@ |
||||
+/* Audit module loaded by tst-audit23. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <link.h> |
||||
+#include <inttypes.h> |
||||
+#include <stdlib.h> |
||||
+#include <stdio.h> |
||||
+#include <string.h> |
||||
+#include <sys/auxv.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int version) |
||||
+{ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+struct map_desc_t |
||||
+{ |
||||
+ char *lname; |
||||
+ uintptr_t laddr; |
||||
+ Lmid_t lmid; |
||||
+}; |
||||
+ |
||||
+void |
||||
+la_activity (uintptr_t *cookie, unsigned int flag) |
||||
+{ |
||||
+ fprintf (stderr, "%s: %d %"PRIxPTR"\n", __func__, flag, (uintptr_t) cookie); |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) |
||||
+{ |
||||
+ const char *l_name = map->l_name[0] == '\0' ? "mainapp" : map->l_name; |
||||
+ fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, |
||||
+ (uintptr_t) cookie, l_name, map->l_addr, lmid); |
||||
+ |
||||
+ struct map_desc_t *map_desc = malloc (sizeof (struct map_desc_t)); |
||||
+ if (map_desc == NULL) |
||||
+ abort (); |
||||
+ |
||||
+ map_desc->lname = strdup (l_name); |
||||
+ map_desc->laddr = map->l_addr; |
||||
+ map_desc->lmid = lmid; |
||||
+ |
||||
+ *cookie = (uintptr_t) map_desc; |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objclose (uintptr_t *cookie) |
||||
+{ |
||||
+ struct map_desc_t *map_desc = (struct map_desc_t *) *cookie; |
||||
+ fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, |
||||
+ (uintptr_t) cookie, map_desc->lname, map_desc->laddr, |
||||
+ map_desc->lmid); |
||||
+ |
||||
+ return 0; |
||||
+} |
@ -0,0 +1,299 @@
@@ -0,0 +1,299 @@
|
||||
commit efb21b5fb27fbad447d9f242436fb591870f0045 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Mon Jan 24 10:46:16 2022 -0300 |
||||
|
||||
elf: Fix initial-exec TLS access on audit modules (BZ #28096) |
||||
|
||||
For audit modules and dependencies with initial-exec TLS, we can not |
||||
set the initial TLS image on default loader initialization because it |
||||
would already be set by the audit setup. However, subsequent thread |
||||
creation would need to follow the default behaviour. |
||||
|
||||
This patch fixes it by setting l_auditing link_map field not only |
||||
for the audit modules, but also for all its dependencies. This is |
||||
used on _dl_allocate_tls_init to avoid the static TLS initialization |
||||
at load time. |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
Tested-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 254d3d5aef2fd8430c469e1938209ac100ebf132) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 407aaeaeb8c84020..3ccf78f62985e2d0 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -367,6 +367,7 @@ tests += \ |
||||
tst-audit18 \ |
||||
tst-audit19b \ |
||||
tst-audit20 \ |
||||
+ tst-audit21 \ |
||||
tst-audit22 \ |
||||
tst-audit23 \ |
||||
tst-auditmany \ |
||||
@@ -654,6 +655,8 @@ modules-names = \ |
||||
tst-auditmod19a \ |
||||
tst-auditmod19b \ |
||||
tst-auditmod20 \ |
||||
+ tst-auditmod21a \ |
||||
+ tst-auditmod21b \ |
||||
tst-auditmod22 \ |
||||
tst-auditmod23 \ |
||||
tst-auxvalmod \ |
||||
@@ -2045,6 +2048,11 @@ tst-audit19b-ARGS = -- $(host-test-program-cmd) |
||||
$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so |
||||
tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so |
||||
|
||||
+$(objpfx)tst-audit21: $(shared-thread-library) |
||||
+$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so |
||||
+$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so |
||||
+tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so |
||||
+ |
||||
$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so |
||||
tst-audit22-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c |
||||
index e2012d0cd515103b..fab6546e2d31edd4 100644 |
||||
--- a/elf/dl-tls.c |
||||
+++ b/elf/dl-tls.c |
||||
@@ -519,8 +519,12 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid) |
||||
} |
||||
|
||||
|
||||
+/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage |
||||
+ for the TLS space. The DTV may be resized, and so this function may |
||||
+ call malloc to allocate that space. The loader's GL(dl_load_tls_lock) |
||||
+ is taken when manipulating global TLS-related data in the loader. */ |
||||
void * |
||||
-_dl_allocate_tls_init (void *result) |
||||
+_dl_allocate_tls_init (void *result, bool init_tls) |
||||
{ |
||||
if (result == NULL) |
||||
/* The memory allocation failed. */ |
||||
@@ -593,7 +597,14 @@ _dl_allocate_tls_init (void *result) |
||||
some platforms use in static programs requires it. */ |
||||
dtv[map->l_tls_modid].pointer.val = dest; |
||||
|
||||
- /* Copy the initialization image and clear the BSS part. */ |
||||
+ /* Copy the initialization image and clear the BSS part. For |
||||
+ audit modules or dependencies with initial-exec TLS, we can not |
||||
+ set the initial TLS image on default loader initialization |
||||
+ because it would already be set by the audit setup. However, |
||||
+ subsequent thread creation would need to follow the default |
||||
+ behaviour. */ |
||||
+ if (map->l_ns != LM_ID_BASE && !init_tls) |
||||
+ continue; |
||||
memset (__mempcpy (dest, map->l_tls_initimage, |
||||
map->l_tls_initimage_size), '\0', |
||||
map->l_tls_blocksize - map->l_tls_initimage_size); |
||||
@@ -620,7 +631,7 @@ _dl_allocate_tls (void *mem) |
||||
{ |
||||
return _dl_allocate_tls_init (mem == NULL |
||||
? _dl_allocate_tls_storage () |
||||
- : allocate_dtv (mem)); |
||||
+ : allocate_dtv (mem), true); |
||||
} |
||||
rtld_hidden_def (_dl_allocate_tls) |
||||
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index b089e5cf4740443e..26c6fb6479c9008c 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -2429,7 +2429,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
into the main thread's TLS area, which we allocated above. |
||||
Note: thread-local variables must only be accessed after completing |
||||
the next step. */ |
||||
- _dl_allocate_tls_init (tcbp); |
||||
+ _dl_allocate_tls_init (tcbp, false); |
||||
|
||||
/* And finally install it for the main thread. */ |
||||
if (! tls_init_tp_called) |
||||
diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c |
||||
new file mode 100644 |
||||
index 0000000000000000..3a47ab64d44421ee |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit21.c |
||||
@@ -0,0 +1,42 @@ |
||||
+/* Check LD_AUDIT with static TLS. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <ctype.h> |
||||
+#include <support/xthread.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+static volatile __thread int out __attribute__ ((tls_model ("initial-exec"))); |
||||
+ |
||||
+static void * |
||||
+tf (void *arg) |
||||
+{ |
||||
+ TEST_COMPARE (out, 0); |
||||
+ out = isspace (' '); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+int main (int argc, char *argv[]) |
||||
+{ |
||||
+ TEST_COMPARE (out, 0); |
||||
+ out = isspace (' '); |
||||
+ |
||||
+ pthread_t t = xpthread_create (NULL, tf, NULL); |
||||
+ xpthread_join (t); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c |
||||
new file mode 100644 |
||||
index 0000000000000000..f6d51b5c0531c49d |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod21a.c |
||||
@@ -0,0 +1,80 @@ |
||||
+/* Check LD_AUDIT with static TLS. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <ctype.h> |
||||
+#include <stdlib.h> |
||||
+#include <link.h> |
||||
+ |
||||
+#define tls_ie __attribute__ ((tls_model ("initial-exec"))) |
||||
+ |
||||
+__thread int tls_var0 tls_ie; |
||||
+__thread int tls_var1 tls_ie = 0x10; |
||||
+ |
||||
+/* Defined at tst-auditmod21b.so */ |
||||
+extern __thread int tls_var2; |
||||
+extern __thread int tls_var3; |
||||
+ |
||||
+static volatile int out; |
||||
+ |
||||
+static void |
||||
+call_libc (void) |
||||
+{ |
||||
+ /* isspace accesses the initial-exec glibc TLS variables, which are |
||||
+ setup in glibc initialization. */ |
||||
+ out = isspace (' '); |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int v) |
||||
+{ |
||||
+ tls_var0 = 0x1; |
||||
+ if (tls_var1 != 0x10) |
||||
+ abort (); |
||||
+ tls_var1 = 0x20; |
||||
+ |
||||
+ tls_var2 = 0x2; |
||||
+ if (tls_var3 != 0x20) |
||||
+ abort (); |
||||
+ tls_var3 = 0x40; |
||||
+ |
||||
+ call_libc (); |
||||
+ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+unsigned int |
||||
+la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie) |
||||
+{ |
||||
+ call_libc (); |
||||
+ *cookie = (uintptr_t) map; |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+void |
||||
+la_activity (uintptr_t* cookie, unsigned int flag) |
||||
+{ |
||||
+ if (tls_var0 != 0x1 || tls_var1 != 0x20) |
||||
+ abort (); |
||||
+ call_libc (); |
||||
+} |
||||
+ |
||||
+void |
||||
+la_preinit (uintptr_t* cookie) |
||||
+{ |
||||
+ call_libc (); |
||||
+} |
||||
diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c |
||||
new file mode 100644 |
||||
index 0000000000000000..6ba5335b7514c674 |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod21b.c |
||||
@@ -0,0 +1,22 @@ |
||||
+/* Check LD_AUDIT with static TLS. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#define tls_ie __attribute__ ((tls_model ("initial-exec"))) |
||||
+ |
||||
+__thread int tls_var2 tls_ie; |
||||
+__thread int tls_var3 tls_ie = 0x20; |
||||
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c |
||||
index 50065bc9bd8a28e5..554a721f814b53c4 100644 |
||||
--- a/nptl/allocatestack.c |
||||
+++ b/nptl/allocatestack.c |
||||
@@ -139,7 +139,7 @@ get_cached_stack (size_t *sizep, void **memp) |
||||
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); |
||||
|
||||
/* Re-initialize the TLS. */ |
||||
- _dl_allocate_tls_init (TLS_TPADJ (result)); |
||||
+ _dl_allocate_tls_init (TLS_TPADJ (result), true); |
||||
|
||||
return result; |
||||
} |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 686f0a7b9709eb10..a56060d0204cc453 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1254,7 +1254,7 @@ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; |
||||
/* These are internal entry points to the two halves of _dl_allocate_tls, |
||||
only used within rtld.c itself at startup time. */ |
||||
extern void *_dl_allocate_tls_storage (void) attribute_hidden; |
||||
-extern void *_dl_allocate_tls_init (void *); |
||||
+extern void *_dl_allocate_tls_init (void *, bool); |
||||
rtld_hidden_proto (_dl_allocate_tls_init) |
||||
|
||||
/* Deallocate memory allocated with _dl_allocate_tls. */ |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
commit 165e7ad459fbba2f89708fba04a55bb3981e884c |
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
Date: Wed Feb 2 14:03:58 2022 +0000 |
||||
|
||||
Fix elf/tst-audit25a with default bind now toolchains |
||||
|
||||
This test relies on lazy binding for the executable so request that |
||||
explicitly in case the toolchain defaults to bind now. |
||||
|
||||
(cherry picked from commit 80a08d0faa9b224019f895800c4d97de4e23e1aa) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 0ab3e885f5e35671..9e4e056938a75ddb 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -2133,6 +2133,7 @@ $(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \ |
||||
$(objpfx)tst-audit25mod2.so \ |
||||
$(objpfx)tst-audit25mod3.so \ |
||||
$(objpfx)tst-audit25mod4.so |
||||
+LDFLAGS-tst-audit25a = -Wl,-z,lazy |
||||
$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so |
||||
LDFLAGS-tst-audit25mod1.so = -Wl,-z,now |
||||
$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit aabdad371f44defc6046aabdc96af7782a2e94be |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Sun Feb 6 11:12:24 2022 -0800 |
||||
|
||||
elf: Replace tst-audit24bmod2.so with tst-audit24bmod2 |
||||
|
||||
Replace tst-audit24bmod2.so with tst-audit24bmod2 to silence: |
||||
|
||||
make[2]: Entering directory '/export/gnu/import/git/gitlab/x86-glibc/elf' |
||||
Makefile:2201: warning: overriding recipe for target '/export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/elf/tst-audit24bmod2.so' |
||||
../Makerules:765: warning: ignoring old recipe for target '/export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/elf/tst-audit24bmod2.so' |
||||
|
||||
(cherry picked from commit fa7ad1df1915c8a62f50e3a5b7e10f9c7118cd7f) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 9e4e056938a75ddb..57059293d0bc86cb 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -888,7 +888,7 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) |
||||
# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special |
||||
# rules. |
||||
modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod \ |
||||
- tst-audit24bmod1 tst-audit24bmod2.so |
||||
+ tst-audit24bmod1 tst-audit24bmod2 |
||||
|
||||
tests += $(tests-static) |
||||
|
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
commit 4dca2d3a7b43bf99bd6a567870a3144af4e763ef |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Fri Feb 4 15:54:59 2022 -0300 |
||||
|
||||
hppa: Fix bind-now audit (BZ #28857) |
||||
|
||||
On hppa, a function pointer returned by la_symbind is actually a function |
||||
descriptor has the plabel bit set (bit 30). This must be cleared to get |
||||
the actual address of the descriptor. If the descriptor has been bound, |
||||
the first word of the descriptor is the physical address of theA function, |
||||
otherwise, the first word of the descriptor points to a trampoline in the |
||||
PLT. |
||||
|
||||
This patch also adds a workaround on tests because on hppa (and it seems |
||||
to be the only ABI I have see it), some shared library adds a dynamic PLT |
||||
relocation to am empty symbol name: |
||||
|
||||
$ readelf -r elf/tst-audit25mod1.so |
||||
[...] |
||||
Relocation section '.rela.plt' at offset 0x464 contains 6 entries: |
||||
Offset Info Type Sym.Value Sym. Name + Addend |
||||
00002008 00000081 R_PARISC_IPLT 508 |
||||
[...] |
||||
|
||||
It breaks some assumptions on the test, where a symbol with an empty |
||||
name ("") is passed on la_symbind. |
||||
|
||||
Checked on x86_64-linux-gnu and hppa-linux-gnu. |
||||
|
||||
(cherry picked from commit 9e94f57484a2aba0fe67ea2059b5843f651887c2) |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 57059293d0bc86cb..3e17a0706f5ec2df 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -2116,7 +2116,7 @@ $(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so |
||||
$(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \ |
||||
$(objpfx)tst-audit24amod2.so |
||||
tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so |
||||
-LDFLAGS-tst-audit24b = -Wl,-z,lazy |
||||
+LDFLAGS-tst-audit24c = -Wl,-z,lazy |
||||
|
||||
$(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so |
||||
$(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \ |
||||
diff --git a/elf/dl-audit.c b/elf/dl-audit.c |
||||
index 72a50717ef60a357..ec9b032eae37c103 100644 |
||||
--- a/elf/dl-audit.c |
||||
+++ b/elf/dl-audit.c |
||||
@@ -257,7 +257,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, |
||||
reloc_result->flags = flags; |
||||
} |
||||
|
||||
- DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); |
||||
+ if (flags & LA_SYMB_ALTVALUE) |
||||
+ DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); |
||||
} |
||||
|
||||
void |
||||
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c |
||||
index d8e88f3984af1707..3075dfae2fd3d288 100644 |
||||
--- a/elf/tst-auditmod24a.c |
||||
+++ b/elf/tst-auditmod24a.c |
||||
@@ -110,5 +110,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, |
||||
return sym->st_value; |
||||
} |
||||
|
||||
- abort (); |
||||
+ if (symname[0] != '\0') |
||||
+ abort (); |
||||
+ return sym->st_value; |
||||
} |
||||
diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c |
||||
index 8c803ecc0a48f21b..badc6be451ee0357 100644 |
||||
--- a/elf/tst-auditmod24d.c |
||||
+++ b/elf/tst-auditmod24d.c |
||||
@@ -116,5 +116,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, |
||||
} |
||||
} |
||||
|
||||
- abort (); |
||||
+ if (symname[0] != '\0') |
||||
+ abort (); |
||||
+ return sym->st_value; |
||||
} |
||||
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c |
||||
index 526f5c54bc2c3b8c..20640a8daf346b5f 100644 |
||||
--- a/elf/tst-auditmod25.c |
||||
+++ b/elf/tst-auditmod25.c |
||||
@@ -72,7 +72,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, |
||||
unsigned int *flags, const char *symname) |
||||
#endif |
||||
{ |
||||
- if (*refcook != -1 && *defcook != -1) |
||||
+ if (*refcook != -1 && *defcook != -1 && symname[0] != '\0') |
||||
fprintf (stderr, "la_symbind: %s %u\n", symname, |
||||
*flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0); |
||||
return sym->st_value; |
||||
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h |
||||
index f4f00714fa158e18..92fd0b7c844713ce 100644 |
||||
--- a/sysdeps/hppa/dl-lookupcfg.h |
||||
+++ b/sysdeps/hppa/dl-lookupcfg.h |
||||
@@ -80,7 +80,9 @@ void attribute_hidden _dl_unmap (struct link_map *map); |
||||
/* Extract the code address from a fixup value */ |
||||
#define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip) |
||||
#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) |
||||
-#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) |
||||
+/* Clear the plabel bit to get the actual address of the descriptor. */ |
||||
+#define DL_FIXUP_ADDR_VALUE(addr) \ |
||||
+ (*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2)) |
||||
#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) |
||||
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ |
||||
- (*value) = *(struct fdesc *) (st_value) |
||||
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ |
||||
+ *(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2) |
@ -0,0 +1,242 @@
@@ -0,0 +1,242 @@
|
||||
commit 0c03cb54c808173d8e7ba96f6152dfcf627ac496 |
||||
Author: Stefan Liebler <stli@linux.ibm.com> |
||||
Date: Wed Apr 13 14:36:09 2022 +0200 |
||||
|
||||
S390: Add new s390 platform z16. |
||||
|
||||
The new IBM z16 is added to platform string array. |
||||
The macro _DL_PLATFORMS_COUNT is incremented. |
||||
|
||||
_dl_hwcaps_subdir is extended by "z16" if HWCAP_S390_VXRS_PDE2 |
||||
is set. HWCAP_S390_NNPA is not tested in _dl_hwcaps_subdirs_active |
||||
as those instructions may be replaced or removed in future. |
||||
|
||||
tst-glibc-hwcaps.c is extended in order to test z16 via new marker5. |
||||
|
||||
A fatal glibc error is dumped if glibc was build with architecture |
||||
level set for z16, but run on an older machine. (See dl-hwcap-check.h) |
||||
|
||||
(cherry picked from commit 2376944b9e5c0364b9fb473e4d8dabca31b57167) |
||||
|
||||
Conflicts: |
||||
sysdeps/s390/s390-64/dl-hwcap-check.h - Use GCCMACRO__ARCH__. |
||||
- Backported f01d482f0355a7029d0715ace0ccf3323e7e94bc requires it. |
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 3e17a0706f5ec2df..8e2dd91c583f9a62 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -571,6 +571,11 @@ modules-names = \ |
||||
libmarkermod4-2 \ |
||||
libmarkermod4-3 \ |
||||
libmarkermod4-4 \ |
||||
+ libmarkermod5-1 \ |
||||
+ libmarkermod5-2 \ |
||||
+ libmarkermod5-3 \ |
||||
+ libmarkermod5-4 \ |
||||
+ libmarkermod5-5 \ |
||||
ltglobmod1 \ |
||||
ltglobmod2 \ |
||||
neededobj1 \ |
||||
@@ -2412,6 +2417,7 @@ LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so |
||||
LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so |
||||
LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so |
||||
LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so |
||||
+LDFLAGS-libmarkermod5-1.so += -Wl,-soname,libmarkermod5.so |
||||
$(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c |
||||
$(compile-command.c) \ |
||||
-DMARKER=marker$(firstword $(subst -, ,$*)) \ |
||||
@@ -2424,6 +2430,8 @@ $(objpfx)libmarkermod3.so: $(objpfx)libmarkermod3-1.so |
||||
cp $< $@ |
||||
$(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so |
||||
cp $< $@ |
||||
+$(objpfx)libmarkermod5.so: $(objpfx)libmarkermod5-1.so |
||||
+ cp $< $@ |
||||
|
||||
# tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is |
||||
# preferred over auto-detected subdirectories. |
||||
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script |
||||
index c3271f61f9e50f2e..d58fc8c5de3c5198 100644 |
||||
--- a/elf/tst-glibc-hwcaps-cache.script |
||||
+++ b/elf/tst-glibc-hwcaps-cache.script |
||||
@@ -4,6 +4,7 @@ |
||||
cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so |
||||
cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so |
||||
cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so |
||||
+cp $B/elf/libmarkermod5-1.so $L/libmarkermod5.so |
||||
|
||||
mkdirp 0770 $L/glibc-hwcaps/power9 |
||||
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so |
||||
@@ -20,6 +21,11 @@ mkdirp 0770 $L/glibc-hwcaps/z15 |
||||
cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/z13/libmarkermod4.so |
||||
cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/z14/libmarkermod4.so |
||||
cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/z15/libmarkermod4.so |
||||
+mkdirp 0770 $L/glibc-hwcaps/z16 |
||||
+cp $B/elf/libmarkermod5-2.so $L/glibc-hwcaps/z13/libmarkermod5.so |
||||
+cp $B/elf/libmarkermod5-3.so $L/glibc-hwcaps/z14/libmarkermod5.so |
||||
+cp $B/elf/libmarkermod5-4.so $L/glibc-hwcaps/z15/libmarkermod5.so |
||||
+cp $B/elf/libmarkermod5-5.so $L/glibc-hwcaps/z16/libmarkermod5.so |
||||
|
||||
mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 |
||||
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so |
||||
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c |
||||
index 155f0bd99eccb3f9..755b54ff13a0fa2f 100644 |
||||
--- a/sysdeps/s390/dl-procinfo.c |
||||
+++ b/sysdeps/s390/dl-procinfo.c |
||||
@@ -64,11 +64,12 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[23][9] |
||||
#if !defined PROCINFO_DECL && defined SHARED |
||||
._dl_s390_platforms |
||||
#else |
||||
-PROCINFO_CLASS const char _dl_s390_platforms[10][7] |
||||
+PROCINFO_CLASS const char _dl_s390_platforms[11][7] |
||||
#endif |
||||
#ifndef PROCINFO_DECL |
||||
= { |
||||
- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15" |
||||
+ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15", |
||||
+ "z16" |
||||
} |
||||
#endif |
||||
#if !defined SHARED || defined PROCINFO_DECL |
||||
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h |
||||
index e4e3e334a5b3d47c..d44e1dd97441bd90 100644 |
||||
--- a/sysdeps/s390/dl-procinfo.h |
||||
+++ b/sysdeps/s390/dl-procinfo.h |
||||
@@ -23,7 +23,7 @@ |
||||
|
||||
#define _DL_HWCAP_COUNT 23 |
||||
|
||||
-#define _DL_PLATFORMS_COUNT 10 |
||||
+#define _DL_PLATFORMS_COUNT 11 |
||||
|
||||
/* The kernel provides up to 32 capability bits with elf_hwcap. */ |
||||
#define _DL_FIRST_PLATFORM 32 |
||||
diff --git a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile |
||||
index e5da26871c862e63..66ed844e68df5159 100644 |
||||
--- a/sysdeps/s390/s390-64/Makefile |
||||
+++ b/sysdeps/s390/s390-64/Makefile |
||||
@@ -7,8 +7,11 @@ CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused |
||||
CFLAGS-dl-load.c += -Wno-unused |
||||
CFLAGS-dl-reloc.c += -Wno-unused |
||||
|
||||
-$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \ |
||||
- $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so |
||||
+$(objpfx)tst-glibc-hwcaps: \ |
||||
+ $(objpfx)libmarkermod2-1.so \ |
||||
+ $(objpfx)libmarkermod3-1.so \ |
||||
+ $(objpfx)libmarkermod4-1.so \ |
||||
+ $(objpfx)libmarkermod5-1.so |
||||
$(objpfx)tst-glibc-hwcaps.out: \ |
||||
$(objpfx)libmarkermod2.so \ |
||||
$(objpfx)glibc-hwcaps/z13/libmarkermod2.so \ |
||||
@@ -19,6 +22,11 @@ $(objpfx)tst-glibc-hwcaps.out: \ |
||||
$(objpfx)glibc-hwcaps/z13/libmarkermod4.so \ |
||||
$(objpfx)glibc-hwcaps/z14/libmarkermod4.so \ |
||||
$(objpfx)glibc-hwcaps/z15/libmarkermod4.so \ |
||||
+ $(objpfx)libmarkermod5.so \ |
||||
+ $(objpfx)glibc-hwcaps/z13/libmarkermod5.so \ |
||||
+ $(objpfx)glibc-hwcaps/z14/libmarkermod5.so \ |
||||
+ $(objpfx)glibc-hwcaps/z15/libmarkermod5.so \ |
||||
+ $(objpfx)glibc-hwcaps/z16/libmarkermod5.so |
||||
|
||||
$(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so |
||||
$(make-target-directory) |
||||
@@ -38,6 +46,19 @@ $(objpfx)glibc-hwcaps/z14/libmarkermod4.so: $(objpfx)libmarkermod4-3.so |
||||
$(objpfx)glibc-hwcaps/z15/libmarkermod4.so: $(objpfx)libmarkermod4-4.so |
||||
$(make-target-directory) |
||||
cp $< $@ |
||||
+$(objpfx)glibc-hwcaps/z13/libmarkermod5.so: $(objpfx)libmarkermod5-2.so |
||||
+ $(make-target-directory) |
||||
+ cp $< $@ |
||||
+$(objpfx)glibc-hwcaps/z14/libmarkermod5.so: $(objpfx)libmarkermod5-3.so |
||||
+ $(make-target-directory) |
||||
+ cp $< $@ |
||||
+$(objpfx)glibc-hwcaps/z15/libmarkermod5.so: $(objpfx)libmarkermod5-4.so |
||||
+ $(make-target-directory) |
||||
+ cp $< $@ |
||||
+$(objpfx)glibc-hwcaps/z16/libmarkermod5.so: $(objpfx)libmarkermod5-5.so |
||||
+ $(make-target-directory) |
||||
+ cp $< $@ |
||||
+ |
||||
|
||||
ifeq (no,$(build-hardcoded-path-in-tests)) |
||||
# This is an ld.so.cache test, and RPATH/RUNPATH in the executable |
||||
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h |
||||
index 27f7e245b1d1a9e9..52c609571b32f4ab 100644 |
||||
--- a/sysdeps/s390/s390-64/dl-hwcap-check.h |
||||
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h |
||||
@@ -26,7 +26,11 @@ static inline void |
||||
dl_hwcap_check (void) |
||||
{ |
||||
#if defined __ARCH__ |
||||
-# if GCCMACRO__ARCH__ >= 13 |
||||
+# if GCCMACRO__ARCH__ >= 14 |
||||
+ if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_PDE2)) |
||||
+ _dl_fatal_printf ("\ |
||||
+Fatal glibc error: CPU lacks VXRS_PDE2 support (z16 or later required)\n"); |
||||
+# elif GCCMACRO__ARCH__ >= 13 |
||||
if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_EXT2)) |
||||
_dl_fatal_printf ("\ |
||||
Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n"); |
||||
diff --git a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c |
||||
index b9d094f3d73c2d7a..187d732d560c4a62 100644 |
||||
--- a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c |
||||
+++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c |
||||
@@ -19,8 +19,8 @@ |
||||
#include <dl-hwcaps.h> |
||||
#include <ldsodefs.h> |
||||
|
||||
-const char _dl_hwcaps_subdirs[] = "z15:z14:z13"; |
||||
-enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */ |
||||
+const char _dl_hwcaps_subdirs[] = "z16:z15:z14:z13"; |
||||
+enum { subdirs_count = 4 }; /* Number of components in _dl_hwcaps_subdirs. */ |
||||
|
||||
uint32_t |
||||
_dl_hwcaps_subdirs_active (void) |
||||
@@ -50,5 +50,12 @@ _dl_hwcaps_subdirs_active (void) |
||||
return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); |
||||
++active; |
||||
|
||||
+ /* z16. |
||||
+ Note: We do not list HWCAP_S390_NNPA here as, according to the Principles of |
||||
+ Operation, those instructions may be replaced or removed in future. */ |
||||
+ if (!(GLRO (dl_hwcap) & HWCAP_S390_VXRS_PDE2)) |
||||
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); |
||||
+ ++active; |
||||
+ |
||||
return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); |
||||
} |
||||
diff --git a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c |
||||
index 02397a478c552516..f3b8ef3dec80d2d1 100644 |
||||
--- a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c |
||||
+++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c |
||||
@@ -25,6 +25,7 @@ |
||||
extern int marker2 (void); |
||||
extern int marker3 (void); |
||||
extern int marker4 (void); |
||||
+extern int marker5 (void); |
||||
|
||||
/* Return the arch level, 10 for the baseline libmarkermod*.so's. */ |
||||
static int |
||||
@@ -63,9 +64,11 @@ compute_level (void) |
||||
return 12; |
||||
if (strcmp (platform, "z15") == 0) |
||||
return 13; |
||||
+ if (strcmp (platform, "z16") == 0) |
||||
+ return 14; |
||||
printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform); |
||||
- /* Assume that the new platform supports z15. */ |
||||
- return 13; |
||||
+ /* Assume that the new platform supports z16. */ |
||||
+ return 14; |
||||
} |
||||
|
||||
static int |
||||
@@ -76,6 +79,7 @@ do_test (void) |
||||
TEST_COMPARE (marker2 (), MIN (level - 9, 2)); |
||||
TEST_COMPARE (marker3 (), MIN (level - 9, 3)); |
||||
TEST_COMPARE (marker4 (), MIN (level - 9, 4)); |
||||
+ TEST_COMPARE (marker5 (), MIN (level - 9, 5)); |
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,834 @@
@@ -0,0 +1,834 @@
|
||||
commit 290db09546b260a30137d03ce97a857e6f15b648 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Apr 6 12:24:42 2022 -0300 |
||||
|
||||
nptl: Handle spurious EINTR when thread cancellation is disabled (BZ#29029) |
||||
|
||||
Some Linux interfaces never restart after being interrupted by a signal |
||||
handler, regardless of the use of SA_RESTART [1]. It means that for |
||||
pthread cancellation, if the target thread disables cancellation with |
||||
pthread_setcancelstate and calls such interfaces (like poll or select), |
||||
it should not see spurious EINTR failures due the internal SIGCANCEL. |
||||
|
||||
However recent changes made pthread_cancel to always sent the internal |
||||
signal, regardless of the target thread cancellation status or type. |
||||
To fix it, the previous semantic is restored, where the cancel signal |
||||
is only sent if the target thread has cancelation enabled in |
||||
asynchronous mode. |
||||
|
||||
The cancel state and cancel type is moved back to cancelhandling |
||||
and atomic operation are used to synchronize between threads. The |
||||
patch essentially revert the following commits: |
||||
|
||||
8c1c0aae20 nptl: Move cancel type out of cancelhandling |
||||
2b51742531 nptl: Move cancel state out of cancelhandling |
||||
26cfbb7162 nptl: Remove CANCELING_BITMASK |
||||
|
||||
However I changed the atomic operation to follow the internal C11 |
||||
semantic and removed the MACRO usage, it simplifies a bit the |
||||
resulting code (and removes another usage of the old atomic macros). |
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, |
||||
and powerpc64-linux-gnu. |
||||
|
||||
[1] https://man7.org/linux/man-pages/man7/signal.7.html |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
Tested-by: Aurelien Jarno <aurelien@aurel32.net> |
||||
|
||||
(cherry-picked from commit 404656009b459658138ed1bd18f3c6cf3863e6a6) |
||||
|
||||
diff --git a/manual/process.texi b/manual/process.texi |
||||
index 28c9531f4294f56e..9307379194c6f666 100644 |
||||
--- a/manual/process.texi |
||||
+++ b/manual/process.texi |
||||
@@ -68,8 +68,7 @@ until the subprogram terminates before you can do anything else. |
||||
@c CLEANUP_HANDLER @ascuplugin @ascuheap @acsmem |
||||
@c libc_cleanup_region_start @ascuplugin @ascuheap @acsmem |
||||
@c pthread_cleanup_push_defer @ascuplugin @ascuheap @acsmem |
||||
-@c __pthread_testcancel @ascuplugin @ascuheap @acsmem |
||||
-@c CANCEL_ENABLED_AND_CANCELED ok |
||||
+@c cancel_enabled_and_canceled @ascuplugin @ascuheap @acsmem |
||||
@c do_cancel @ascuplugin @ascuheap @acsmem |
||||
@c cancel_handler ok |
||||
@c kill syscall ok |
||||
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c |
||||
index 554a721f814b53c4..96101753ec2f4323 100644 |
||||
--- a/nptl/allocatestack.c |
||||
+++ b/nptl/allocatestack.c |
||||
@@ -120,8 +120,6 @@ get_cached_stack (size_t *sizep, void **memp) |
||||
|
||||
/* Cancellation handling is back to the default. */ |
||||
result->cancelhandling = 0; |
||||
- result->cancelstate = PTHREAD_CANCEL_ENABLE; |
||||
- result->canceltype = PTHREAD_CANCEL_DEFERRED; |
||||
result->cleanup = NULL; |
||||
result->setup_failed = 0; |
||||
|
||||
diff --git a/nptl/cancellation.c b/nptl/cancellation.c |
||||
index 05962784d51fb98b..e97d56f97d7a5698 100644 |
||||
--- a/nptl/cancellation.c |
||||
+++ b/nptl/cancellation.c |
||||
@@ -31,19 +31,26 @@ int |
||||
__pthread_enable_asynccancel (void) |
||||
{ |
||||
struct pthread *self = THREAD_SELF; |
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling); |
||||
|
||||
- int oldval = THREAD_GETMEM (self, canceltype); |
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); |
||||
+ while (1) |
||||
+ { |
||||
+ int newval = oldval | CANCELTYPE_BITMASK; |
||||
|
||||
- int ch = THREAD_GETMEM (self, cancelhandling); |
||||
+ if (newval == oldval) |
||||
+ break; |
||||
|
||||
- if (self->cancelstate == PTHREAD_CANCEL_ENABLE |
||||
- && (ch & CANCELED_BITMASK) |
||||
- && !(ch & EXITING_BITMASK) |
||||
- && !(ch & TERMINATED_BITMASK)) |
||||
- { |
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED); |
||||
- __do_cancel (); |
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &oldval, newval)) |
||||
+ { |
||||
+ if (cancel_enabled_and_canceled_and_async (newval)) |
||||
+ { |
||||
+ self->result = PTHREAD_CANCELED; |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ |
||||
+ break; |
||||
+ } |
||||
} |
||||
|
||||
return oldval; |
||||
@@ -57,10 +64,29 @@ __pthread_disable_asynccancel (int oldtype) |
||||
{ |
||||
/* If asynchronous cancellation was enabled before we do not have |
||||
anything to do. */ |
||||
- if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
+ if (oldtype & CANCELTYPE_BITMASK) |
||||
return; |
||||
|
||||
struct pthread *self = THREAD_SELF; |
||||
- self->canceltype = PTHREAD_CANCEL_DEFERRED; |
||||
+ int newval; |
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling); |
||||
+ do |
||||
+ { |
||||
+ newval = oldval & ~CANCELTYPE_BITMASK; |
||||
+ } |
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &oldval, newval)); |
||||
+ |
||||
+ /* We cannot return when we are being canceled. Upon return the |
||||
+ thread might be things which would have to be undone. The |
||||
+ following loop should loop until the cancellation signal is |
||||
+ delivered. */ |
||||
+ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK)) |
||||
+ == CANCELING_BITMASK)) |
||||
+ { |
||||
+ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval, |
||||
+ FUTEX_PRIVATE); |
||||
+ newval = atomic_load_relaxed (&self->cancelhandling); |
||||
+ } |
||||
} |
||||
libc_hidden_def (__pthread_disable_asynccancel) |
||||
diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c |
||||
index 7e858d0df068276b..35ba40fb0247c7cc 100644 |
||||
--- a/nptl/cleanup_defer.c |
||||
+++ b/nptl/cleanup_defer.c |
||||
@@ -31,9 +31,22 @@ ___pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) |
||||
ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); |
||||
ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); |
||||
|
||||
- /* Disable asynchronous cancellation for now. */ |
||||
- ibuf->priv.data.canceltype = THREAD_GETMEM (self, canceltype); |
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED); |
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); |
||||
+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK)) |
||||
+ { |
||||
+ int newval; |
||||
+ do |
||||
+ { |
||||
+ newval = cancelhandling & ~CANCELTYPE_BITMASK; |
||||
+ } |
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &cancelhandling, |
||||
+ newval)); |
||||
+ } |
||||
+ |
||||
+ ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK |
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS |
||||
+ : PTHREAD_CANCEL_DEFERRED); |
||||
|
||||
/* Store the new cleanup handler info. */ |
||||
THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); |
||||
@@ -55,9 +68,26 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) |
||||
|
||||
THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); |
||||
|
||||
- THREAD_SETMEM (self, canceltype, ibuf->priv.data.canceltype); |
||||
- if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
- __pthread_testcancel (); |
||||
+ if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_DEFERRED) |
||||
+ return; |
||||
+ |
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); |
||||
+ if (cancelhandling & CANCELTYPE_BITMASK) |
||||
+ { |
||||
+ int newval; |
||||
+ do |
||||
+ { |
||||
+ newval = cancelhandling | CANCELTYPE_BITMASK; |
||||
+ } |
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &cancelhandling, newval)); |
||||
+ |
||||
+ if (cancel_enabled_and_canceled (cancelhandling)) |
||||
+ { |
||||
+ self->result = PTHREAD_CANCELED; |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ } |
||||
} |
||||
versioned_symbol (libc, ___pthread_unregister_cancel_restore, |
||||
__pthread_unregister_cancel_restore, GLIBC_2_34); |
||||
diff --git a/nptl/descr.h b/nptl/descr.h |
||||
index dabf980e29615db3..dfef9c4bda075d13 100644 |
||||
--- a/nptl/descr.h |
||||
+++ b/nptl/descr.h |
||||
@@ -280,18 +280,27 @@ struct pthread |
||||
|
||||
/* Flags determining processing of cancellation. */ |
||||
int cancelhandling; |
||||
+ /* Bit set if cancellation is disabled. */ |
||||
+#define CANCELSTATE_BIT 0 |
||||
+#define CANCELSTATE_BITMASK (1 << CANCELSTATE_BIT) |
||||
+ /* Bit set if asynchronous cancellation mode is selected. */ |
||||
+#define CANCELTYPE_BIT 1 |
||||
+#define CANCELTYPE_BITMASK (1 << CANCELTYPE_BIT) |
||||
+ /* Bit set if canceling has been initiated. */ |
||||
+#define CANCELING_BIT 2 |
||||
+#define CANCELING_BITMASK (1 << CANCELING_BIT) |
||||
/* Bit set if canceled. */ |
||||
#define CANCELED_BIT 3 |
||||
-#define CANCELED_BITMASK (0x01 << CANCELED_BIT) |
||||
+#define CANCELED_BITMASK (1 << CANCELED_BIT) |
||||
/* Bit set if thread is exiting. */ |
||||
#define EXITING_BIT 4 |
||||
-#define EXITING_BITMASK (0x01 << EXITING_BIT) |
||||
+#define EXITING_BITMASK (1 << EXITING_BIT) |
||||
/* Bit set if thread terminated and TCB is freed. */ |
||||
#define TERMINATED_BIT 5 |
||||
-#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) |
||||
+#define TERMINATED_BITMASK (1 << TERMINATED_BIT) |
||||
/* Bit set if thread is supposed to change XID. */ |
||||
#define SETXID_BIT 6 |
||||
-#define SETXID_BITMASK (0x01 << SETXID_BIT) |
||||
+#define SETXID_BITMASK (1 << SETXID_BIT) |
||||
|
||||
/* Flags. Including those copied from the thread attribute. */ |
||||
int flags; |
||||
@@ -391,14 +400,6 @@ struct pthread |
||||
/* Indicates whether is a C11 thread created by thrd_creat. */ |
||||
bool c11; |
||||
|
||||
- /* Thread cancel state (PTHREAD_CANCEL_ENABLE or |
||||
- PTHREAD_CANCEL_DISABLE). */ |
||||
- unsigned char cancelstate; |
||||
- |
||||
- /* Thread cancel type (PTHREAD_CANCEL_DEFERRED or |
||||
- PTHREAD_CANCEL_ASYNCHRONOUS). */ |
||||
- unsigned char canceltype; |
||||
- |
||||
/* Used in __pthread_kill_internal to detected a thread that has |
||||
exited or is about to exit. exit_lock must only be acquired |
||||
after blocking signals. */ |
||||
@@ -418,6 +419,22 @@ struct pthread |
||||
(sizeof (struct pthread) - offsetof (struct pthread, end_padding)) |
||||
} __attribute ((aligned (TCB_ALIGNMENT))); |
||||
|
||||
+static inline bool |
||||
+cancel_enabled_and_canceled (int value) |
||||
+{ |
||||
+ return (value & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK |
||||
+ | TERMINATED_BITMASK)) |
||||
+ == CANCELED_BITMASK; |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+cancel_enabled_and_canceled_and_async (int value) |
||||
+{ |
||||
+ return ((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK |
||||
+ | EXITING_BITMASK | TERMINATED_BITMASK)) |
||||
+ == (CANCELTYPE_BITMASK | CANCELED_BITMASK); |
||||
+} |
||||
+ |
||||
/* This yields the pointer that TLS support code calls the thread pointer. */ |
||||
#if TLS_TCB_AT_TP |
||||
# define TLS_TPADJ(pd) (pd) |
||||
diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c |
||||
index 180d15bc9e9a8368..fccb1abe69aa693c 100644 |
||||
--- a/nptl/libc-cleanup.c |
||||
+++ b/nptl/libc-cleanup.c |
||||
@@ -27,9 +27,24 @@ __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer) |
||||
|
||||
buffer->__prev = THREAD_GETMEM (self, cleanup); |
||||
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); |
||||
+ |
||||
/* Disable asynchronous cancellation for now. */ |
||||
- buffer->__canceltype = THREAD_GETMEM (self, canceltype); |
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED); |
||||
+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK)) |
||||
+ { |
||||
+ int newval; |
||||
+ do |
||||
+ { |
||||
+ newval = cancelhandling & ~CANCELTYPE_BITMASK; |
||||
+ } |
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &cancelhandling, |
||||
+ newval)); |
||||
+ } |
||||
+ |
||||
+ buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK |
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS |
||||
+ : PTHREAD_CANCEL_DEFERRED); |
||||
|
||||
THREAD_SETMEM (self, cleanup, buffer); |
||||
} |
||||
@@ -42,8 +57,22 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer) |
||||
|
||||
THREAD_SETMEM (self, cleanup, buffer->__prev); |
||||
|
||||
- THREAD_SETMEM (self, canceltype, buffer->__canceltype); |
||||
- if (buffer->__canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
- __pthread_testcancel (); |
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); |
||||
+ if (cancelhandling & CANCELTYPE_BITMASK) |
||||
+ { |
||||
+ int newval; |
||||
+ do |
||||
+ { |
||||
+ newval = cancelhandling | CANCELTYPE_BITMASK; |
||||
+ } |
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &cancelhandling, newval)); |
||||
+ |
||||
+ if (cancel_enabled_and_canceled (cancelhandling)) |
||||
+ { |
||||
+ self->result = PTHREAD_CANCELED; |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ } |
||||
} |
||||
libc_hidden_def (__libc_cleanup_pop_restore) |
||||
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c |
||||
index 9bac6e3b76a20312..2680b55586e035fe 100644 |
||||
--- a/nptl/pthread_cancel.c |
||||
+++ b/nptl/pthread_cancel.c |
||||
@@ -43,18 +43,29 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx) |
||||
|
||||
struct pthread *self = THREAD_SELF; |
||||
|
||||
- int ch = atomic_load_relaxed (&self->cancelhandling); |
||||
- /* Cancelation not enabled, not cancelled, or already exitting. */ |
||||
- if (self->cancelstate == PTHREAD_CANCEL_DISABLE |
||||
- || (ch & CANCELED_BITMASK) == 0 |
||||
- || (ch & EXITING_BITMASK) != 0) |
||||
- return; |
||||
- |
||||
- /* Set the return value. */ |
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED); |
||||
- /* Make sure asynchronous cancellation is still enabled. */ |
||||
- if (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
- __do_cancel (); |
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling); |
||||
+ while (1) |
||||
+ { |
||||
+ /* We are canceled now. When canceled by another thread this flag |
||||
+ is already set but if the signal is directly send (internally or |
||||
+ from another process) is has to be done here. */ |
||||
+ int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; |
||||
+ |
||||
+ if (oldval == newval || (oldval & EXITING_BITMASK) != 0) |
||||
+ /* Already canceled or exiting. */ |
||||
+ break; |
||||
+ |
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &oldval, newval)) |
||||
+ { |
||||
+ self->result = PTHREAD_CANCELED; |
||||
+ |
||||
+ /* Make sure asynchronous cancellation is still enabled. */ |
||||
+ if ((oldval & CANCELTYPE_BITMASK) != 0) |
||||
+ /* Run the registered destructors and terminate the thread. */ |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ } |
||||
} |
||||
|
||||
int |
||||
@@ -93,29 +104,70 @@ __pthread_cancel (pthread_t th) |
||||
} |
||||
#endif |
||||
|
||||
- int oldch = atomic_fetch_or_acquire (&pd->cancelhandling, CANCELED_BITMASK); |
||||
- if ((oldch & CANCELED_BITMASK) != 0) |
||||
- return 0; |
||||
- |
||||
- if (pd == THREAD_SELF) |
||||
+ /* Some syscalls are never restarted after being interrupted by a signal |
||||
+ handler, regardless of the use of SA_RESTART (they always fail with |
||||
+ EINTR). So pthread_cancel cannot send SIGCANCEL unless the cancellation |
||||
+ is enabled and set as asynchronous (in this case the cancellation will |
||||
+ be acted in the cancellation handler instead by the syscall wrapper). |
||||
+ Otherwise the target thread is set as 'cancelling' (CANCELING_BITMASK) |
||||
+ by atomically setting 'cancelhandling' and the cancelation will be acted |
||||
+ upon on next cancellation entrypoing in the target thread. |
||||
+ |
||||
+ It also requires to atomically check if cancellation is enabled and |
||||
+ asynchronous, so both cancellation state and type are tracked on |
||||
+ 'cancelhandling'. */ |
||||
+ |
||||
+ int result = 0; |
||||
+ int oldval = atomic_load_relaxed (&pd->cancelhandling); |
||||
+ int newval; |
||||
+ do |
||||
{ |
||||
- /* A single-threaded process should be able to kill itself, since there |
||||
- is nothing in the POSIX specification that says that it cannot. So |
||||
- we set multiple_threads to true so that cancellation points get |
||||
- executed. */ |
||||
- THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); |
||||
+ newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; |
||||
+ if (oldval == newval) |
||||
+ break; |
||||
+ |
||||
+ /* If the cancellation is handled asynchronously just send a |
||||
+ signal. We avoid this if possible since it's more |
||||
+ expensive. */ |
||||
+ if (cancel_enabled_and_canceled_and_async (newval)) |
||||
+ { |
||||
+ /* Mark the cancellation as "in progress". */ |
||||
+ int newval2 = oldval | CANCELING_BITMASK; |
||||
+ if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, |
||||
+ &oldval, newval2)) |
||||
+ continue; |
||||
+ |
||||
+ if (pd == THREAD_SELF) |
||||
+ /* This is not merely an optimization: An application may |
||||
+ call pthread_cancel (pthread_self ()) without calling |
||||
+ pthread_create, so the signal handler may not have been |
||||
+ set up for a self-cancel. */ |
||||
+ { |
||||
+ pd->result = PTHREAD_CANCELED; |
||||
+ if ((newval & CANCELTYPE_BITMASK) != 0) |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ else |
||||
+ /* The cancellation handler will take care of marking the |
||||
+ thread as canceled. */ |
||||
+ result = __pthread_kill_internal (th, SIGCANCEL); |
||||
+ |
||||
+ break; |
||||
+ } |
||||
+ |
||||
+ /* A single-threaded process should be able to kill itself, since |
||||
+ there is nothing in the POSIX specification that says that it |
||||
+ cannot. So we set multiple_threads to true so that cancellation |
||||
+ points get executed. */ |
||||
+ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); |
||||
#ifndef TLS_MULTIPLE_THREADS_IN_TCB |
||||
__libc_multiple_threads = 1; |
||||
#endif |
||||
- |
||||
- THREAD_SETMEM (pd, result, PTHREAD_CANCELED); |
||||
- if (pd->cancelstate == PTHREAD_CANCEL_ENABLE |
||||
- && pd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
- __do_cancel (); |
||||
- return 0; |
||||
} |
||||
+ while (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, &oldval, |
||||
+ newval)); |
||||
|
||||
- return __pthread_kill_internal (th, SIGCANCEL); |
||||
+ return result; |
||||
} |
||||
versioned_symbol (libc, __pthread_cancel, pthread_cancel, GLIBC_2_34); |
||||
|
||||
diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c |
||||
index 7303069316caef13..617056ef10671607 100644 |
||||
--- a/nptl/pthread_join_common.c |
||||
+++ b/nptl/pthread_join_common.c |
||||
@@ -57,12 +57,9 @@ __pthread_clockjoin_ex (pthread_t threadid, void **thread_return, |
||||
if ((pd == self |
||||
|| (self->joinid == pd |
||||
&& (pd->cancelhandling |
||||
- & (CANCELED_BITMASK | EXITING_BITMASK |
||||
+ & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK |
||||
| TERMINATED_BITMASK)) == 0)) |
||||
- && !(self->cancelstate == PTHREAD_CANCEL_ENABLE |
||||
- && (pd->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK |
||||
- | TERMINATED_BITMASK)) |
||||
- == CANCELED_BITMASK)) |
||||
+ && !cancel_enabled_and_canceled (self->cancelhandling)) |
||||
/* This is a deadlock situation. The threads are waiting for each |
||||
other to finish. Note that this is a "may" error. To be 100% |
||||
sure we catch this error we would have to lock the data |
||||
diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c |
||||
index 7e2b6e4974bd58bd..cb567be5926816f1 100644 |
||||
--- a/nptl/pthread_setcancelstate.c |
||||
+++ b/nptl/pthread_setcancelstate.c |
||||
@@ -31,9 +31,29 @@ __pthread_setcancelstate (int state, int *oldstate) |
||||
|
||||
self = THREAD_SELF; |
||||
|
||||
- if (oldstate != NULL) |
||||
- *oldstate = self->cancelstate; |
||||
- self->cancelstate = state; |
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling); |
||||
+ while (1) |
||||
+ { |
||||
+ int newval = (state == PTHREAD_CANCEL_DISABLE |
||||
+ ? oldval | CANCELSTATE_BITMASK |
||||
+ : oldval & ~CANCELSTATE_BITMASK); |
||||
+ |
||||
+ if (oldstate != NULL) |
||||
+ *oldstate = ((oldval & CANCELSTATE_BITMASK) |
||||
+ ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE); |
||||
+ |
||||
+ if (oldval == newval) |
||||
+ break; |
||||
+ |
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &oldval, newval)) |
||||
+ { |
||||
+ if (cancel_enabled_and_canceled_and_async (newval)) |
||||
+ __do_cancel (); |
||||
+ |
||||
+ break; |
||||
+ } |
||||
+ } |
||||
|
||||
return 0; |
||||
} |
||||
diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c |
||||
index e7b24ae733dcc0f2..e08ff7b141f904f1 100644 |
||||
--- a/nptl/pthread_setcanceltype.c |
||||
+++ b/nptl/pthread_setcanceltype.c |
||||
@@ -29,11 +29,32 @@ __pthread_setcanceltype (int type, int *oldtype) |
||||
|
||||
volatile struct pthread *self = THREAD_SELF; |
||||
|
||||
- if (oldtype != NULL) |
||||
- *oldtype = self->canceltype; |
||||
- self->canceltype = type; |
||||
- if (type == PTHREAD_CANCEL_ASYNCHRONOUS) |
||||
- __pthread_testcancel (); |
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling); |
||||
+ while (1) |
||||
+ { |
||||
+ int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS |
||||
+ ? oldval | CANCELTYPE_BITMASK |
||||
+ : oldval & ~CANCELTYPE_BITMASK); |
||||
+ |
||||
+ if (oldtype != NULL) |
||||
+ *oldtype = ((oldval & CANCELTYPE_BITMASK) |
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); |
||||
+ |
||||
+ if (oldval == newval) |
||||
+ break; |
||||
+ |
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, |
||||
+ &oldval, newval)) |
||||
+ { |
||||
+ if (cancel_enabled_and_canceled_and_async (newval)) |
||||
+ { |
||||
+ THREAD_SETMEM (self, result, PTHREAD_CANCELED); |
||||
+ __do_cancel (); |
||||
+ } |
||||
+ |
||||
+ break; |
||||
+ } |
||||
+ } |
||||
|
||||
return 0; |
||||
} |
||||
diff --git a/nptl/pthread_testcancel.c b/nptl/pthread_testcancel.c |
||||
index 31185d89f2ab84c6..25230215fd607e8b 100644 |
||||
--- a/nptl/pthread_testcancel.c |
||||
+++ b/nptl/pthread_testcancel.c |
||||
@@ -24,13 +24,10 @@ void |
||||
___pthread_testcancel (void) |
||||
{ |
||||
struct pthread *self = THREAD_SELF; |
||||
- int cancelhandling = THREAD_GETMEM (self, cancelhandling); |
||||
- if (self->cancelstate == PTHREAD_CANCEL_ENABLE |
||||
- && (cancelhandling & CANCELED_BITMASK) |
||||
- && !(cancelhandling & EXITING_BITMASK) |
||||
- && !(cancelhandling & TERMINATED_BITMASK)) |
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); |
||||
+ if (cancel_enabled_and_canceled (cancelhandling)) |
||||
{ |
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED); |
||||
+ self->result = PTHREAD_CANCELED; |
||||
__do_cancel (); |
||||
} |
||||
} |
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c |
||||
index b39dfbff2c6678d5..23aa4cfc0b784dfc 100644 |
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c |
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c |
||||
@@ -107,7 +107,4 @@ __tls_init_tp (void) |
||||
It will be bigger than it actually is, but for unwind.c/pt-longjmp.c |
||||
purposes this is good enough. */ |
||||
THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end); |
||||
- |
||||
- THREAD_SETMEM (pd, cancelstate, PTHREAD_CANCEL_ENABLE); |
||||
- THREAD_SETMEM (pd, canceltype, PTHREAD_CANCEL_DEFERRED); |
||||
} |
||||
diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h |
||||
index 374657a2fd0ee19a..b968afc4c6b61b92 100644 |
||||
--- a/sysdeps/nptl/pthreadP.h |
||||
+++ b/sysdeps/nptl/pthreadP.h |
||||
@@ -276,7 +276,7 @@ __do_cancel (void) |
||||
struct pthread *self = THREAD_SELF; |
||||
|
||||
/* Make sure we get no more cancellations. */ |
||||
- THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT); |
||||
+ atomic_bit_set (&self->cancelhandling, EXITING_BIT); |
||||
|
||||
__pthread_unwind ((__pthread_unwind_buf_t *) |
||||
THREAD_GETMEM (self, cleanup_jmp_buf)); |
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile |
||||
index c65710169697ad95..00419c4d199df912 100644 |
||||
--- a/sysdeps/pthread/Makefile |
||||
+++ b/sysdeps/pthread/Makefile |
||||
@@ -69,6 +69,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ |
||||
tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16 \ |
||||
tst-cancel18 tst-cancel19 tst-cancel20 tst-cancel21 \ |
||||
tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \ |
||||
+ tst-cancel29 \ |
||||
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \ |
||||
tst-clock1 \ |
||||
tst-cond-except \ |
||||
diff --git a/sysdeps/pthread/tst-cancel29.c b/sysdeps/pthread/tst-cancel29.c |
||||
new file mode 100644 |
||||
index 0000000000000000..4f0d99e002883be4 |
||||
--- /dev/null |
||||
+++ b/sysdeps/pthread/tst-cancel29.c |
||||
@@ -0,0 +1,207 @@ |
||||
+/* Check if a thread that disables cancellation and which call functions |
||||
+ that might be interrupted by a signal do not see the internal SIGCANCEL. |
||||
+ |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <errno.h> |
||||
+#include <inttypes.h> |
||||
+#include <poll.h> |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+#include <support/temp_file.h> |
||||
+#include <support/xthread.h> |
||||
+#include <sys/socket.h> |
||||
+#include <signal.h> |
||||
+#include <stdio.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+/* On Linux some interfaces are never restarted after being interrupted by |
||||
+ a signal handler, regardless of the use of SA_RESTART. It means that |
||||
+ if asynchronous cancellation is not enabled, the pthread_cancel can not |
||||
+ set the internal SIGCANCEL otherwise the interface might see a spurious |
||||
+ EINTR failure. */ |
||||
+ |
||||
+static pthread_barrier_t b; |
||||
+ |
||||
+/* Cleanup handling test. */ |
||||
+static int cl_called; |
||||
+static void |
||||
+cl (void *arg) |
||||
+{ |
||||
+ ++cl_called; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_sigtimedwait (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ sigset_t mask; |
||||
+ sigemptyset (&mask); |
||||
+ r = sigtimedwait (&mask, NULL, &(struct timespec) { 0, 250000000 }); |
||||
+ if (r != -1) |
||||
+ return (void*) -1; |
||||
+ if (errno != EAGAIN) |
||||
+ return (void*) -2; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_poll (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ r = poll (NULL, 0, 250); |
||||
+ if (r != 0) |
||||
+ return (void*) -1; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_ppoll (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ r = ppoll (NULL, 0, &(struct timespec) { 0, 250000000 }, NULL); |
||||
+ if (r != 0) |
||||
+ return (void*) -1; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_select (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ r = select (0, NULL, NULL, NULL, &(struct timeval) { 0, 250000 }); |
||||
+ if (r != 0) |
||||
+ return (void*) -1; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_pselect (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ r = pselect (0, NULL, NULL, NULL, &(struct timespec) { 0, 250000000 }, NULL); |
||||
+ if (r != 0) |
||||
+ return (void*) -1; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static void * |
||||
+tf_clock_nanosleep (void *arg) |
||||
+{ |
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ int r; |
||||
+ pthread_cleanup_push (cl, NULL); |
||||
+ |
||||
+ r = clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 0, 250000000 }, |
||||
+ NULL); |
||||
+ if (r != 0) |
||||
+ return (void*) -1; |
||||
+ |
||||
+ pthread_cleanup_pop (0); |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+struct cancel_test_t |
||||
+{ |
||||
+ const char *name; |
||||
+ void * (*cf) (void *); |
||||
+} tests[] = |
||||
+{ |
||||
+ { "sigtimedwait", tf_sigtimedwait, }, |
||||
+ { "poll", tf_poll, }, |
||||
+ { "ppoll", tf_ppoll, }, |
||||
+ { "select", tf_select, }, |
||||
+ { "pselect", tf_pselect , }, |
||||
+ { "clock_nanosleep", tf_clock_nanosleep, }, |
||||
+}; |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ for (int i = 0; i < array_length (tests); i++) |
||||
+ { |
||||
+ xpthread_barrier_init (&b, NULL, 2); |
||||
+ |
||||
+ cl_called = 0; |
||||
+ |
||||
+ pthread_t th = xpthread_create (NULL, tests[i].cf, NULL); |
||||
+ |
||||
+ xpthread_barrier_wait (&b); |
||||
+ |
||||
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 }; |
||||
+ while (nanosleep (&ts, &ts) != 0) |
||||
+ continue; |
||||
+ |
||||
+ xpthread_cancel (th); |
||||
+ |
||||
+ void *status = xpthread_join (th); |
||||
+ if (status != NULL) |
||||
+ printf ("test '%s' failed: %" PRIdPTR "\n", tests[i].name, |
||||
+ (intptr_t) status); |
||||
+ TEST_VERIFY (status == NULL); |
||||
+ |
||||
+ xpthread_barrier_destroy (&b); |
||||
+ |
||||
+ TEST_COMPARE (cl_called, 0); |
||||
+ |
||||
+ printf ("in-time cancel test of '%s' successful\n", tests[i].name); |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
commit 5d8c7776343b3f1b96ef7777e4504378f23c041a |
||||
Author: Samuel Thibault <samuel.thibault@ens-lyon.org> |
||||
Date: Tue Apr 12 22:14:34 2022 +0200 |
||||
|
||||
hurd: Fix arbitrary error code |
||||
|
||||
ELIBBAD is Linux-specific. |
||||
|
||||
(cherry picked from commit 67ab66541dc1164540abda284645e38be90b5119) |
||||
|
||||
diff --git a/nss/nss_test_errno.c b/nss/nss_test_errno.c |
||||
index 680f8a07b97fe263..59a5c717bebd296f 100644 |
||||
--- a/nss/nss_test_errno.c |
||||
+++ b/nss/nss_test_errno.c |
||||
@@ -28,7 +28,7 @@ static void __attribute__ ((constructor)) |
||||
init (void) |
||||
{ |
||||
/* An arbitrary error code which is otherwise not used. */ |
||||
- errno = ELIBBAD; |
||||
+ errno = -1009; |
||||
} |
||||
|
||||
/* Lookup functions for pwd follow that do not return any data. */ |
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
commit b87b697f15d6bf7e576a2eeadc1f740172f9d013 |
||||
Author: =Joshua Kinard <kumba@gentoo.org> |
||||
Date: Mon Apr 18 09:55:08 2022 -0300 |
||||
|
||||
mips: Fix mips64n32 64 bit time_t stat support (BZ#29069) |
||||
|
||||
Add missing support initially added by 4e8521333bea6e89fcef1020 |
||||
(which missed n32 stat). |
||||
|
||||
(cherry picked from commit 78fb88827362fbd2cc8aa32892ae5b015106e25c) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h b/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h |
||||
index ab9f474cbc271b7c..ed5b1bc00ba52406 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h |
||||
@@ -131,27 +131,30 @@ struct stat64 |
||||
|
||||
struct stat |
||||
{ |
||||
+# ifdef __USE_TIME_BITS64 |
||||
+# include <bits/struct_stat_time64_helper.h> |
||||
+# else |
||||
__dev_t st_dev; |
||||
int st_pad1[3]; /* Reserved for st_dev expansion */ |
||||
-# ifndef __USE_FILE_OFFSET64 |
||||
+# ifndef __USE_FILE_OFFSET64 |
||||
__ino_t st_ino; |
||||
-# else |
||||
+# else |
||||
__ino64_t st_ino; |
||||
-# endif |
||||
+# endif |
||||
__mode_t st_mode; |
||||
__nlink_t st_nlink; |
||||
__uid_t st_uid; |
||||
__gid_t st_gid; |
||||
__dev_t st_rdev; |
||||
-# if !defined __USE_FILE_OFFSET64 |
||||
+# if !defined __USE_FILE_OFFSET64 |
||||
unsigned int st_pad2[2]; /* Reserved for st_rdev expansion */ |
||||
__off_t st_size; |
||||
int st_pad3; |
||||
-# else |
||||
+# else |
||||
unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */ |
||||
__off64_t st_size; |
||||
-# endif |
||||
-# ifdef __USE_XOPEN2K8 |
||||
+# endif |
||||
+# ifdef __USE_XOPEN2K8 |
||||
/* Nanosecond resolution timestamps are stored in a format |
||||
equivalent to 'struct timespec'. This is the type used |
||||
whenever possible but the Unix namespace rules do not allow the |
||||
@@ -161,30 +164,34 @@ struct stat |
||||
struct timespec st_atim; /* Time of last access. */ |
||||
struct timespec st_mtim; /* Time of last modification. */ |
||||
struct timespec st_ctim; /* Time of last status change. */ |
||||
-# define st_atime st_atim.tv_sec /* Backward compatibility. */ |
||||
-# define st_mtime st_mtim.tv_sec |
||||
-# define st_ctime st_ctim.tv_sec |
||||
-# else |
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */ |
||||
+# define st_mtime st_mtim.tv_sec |
||||
+# define st_ctime st_ctim.tv_sec |
||||
+# else |
||||
__time_t st_atime; /* Time of last access. */ |
||||
unsigned long int st_atimensec; /* Nscecs of last access. */ |
||||
__time_t st_mtime; /* Time of last modification. */ |
||||
unsigned long int st_mtimensec; /* Nsecs of last modification. */ |
||||
__time_t st_ctime; /* Time of last status change. */ |
||||
unsigned long int st_ctimensec; /* Nsecs of last status change. */ |
||||
-# endif |
||||
+# endif |
||||
__blksize_t st_blksize; |
||||
unsigned int st_pad4; |
||||
-# ifndef __USE_FILE_OFFSET64 |
||||
+# ifndef __USE_FILE_OFFSET64 |
||||
__blkcnt_t st_blocks; |
||||
-# else |
||||
+# else |
||||
__blkcnt64_t st_blocks; |
||||
-# endif |
||||
+# endif |
||||
int st_pad5[14]; |
||||
+# endif |
||||
}; |
||||
|
||||
#ifdef __USE_LARGEFILE64 |
||||
struct stat64 |
||||
{ |
||||
+# ifdef __USE_TIME_BITS64 |
||||
+# include <bits/struct_stat_time64_helper.h> |
||||
+# else |
||||
__dev_t st_dev; |
||||
unsigned int st_pad1[3]; /* Reserved for st_dev expansion */ |
||||
__ino64_t st_ino; |
||||
@@ -217,6 +224,7 @@ struct stat64 |
||||
unsigned int st_pad3; |
||||
__blkcnt64_t st_blocks; |
||||
int st_pad4[14]; |
||||
+# endif /* __USE_TIME_BITS64 */ |
||||
}; |
||||
#endif |
||||
|
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
commit 71326f1f2fd09dafb9c34404765fb88129e94237 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Apr 20 12:01:43 2022 -0300 |
||||
|
||||
nptl: Fix pthread_cancel cancelhandling atomic operations |
||||
|
||||
The 404656009b reversion did not setup the atomic loop to set the |
||||
cancel bits correctly. The fix is essentially what pthread_cancel |
||||
did prior 26cfbb7162ad. |
||||
|
||||
Checked on x86_64-linux-gnu and aarch64-linux-gnu. |
||||
|
||||
(cherry picked from commit 62be9681677e7ce820db721c126909979382d379) |
||||
|
||||
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c |
||||
index 2680b55586e035fe..64fd183fde59907b 100644 |
||||
--- a/nptl/pthread_cancel.c |
||||
+++ b/nptl/pthread_cancel.c |
||||
@@ -122,6 +122,7 @@ __pthread_cancel (pthread_t th) |
||||
int newval; |
||||
do |
||||
{ |
||||
+ again: |
||||
newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; |
||||
if (oldval == newval) |
||||
break; |
||||
@@ -135,7 +136,7 @@ __pthread_cancel (pthread_t th) |
||||
int newval2 = oldval | CANCELING_BITMASK; |
||||
if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, |
||||
&oldval, newval2)) |
||||
- continue; |
||||
+ goto again; |
||||
|
||||
if (pd == THREAD_SELF) |
||||
/* This is not merely an optimization: An application may |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,407 @@
@@ -0,0 +1,407 @@
|
||||
commit f0c71b34f96c816292c49122d50da3a511b67bf2 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Apr 11 11:30:31 2022 +0200 |
||||
|
||||
Default to --with-default-link=no (bug 25812) |
||||
|
||||
This is necessary to place the libio vtables into the RELRO segment. |
||||
New tests elf/tst-relro-ldso and elf/tst-relro-libc are added to |
||||
verify that this is what actually happens. |
||||
|
||||
The new tests fail on ia64 due to lack of (default) RELRO support |
||||
inbutils, so they are XFAILed there. |
||||
|
||||
(cherry picked from commit 198abcbb94618730dae1b3f4393efaa49e0ec8c7) |
||||
|
||||
diff --git a/INSTALL b/INSTALL |
||||
index d8d4e9f155f56616..60d01568d77645c7 100644 |
||||
--- a/INSTALL |
||||
+++ b/INSTALL |
||||
@@ -90,6 +90,12 @@ if 'CFLAGS' is specified it must enable optimization. For example: |
||||
library will still be usable, but functionality may be lost--for |
||||
example, you can't build a shared libc with old binutils. |
||||
|
||||
+'--with-default-link=FLAG' |
||||
+ With '--with-default-link=yes', the build system does not use a |
||||
+ custom linker script for linking shared objects. The default for |
||||
+ FLAG is the opposite, 'no', because the custom linker script is |
||||
+ needed for full RELRO protection. |
||||
+ |
||||
'--with-nonshared-cflags=CFLAGS' |
||||
Use additional compiler flags CFLAGS to build the parts of the |
||||
library which are always statically linked into applications and |
||||
diff --git a/configure b/configure |
||||
index 03f4e59e754b5463..34c64f8de44e3086 100755 |
||||
--- a/configure |
||||
+++ b/configure |
||||
@@ -3373,7 +3373,7 @@ fi |
||||
if test "${with_default_link+set}" = set; then : |
||||
withval=$with_default_link; use_default_link=$withval |
||||
else |
||||
- use_default_link=default |
||||
+ use_default_link=no |
||||
fi |
||||
|
||||
|
||||
@@ -6085,69 +6085,6 @@ fi |
||||
$as_echo "$libc_cv_hashstyle" >&6; } |
||||
|
||||
|
||||
-# The linker's default -shared behavior is good enough if it |
||||
-# does these things that our custom linker scripts ensure that |
||||
-# all allocated NOTE sections come first. |
||||
-if test "$use_default_link" = default; then |
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sufficient default -shared layout" >&5 |
||||
-$as_echo_n "checking for sufficient default -shared layout... " >&6; } |
||||
-if ${libc_cv_use_default_link+:} false; then : |
||||
- $as_echo_n "(cached) " >&6 |
||||
-else |
||||
- libc_cv_use_default_link=no |
||||
- cat > conftest.s <<\EOF |
||||
- .section .note.a,"a",%note |
||||
- .balign 4 |
||||
- .long 4,4,9 |
||||
- .string "GNU" |
||||
- .string "foo" |
||||
- .section .note.b,"a",%note |
||||
- .balign 4 |
||||
- .long 4,4,9 |
||||
- .string "GNU" |
||||
- .string "bar" |
||||
-EOF |
||||
- if { ac_try=' ${CC-cc} $ASFLAGS -shared -o conftest.so conftest.s 1>&5' |
||||
- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 |
||||
- (eval $ac_try) 2>&5 |
||||
- ac_status=$? |
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 |
||||
- test $ac_status = 0; }; } && |
||||
- ac_try=`$READELF -S conftest.so | sed -n \ |
||||
- '${x;p;} |
||||
- s/^ *\[ *[1-9][0-9]*\] *\([^ ][^ ]*\) *\([^ ][^ ]*\) .*$/\2 \1/ |
||||
- t a |
||||
- b |
||||
- : a |
||||
- H'` |
||||
- then |
||||
- libc_seen_a=no libc_seen_b=no |
||||
- set -- $ac_try |
||||
- while test $# -ge 2 -a "$1" = NOTE; do |
||||
- case "$2" in |
||||
- .note.a) libc_seen_a=yes ;; |
||||
- .note.b) libc_seen_b=yes ;; |
||||
- esac |
||||
- shift 2 |
||||
- done |
||||
- case "$libc_seen_a$libc_seen_b" in |
||||
- yesyes) |
||||
- libc_cv_use_default_link=yes |
||||
- ;; |
||||
- *) |
||||
- echo >&5 "\ |
||||
-$libc_seen_a$libc_seen_b from: |
||||
-$ac_try" |
||||
- ;; |
||||
- esac |
||||
- fi |
||||
- rm -f conftest* |
||||
-fi |
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_use_default_link" >&5 |
||||
-$as_echo "$libc_cv_use_default_link" >&6; } |
||||
- use_default_link=$libc_cv_use_default_link |
||||
-fi |
||||
- |
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_DAT reloc" >&5 |
||||
$as_echo_n "checking for GLOB_DAT reloc... " >&6; } |
||||
if ${libc_cv_has_glob_dat+:} false; then : |
||||
diff --git a/configure.ac b/configure.ac |
||||
index eb9431875fae1b0e..2c69af0807266e7e 100644 |
||||
--- a/configure.ac |
||||
+++ b/configure.ac |
||||
@@ -153,7 +153,7 @@ AC_ARG_WITH([default-link], |
||||
AS_HELP_STRING([--with-default-link], |
||||
[do not use explicit linker scripts]), |
||||
[use_default_link=$withval], |
||||
- [use_default_link=default]) |
||||
+ [use_default_link=no]) |
||||
|
||||
dnl Additional build flags injection. |
||||
AC_ARG_WITH([nonshared-cflags], |
||||
@@ -1378,59 +1378,6 @@ fi |
||||
rm -f conftest*]) |
||||
AC_SUBST(libc_cv_hashstyle) |
||||
|
||||
-# The linker's default -shared behavior is good enough if it |
||||
-# does these things that our custom linker scripts ensure that |
||||
-# all allocated NOTE sections come first. |
||||
-if test "$use_default_link" = default; then |
||||
- AC_CACHE_CHECK([for sufficient default -shared layout], |
||||
- libc_cv_use_default_link, [dnl |
||||
- libc_cv_use_default_link=no |
||||
- cat > conftest.s <<\EOF |
||||
- .section .note.a,"a",%note |
||||
- .balign 4 |
||||
- .long 4,4,9 |
||||
- .string "GNU" |
||||
- .string "foo" |
||||
- .section .note.b,"a",%note |
||||
- .balign 4 |
||||
- .long 4,4,9 |
||||
- .string "GNU" |
||||
- .string "bar" |
||||
-EOF |
||||
- if AC_TRY_COMMAND([dnl |
||||
- ${CC-cc} $ASFLAGS -shared -o conftest.so conftest.s 1>&AS_MESSAGE_LOG_FD]) && |
||||
- ac_try=`$READELF -S conftest.so | sed -n \ |
||||
- ['${x;p;} |
||||
- s/^ *\[ *[1-9][0-9]*\] *\([^ ][^ ]*\) *\([^ ][^ ]*\) .*$/\2 \1/ |
||||
- t a |
||||
- b |
||||
- : a |
||||
- H']` |
||||
- then |
||||
- libc_seen_a=no libc_seen_b=no |
||||
- set -- $ac_try |
||||
- while test $# -ge 2 -a "$1" = NOTE; do |
||||
- case "$2" in |
||||
- .note.a) libc_seen_a=yes ;; |
||||
- .note.b) libc_seen_b=yes ;; |
||||
- esac |
||||
- shift 2 |
||||
- done |
||||
- case "$libc_seen_a$libc_seen_b" in |
||||
- yesyes) |
||||
- libc_cv_use_default_link=yes |
||||
- ;; |
||||
- *) |
||||
- echo >&AS_MESSAGE_LOG_FD "\ |
||||
-$libc_seen_a$libc_seen_b from: |
||||
-$ac_try" |
||||
- ;; |
||||
- esac |
||||
- fi |
||||
- rm -f conftest*]) |
||||
- use_default_link=$libc_cv_use_default_link |
||||
-fi |
||||
- |
||||
AC_CACHE_CHECK(for GLOB_DAT reloc, |
||||
libc_cv_has_glob_dat, [dnl |
||||
cat > conftest.c <<EOF |
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index 8afbe3f6ab259331..fec6e23b5b625e3b 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -504,6 +504,40 @@ tests-execstack-yes = \ |
||||
# tests-execstack-yes |
||||
endif |
||||
endif |
||||
+ |
||||
+tests-special += $(objpfx)tst-relro-ldso.out $(objpfx)tst-relro-libc.out |
||||
+$(objpfx)tst-relro-ldso.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \ |
||||
+ $(objpfx)ld.so |
||||
+ $(PYTHON) tst-relro-symbols.py $(objpfx)ld.so \ |
||||
+ --required=_rtld_global_ro \ |
||||
+ > $@ 2>&1; $(evaluate-test) |
||||
+# The optional symbols are present in libc only if the architecture has |
||||
+# the GLIBC_2.0 symbol set in libc. |
||||
+$(objpfx)tst-relro-libc.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \ |
||||
+ $(common-objpfx)libc.so |
||||
+ $(PYTHON) tst-relro-symbols.py $(common-objpfx)libc.so \ |
||||
+ --required=_IO_cookie_jumps \ |
||||
+ --required=_IO_file_jumps \ |
||||
+ --required=_IO_file_jumps_maybe_mmap \ |
||||
+ --required=_IO_file_jumps_mmap \ |
||||
+ --required=_IO_helper_jumps \ |
||||
+ --required=_IO_mem_jumps \ |
||||
+ --required=_IO_obstack_jumps \ |
||||
+ --required=_IO_proc_jumps \ |
||||
+ --required=_IO_str_chk_jumps \ |
||||
+ --required=_IO_str_jumps \ |
||||
+ --required=_IO_strn_jumps \ |
||||
+ --required=_IO_wfile_jumps \ |
||||
+ --required=_IO_wfile_jumps_maybe_mmap \ |
||||
+ --required=_IO_wfile_jumps_mmap \ |
||||
+ --required=_IO_wmem_jumps \ |
||||
+ --required=_IO_wstr_jumps \ |
||||
+ --required=_IO_wstrn_jumps \ |
||||
+ --optional=_IO_old_cookie_jumps \ |
||||
+ --optional=_IO_old_file_jumps \ |
||||
+ --optional=_IO_old_proc_jumps \ |
||||
+ > $@ 2>&1; $(evaluate-test) |
||||
+ |
||||
tests += $(tests-execstack-$(have-z-execstack)) |
||||
ifeq ($(run-built-tests),yes) |
||||
tests-special += \ |
||||
diff --git a/elf/tst-relro-symbols.py b/elf/tst-relro-symbols.py |
||||
new file mode 100644 |
||||
index 0000000000000000..368ea3349f86bd81 |
||||
--- /dev/null |
||||
+++ b/elf/tst-relro-symbols.py |
||||
@@ -0,0 +1,137 @@ |
||||
+#!/usr/bin/python3 |
||||
+# Verify that certain symbols are covered by RELRO. |
||||
+# Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+# This file is part of the GNU C Library. |
||||
+# |
||||
+# The GNU C Library is free software; you can redistribute it and/or |
||||
+# modify it under the terms of the GNU Lesser General Public |
||||
+# License as published by the Free Software Foundation; either |
||||
+# version 2.1 of the License, or (at your option) any later version. |
||||
+# |
||||
+# The GNU C Library is distributed in the hope that it will be useful, |
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+# Lesser General Public License for more details. |
||||
+# |
||||
+# You should have received a copy of the GNU Lesser General Public |
||||
+# License along with the GNU C Library; if not, see |
||||
+# <https://www.gnu.org/licenses/>. |
||||
+ |
||||
+"""Analyze a (shared) object to verify that certain symbols are |
||||
+present and covered by the PT_GNU_RELRO segment. |
||||
+ |
||||
+""" |
||||
+ |
||||
+import argparse |
||||
+import os.path |
||||
+import sys |
||||
+ |
||||
+# Make available glibc Python modules. |
||||
+sys.path.append(os.path.join( |
||||
+ os.path.dirname(os.path.realpath(__file__)), os.path.pardir, 'scripts')) |
||||
+ |
||||
+import glibcelf |
||||
+ |
||||
+def find_relro(path: str, img: glibcelf.Image) -> (int, int): |
||||
+ """Discover the address range of the PT_GNU_RELRO segment.""" |
||||
+ for phdr in img.phdrs(): |
||||
+ if phdr.p_type == glibcelf.Pt.PT_GNU_RELRO: |
||||
+ # The computation is not entirely accurate because |
||||
+ # _dl_protect_relro in elf/dl-reloc.c rounds both the |
||||
+ # start end and downwards using the run-time page size. |
||||
+ return phdr.p_vaddr, phdr.p_vaddr + phdr.p_memsz |
||||
+ sys.stdout.write('{}: error: no PT_GNU_RELRO segment\n'.format(path)) |
||||
+ sys.exit(1) |
||||
+ |
||||
+def check_in_relro(kind, relro_begin, relro_end, name, start, size, error): |
||||
+ """Check if a section or symbol falls within in the RELRO segment.""" |
||||
+ end = start + size - 1 |
||||
+ if not (relro_begin <= start < end < relro_end): |
||||
+ error( |
||||
+ '{} {!r} of size {} at 0x{:x} is not in RELRO range [0x{:x}, 0x{:x})'.format( |
||||
+ kind, name.decode('UTF-8'), start, size, |
||||
+ relro_begin, relro_end)) |
||||
+ |
||||
+def get_parser(): |
||||
+ """Return an argument parser for this script.""" |
||||
+ parser = argparse.ArgumentParser(description=__doc__) |
||||
+ parser.add_argument('object', help='path to object file to check') |
||||
+ parser.add_argument('--required', metavar='NAME', default=(), |
||||
+ help='required symbol names', nargs='*') |
||||
+ parser.add_argument('--optional', metavar='NAME', default=(), |
||||
+ help='required symbol names', nargs='*') |
||||
+ return parser |
||||
+ |
||||
+def main(argv): |
||||
+ """The main entry point.""" |
||||
+ parser = get_parser() |
||||
+ opts = parser.parse_args(argv) |
||||
+ img = glibcelf.Image.readfile(opts.object) |
||||
+ |
||||
+ required_symbols = frozenset([sym.encode('UTF-8') |
||||
+ for sym in opts.required]) |
||||
+ optional_symbols = frozenset([sym.encode('UTF-8') |
||||
+ for sym in opts.optional]) |
||||
+ check_symbols = required_symbols | optional_symbols |
||||
+ |
||||
+ # Tracks the symbols in check_symbols that have been found. |
||||
+ symbols_found = set() |
||||
+ |
||||
+ # Discover the extent of the RELRO segment. |
||||
+ relro_begin, relro_end = find_relro(opts.object, img) |
||||
+ symbol_table_found = False |
||||
+ |
||||
+ errors = False |
||||
+ def error(msg: str) -> None: |
||||
+ """Record an error condition and write a message to standard output.""" |
||||
+ nonlocal errors |
||||
+ errors = True |
||||
+ sys.stdout.write('{}: error: {}\n'.format(opts.object, msg)) |
||||
+ |
||||
+ # Iterate over section headers to find the symbol table. |
||||
+ for shdr in img.shdrs(): |
||||
+ if shdr.sh_type == glibcelf.Sht.SHT_SYMTAB: |
||||
+ symbol_table_found = True |
||||
+ for sym in img.syms(shdr): |
||||
+ if sym.st_name in check_symbols: |
||||
+ symbols_found.add(sym.st_name) |
||||
+ |
||||
+ # Validate symbol type, section, and size. |
||||
+ if sym.st_info.type != glibcelf.Stt.STT_OBJECT: |
||||
+ error('symbol {!r} has wrong type {}'.format( |
||||
+ sym.st_name.decode('UTF-8'), sym.st_info.type)) |
||||
+ if sym.st_shndx in glibcelf.Shn: |
||||
+ error('symbol {!r} has reserved section {}'.format( |
||||
+ sym.st_name.decode('UTF-8'), sym.st_shndx)) |
||||
+ continue |
||||
+ if sym.st_size == 0: |
||||
+ error('symbol {!r} has size zero'.format( |
||||
+ sym.st_name.decode('UTF-8'))) |
||||
+ continue |
||||
+ |
||||
+ check_in_relro('symbol', relro_begin, relro_end, |
||||
+ sym.st_name, sym.st_value, sym.st_size, |
||||
+ error) |
||||
+ continue # SHT_SYMTAB |
||||
+ if shdr.sh_name == b'.data.rel.ro' \ |
||||
+ or shdr.sh_name.startswith(b'.data.rel.ro.'): |
||||
+ check_in_relro('section', relro_begin, relro_end, |
||||
+ shdr.sh_name, shdr.sh_addr, shdr.sh_size, |
||||
+ error) |
||||
+ continue |
||||
+ |
||||
+ if required_symbols - symbols_found: |
||||
+ for sym in sorted(required_symbols - symbols_found): |
||||
+ error('symbol {!r} not found'.format(sym.decode('UTF-8'))) |
||||
+ |
||||
+ if errors: |
||||
+ sys.exit(1) |
||||
+ |
||||
+ if not symbol_table_found: |
||||
+ sys.stdout.write( |
||||
+ '{}: warning: no symbol table found (stripped object)\n'.format( |
||||
+ opts.object)) |
||||
+ sys.exit(77) |
||||
+ |
||||
+if __name__ == '__main__': |
||||
+ main(sys.argv[1:]) |
||||
diff --git a/manual/install.texi b/manual/install.texi |
||||
index 816b77a0a25a88a7..36a5af62bc5722b0 100644 |
||||
--- a/manual/install.texi |
||||
+++ b/manual/install.texi |
||||
@@ -117,6 +117,12 @@ problem and suppress these constructs, so that the library will still be |
||||
usable, but functionality may be lost---for example, you can't build a |
||||
shared libc with old binutils. |
||||
|
||||
+@item --with-default-link=@var{FLAG} |
||||
+With @code{--with-default-link=yes}, the build system does not use a |
||||
+custom linker script for linking shared objects. The default for |
||||
+@var{FLAG} is the opposite, @samp{no}, because the custom linker script |
||||
+is needed for full RELRO protection. |
||||
+ |
||||
@item --with-nonshared-cflags=@var{cflags} |
||||
Use additional compiler flags @var{cflags} to build the parts of the |
||||
library which are always statically linked into applications and |
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/Makefile b/sysdeps/unix/sysv/linux/ia64/Makefile |
||||
index da85ba43e2d0ddef..c5cc41b3677d4a2a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/ia64/Makefile |
||||
+++ b/sysdeps/unix/sysv/linux/ia64/Makefile |
||||
@@ -1,3 +1,9 @@ |
||||
+ifeq ($(subdir),elf) |
||||
+# ia64 does not support PT_GNU_RELRO. |
||||
+test-xfail-tst-relro-ldso = yes |
||||
+test-xfail-tst-relro-libc = yes |
||||
+endif |
||||
+ |
||||
ifeq ($(subdir),misc) |
||||
sysdep_headers += sys/rse.h |
||||
endif |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
commit ca0faa140ff8cebe4c041d935f0f5eb480873d99 |
||||
Author: Joan Bruguera <joanbrugueram@gmail.com> |
||||
Date: Mon Apr 11 19:49:56 2022 +0200 |
||||
|
||||
misc: Fix rare fortify crash on wchar funcs. [BZ 29030] |
||||
|
||||
If `__glibc_objsize (__o) == (size_t) -1` (i.e. `__o` is unknown size), fortify |
||||
checks should pass, and `__whatever_alias` should be called. |
||||
|
||||
Previously, `__glibc_objsize (__o) == (size_t) -1` was explicitly checked, but |
||||
on commit a643f60c53876b, this was moved into `__glibc_safe_or_unknown_len`. |
||||
|
||||
A comment says the -1 case should work as: "The -1 check is redundant because |
||||
since it implies that __glibc_safe_len_cond is true.". But this fails when: |
||||
* `__s > 1` |
||||
* `__osz == -1` (i.e. unknown size at compile time) |
||||
* `__l` is big enough |
||||
* `__l * __s <= __osz` can be folded to a constant |
||||
(I only found this to be true for `mbsrtowcs` and other functions in wchar2.h) |
||||
|
||||
In this case `__l * __s <= __osz` is false, and `__whatever_chk_warn` will be |
||||
called by `__glibc_fortify` or `__glibc_fortify_n` and crash the program. |
||||
|
||||
This commit adds the explicit `__osz == -1` check again. |
||||
moc crashes on startup due to this, see: https://bugs.archlinux.org/task/74041 |
||||
|
||||
Minimal test case (test.c): |
||||
#include <wchar.h> |
||||
|
||||
int main (void) |
||||
{ |
||||
const char *hw = "HelloWorld"; |
||||
mbsrtowcs (NULL, &hw, (size_t)-1, NULL); |
||||
return 0; |
||||
} |
||||
|
||||
Build with: |
||||
gcc -O2 -Wp,-D_FORTIFY_SOURCE=2 test.c -o test && ./test |
||||
|
||||
Output: |
||||
*** buffer overflow detected ***: terminated |
||||
|
||||
Fixes: BZ #29030 |
||||
Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com> |
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
(cherry picked from commit 33e03f9cd2be4f2cd62f93fda539cc07d9c8130e) |
||||
|
||||
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c |
||||
index 8b5902423cf0ad88..fb02452f5993c594 100644 |
||||
--- a/debug/tst-fortify.c |
||||
+++ b/debug/tst-fortify.c |
||||
@@ -1505,6 +1505,11 @@ do_test (void) |
||||
CHK_FAIL_END |
||||
#endif |
||||
|
||||
+ /* Bug 29030 regresion check */ |
||||
+ cp = "HelloWorld"; |
||||
+ if (mbsrtowcs (NULL, &cp, (size_t)-1, &s) != 10) |
||||
+ FAIL (); |
||||
+ |
||||
cp = "A"; |
||||
if (mbstowcs (wenough, cp, 10) != 1 |
||||
|| wcscmp (wenough, L"A") != 0) |
||||
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h |
||||
index 515fb681a0547217..b36013b9a6b4d9c3 100644 |
||||
--- a/misc/sys/cdefs.h |
||||
+++ b/misc/sys/cdefs.h |
||||
@@ -161,13 +161,13 @@ |
||||
|| (__builtin_constant_p (__l) && (__l) > 0)) |
||||
|
||||
/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ |
||||
- condition can be folded to a constant and if it is true. The -1 check is |
||||
- redundant because since it implies that __glibc_safe_len_cond is true. */ |
||||
+ condition can be folded to a constant and if it is true, or unknown (-1) */ |
||||
#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ |
||||
- (__glibc_unsigned_or_positive (__l) \ |
||||
- && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ |
||||
- __s, __osz)) \ |
||||
- && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) |
||||
+ ((__osz) == (__SIZE_TYPE__) -1 \ |
||||
+ || (__glibc_unsigned_or_positive (__l) \ |
||||
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ |
||||
+ (__s), (__osz))) \ |
||||
+ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz)))) |
||||
|
||||
/* Conversely, we know at compile time that the length is unsafe if the |
||||
__L * __S <= __OBJSZ condition can be folded to a constant and if it is |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
commit 0d477e92c49db2906b32e44135b98746ccc73c7b |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Apr 26 14:22:10 2022 +0200 |
||||
|
||||
INSTALL: Rephrase -with-default-link documentation |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit c935789bdf40ba22b5698da869d3a4789797e09f) |
||||
|
||||
diff --git a/INSTALL b/INSTALL |
||||
index 60d01568d77645c7..10a3dcdc0a8db665 100644 |
||||
--- a/INSTALL |
||||
+++ b/INSTALL |
||||
@@ -90,10 +90,10 @@ if 'CFLAGS' is specified it must enable optimization. For example: |
||||
library will still be usable, but functionality may be lost--for |
||||
example, you can't build a shared libc with old binutils. |
||||
|
||||
-'--with-default-link=FLAG' |
||||
- With '--with-default-link=yes', the build system does not use a |
||||
- custom linker script for linking shared objects. The default for |
||||
- FLAG is the opposite, 'no', because the custom linker script is |
||||
+'--with-default-link' |
||||
+ With '--with-default-link', the build system does not use a custom |
||||
+ linker script for linking shared objects. The default is |
||||
+ '--without-default-link', because the custom linker script is |
||||
needed for full RELRO protection. |
||||
|
||||
'--with-nonshared-cflags=CFLAGS' |
||||
diff --git a/manual/install.texi b/manual/install.texi |
||||
index 36a5af62bc5722b0..8e34ff7e1847f3ae 100644 |
||||
--- a/manual/install.texi |
||||
+++ b/manual/install.texi |
||||
@@ -117,11 +117,11 @@ problem and suppress these constructs, so that the library will still be |
||||
usable, but functionality may be lost---for example, you can't build a |
||||
shared libc with old binutils. |
||||
|
||||
-@item --with-default-link=@var{FLAG} |
||||
-With @code{--with-default-link=yes}, the build system does not use a |
||||
-custom linker script for linking shared objects. The default for |
||||
-@var{FLAG} is the opposite, @samp{no}, because the custom linker script |
||||
-is needed for full RELRO protection. |
||||
+@item --with-default-link |
||||
+With @code{--with-default-link}, the build system does not use a custom |
||||
+linker script for linking shared objects. The default is |
||||
+@code{--without-default-link}, because the custom linker script is |
||||
+needed for full RELRO protection. |
||||
|
||||
@item --with-nonshared-cflags=@var{cflags} |
||||
Use additional compiler flags @var{cflags} to build the parts of the |
@ -0,0 +1,377 @@
@@ -0,0 +1,377 @@
|
||||
commit bc56ab1f4aa937665034373d3e320d0779a839aa |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Apr 26 14:23:02 2022 +0200 |
||||
|
||||
dlfcn: Do not use rtld_active () to determine ld.so state (bug 29078) |
||||
|
||||
When audit modules are loaded, ld.so initialization is not yet |
||||
complete, and rtld_active () returns false even though ld.so is |
||||
mostly working. Instead, the static dlopen hook is used, but that |
||||
does not work at all because this is not a static dlopen situation. |
||||
|
||||
Commit 466c1ea15f461edb8e3ffaf5d86d708876343bbf ("dlfcn: Rework |
||||
static dlopen hooks") moved the hook pointer into _rtld_global_ro, |
||||
which means that separate protection is not needed anymore and the |
||||
hook pointer can be checked directly. |
||||
|
||||
The guard for disabling libio vtable hardening in _IO_vtable_check |
||||
should stay for now. |
||||
|
||||
Fixes commit 8e1472d2c1e25e6eabc2059170731365f6d5b3d1 ("ld.so: |
||||
Examine GLRO to detect inactive loader [BZ #20204]"). |
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit 8dcb6d0af07fda3607b541857e4f3970a74ed55b) |
||||
|
||||
diff --git a/dlfcn/dladdr.c b/dlfcn/dladdr.c |
||||
index 1cc305f0c46e7c3b..0d07ae1cd4dbb7a2 100644 |
||||
--- a/dlfcn/dladdr.c |
||||
+++ b/dlfcn/dladdr.c |
||||
@@ -24,7 +24,7 @@ int |
||||
__dladdr (const void *address, Dl_info *info) |
||||
{ |
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dladdr (address, info); |
||||
#endif |
||||
return _dl_addr (address, info, NULL, NULL); |
||||
diff --git a/dlfcn/dladdr1.c b/dlfcn/dladdr1.c |
||||
index 78560dbac208c316..93ce68c1d6067fe2 100644 |
||||
--- a/dlfcn/dladdr1.c |
||||
+++ b/dlfcn/dladdr1.c |
||||
@@ -24,7 +24,7 @@ int |
||||
__dladdr1 (const void *address, Dl_info *info, void **extra, int flags) |
||||
{ |
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dladdr1 (address, info, extra, flags); |
||||
#endif |
||||
|
||||
diff --git a/dlfcn/dlclose.c b/dlfcn/dlclose.c |
||||
index 6a013a81bb648191..07ecb21bf7d43be4 100644 |
||||
--- a/dlfcn/dlclose.c |
||||
+++ b/dlfcn/dlclose.c |
||||
@@ -24,7 +24,7 @@ int |
||||
__dlclose (void *handle) |
||||
{ |
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlclose (handle); |
||||
#endif |
||||
|
||||
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c |
||||
index 5047b140662bc33e..63da79c63000eef0 100644 |
||||
--- a/dlfcn/dlerror.c |
||||
+++ b/dlfcn/dlerror.c |
||||
@@ -32,7 +32,7 @@ char * |
||||
__dlerror (void) |
||||
{ |
||||
# ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlerror (); |
||||
# endif |
||||
|
||||
diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c |
||||
index c6f9a1da09ff8622..47d2daa96fa5986f 100644 |
||||
--- a/dlfcn/dlinfo.c |
||||
+++ b/dlfcn/dlinfo.c |
||||
@@ -89,7 +89,7 @@ dlinfo_implementation (void *handle, int request, void *arg) |
||||
int |
||||
___dlinfo (void *handle, int request, void *arg) |
||||
{ |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg); |
||||
else |
||||
return dlinfo_implementation (handle, request, arg); |
||||
diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c |
||||
index c171c8953da20fc7..2309224eb8484b1a 100644 |
||||
--- a/dlfcn/dlmopen.c |
||||
+++ b/dlfcn/dlmopen.c |
||||
@@ -80,7 +80,7 @@ dlmopen_implementation (Lmid_t nsid, const char *file, int mode, |
||||
void * |
||||
___dlmopen (Lmid_t nsid, const char *file, int mode) |
||||
{ |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlmopen (nsid, file, mode, RETURN_ADDRESS (0)); |
||||
else |
||||
return dlmopen_implementation (nsid, file, mode, RETURN_ADDRESS (0)); |
||||
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c |
||||
index e04b374b82b04337..9c59c751c4eaf7a7 100644 |
||||
--- a/dlfcn/dlopen.c |
||||
+++ b/dlfcn/dlopen.c |
||||
@@ -75,7 +75,7 @@ dlopen_implementation (const char *file, int mode, void *dl_caller) |
||||
void * |
||||
___dlopen (const char *file, int mode) |
||||
{ |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0)); |
||||
else |
||||
return dlopen_implementation (file, mode, RETURN_ADDRESS (0)); |
||||
diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c |
||||
index 9115501ac121eeca..c2f2a42194d50953 100644 |
||||
--- a/dlfcn/dlopenold.c |
||||
+++ b/dlfcn/dlopenold.c |
||||
@@ -70,7 +70,7 @@ __dlopen_nocheck (const char *file, int mode) |
||||
mode |= RTLD_LAZY; |
||||
args.mode = mode; |
||||
|
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0)); |
||||
|
||||
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new; |
||||
diff --git a/dlfcn/dlsym.c b/dlfcn/dlsym.c |
||||
index 43044cf7bb95801e..d3861170a7631d01 100644 |
||||
--- a/dlfcn/dlsym.c |
||||
+++ b/dlfcn/dlsym.c |
||||
@@ -62,7 +62,7 @@ dlsym_implementation (void *handle, const char *name, void *dl_caller) |
||||
void * |
||||
___dlsym (void *handle, const char *name) |
||||
{ |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlsym (handle, name, RETURN_ADDRESS (0)); |
||||
else |
||||
return dlsym_implementation (handle, name, RETURN_ADDRESS (0)); |
||||
diff --git a/dlfcn/dlvsym.c b/dlfcn/dlvsym.c |
||||
index 9b76f9afa513e11f..3af02109c306b800 100644 |
||||
--- a/dlfcn/dlvsym.c |
||||
+++ b/dlfcn/dlvsym.c |
||||
@@ -65,7 +65,7 @@ dlvsym_implementation (void *handle, const char *name, const char *version, |
||||
void * |
||||
___dlvsym (void *handle, const char *name, const char *version) |
||||
{ |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->dlvsym (handle, name, version, |
||||
RETURN_ADDRESS (0)); |
||||
else |
||||
diff --git a/elf/Makefile b/elf/Makefile |
||||
index fec6e23b5b625e3b..c89a6a58690646ee 100644 |
||||
--- a/elf/Makefile |
||||
+++ b/elf/Makefile |
||||
@@ -376,6 +376,7 @@ tests += \ |
||||
tst-audit24d \ |
||||
tst-audit25a \ |
||||
tst-audit25b \ |
||||
+ tst-audit26 \ |
||||
tst-auditmany \ |
||||
tst-auxobj \ |
||||
tst-auxobj-dlopen \ |
||||
@@ -721,6 +722,7 @@ modules-names = \ |
||||
tst-auditmod24c \ |
||||
tst-auditmod24d \ |
||||
tst-auditmod25 \ |
||||
+ tst-auditmod26 \ |
||||
tst-auxvalmod \ |
||||
tst-big-note-lib \ |
||||
tst-deep1mod1 \ |
||||
@@ -2194,6 +2196,10 @@ $(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \ |
||||
LDFLAGS-tst-audit25b = -Wl,-z,now |
||||
tst-audit25b-ARGS = -- $(host-test-program-cmd) |
||||
|
||||
+$(objpfx)tst-audit26.out: $(objpfx)tst-auditmod26.so |
||||
+$(objpfx)tst-auditmod26.so: $(libsupport) |
||||
+tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so |
||||
+ |
||||
# tst-sonamemove links against an older implementation of the library. |
||||
LDFLAGS-tst-sonamemove-linkmod1.so = \ |
||||
-Wl,--version-script=tst-sonamemove-linkmod1.map \ |
||||
diff --git a/elf/dl-libc.c b/elf/dl-libc.c |
||||
index d5bc4a277f4c6ef3..db4342a3256921f0 100644 |
||||
--- a/elf/dl-libc.c |
||||
+++ b/elf/dl-libc.c |
||||
@@ -157,7 +157,7 @@ __libc_dlopen_mode (const char *name, int mode) |
||||
args.caller_dlopen = RETURN_ADDRESS (0); |
||||
|
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->libc_dlopen_mode (name, mode); |
||||
#endif |
||||
return dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map; |
||||
@@ -185,7 +185,7 @@ __libc_dlsym (void *map, const char *name) |
||||
args.name = name; |
||||
|
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->libc_dlsym (map, name); |
||||
#endif |
||||
return (dlerror_run (do_dlsym, &args) ? NULL |
||||
@@ -199,7 +199,7 @@ void * |
||||
__libc_dlvsym (void *map, const char *name, const char *version) |
||||
{ |
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->libc_dlvsym (map, name, version); |
||||
#endif |
||||
|
||||
@@ -222,7 +222,7 @@ int |
||||
__libc_dlclose (void *map) |
||||
{ |
||||
#ifdef SHARED |
||||
- if (!rtld_active ()) |
||||
+ if (GLRO (dl_dlfcn_hook) != NULL) |
||||
return GLRO (dl_dlfcn_hook)->libc_dlclose (map); |
||||
#endif |
||||
return dlerror_run (do_dlclose, map); |
||||
diff --git a/elf/tst-audit26.c b/elf/tst-audit26.c |
||||
new file mode 100644 |
||||
index 0000000000000000..3f920e83bac247a5 |
||||
--- /dev/null |
||||
+++ b/elf/tst-audit26.c |
||||
@@ -0,0 +1,35 @@ |
||||
+/* Check the usability of <dlfcn.h> functions in audit modules. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <gnu/lib-names.h> |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ /* Check that the audit module has been loaded. */ |
||||
+ void *handle = xdlopen ("mapped to libc", RTLD_LOCAL | RTLD_NOW); |
||||
+ TEST_VERIFY (handle |
||||
+ == xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD)); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-auditmod26.c b/elf/tst-auditmod26.c |
||||
new file mode 100644 |
||||
index 0000000000000000..db7ba95abec20f53 |
||||
--- /dev/null |
||||
+++ b/elf/tst-auditmod26.c |
||||
@@ -0,0 +1,104 @@ |
||||
+/* Check the usability of <dlfcn.h> functions in audit modules. Audit module. |
||||
+ Copyright (C) 2022 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <dlfcn.h> |
||||
+#include <first-versions.h> |
||||
+#include <gnu/lib-names.h> |
||||
+#include <link.h> |
||||
+#include <stdio.h> |
||||
+#include <string.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+ |
||||
+unsigned int |
||||
+la_version (unsigned int current) |
||||
+{ |
||||
+ /* Exercise various <dlfcn.h> functions. */ |
||||
+ |
||||
+ /* Check dlopen, dlsym, dlclose. */ |
||||
+ void *handle = xdlopen (LIBM_SO, RTLD_LOCAL | RTLD_NOW); |
||||
+ void *ptr = xdlsym (handle, "sincos"); |
||||
+ TEST_VERIFY (ptr != NULL); |
||||
+ ptr = dlsym (handle, "SINCOS"); |
||||
+ TEST_VERIFY (ptr == NULL); |
||||
+ const char *message = dlerror (); |
||||
+ TEST_VERIFY (strstr (message, ": undefined symbol: SINCOS") != NULL); |
||||
+ ptr = dlsym (handle, "SINCOS"); |
||||
+ TEST_VERIFY (ptr == NULL); |
||||
+ xdlclose (handle); |
||||
+ TEST_COMPARE_STRING (dlerror (), NULL); |
||||
+ |
||||
+ handle = xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD); |
||||
+ |
||||
+ /* Check dlvsym. _exit is unlikely to gain another symbol |
||||
+ version. */ |
||||
+ TEST_VERIFY (xdlsym (handle, "_exit") |
||||
+ == xdlvsym (handle, "_exit", FIRST_VERSION_libc__exit_STRING)); |
||||
+ |
||||
+ /* Check dlinfo. */ |
||||
+ { |
||||
+ void *handle2 = NULL; |
||||
+ TEST_COMPARE (dlinfo (handle, RTLD_DI_LINKMAP, &handle2), 0); |
||||
+ TEST_VERIFY (handle2 == handle); |
||||
+ } |
||||
+ |
||||
+ /* Check dladdr and dladdr1. */ |
||||
+ Dl_info info = { }; |
||||
+ TEST_VERIFY (dladdr (&_exit, &info) != 0); |
||||
+ if (strcmp (info.dli_sname, "_Exit") != 0) /* _Exit is an alias. */ |
||||
+ TEST_COMPARE_STRING (info.dli_sname, "_exit"); |
||||
+ TEST_VERIFY (info.dli_saddr == &_exit); |
||||
+ TEST_VERIFY (strstr (info.dli_fname, LIBC_SO)); |
||||
+ void *extra_info; |
||||
+ memset (&info, 0, sizeof (info)); |
||||
+ TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0); |
||||
+ TEST_VERIFY (extra_info == handle); |
||||
+ |
||||
+ /* Verify that dlmopen creates a new namespace. */ |
||||
+ void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); |
||||
+ TEST_VERIFY (dlmopen_handle != handle); |
||||
+ memset (&info, 0, sizeof (info)); |
||||
+ extra_info = NULL; |
||||
+ ptr = xdlsym (dlmopen_handle, "_exit"); |
||||
+ TEST_VERIFY (dladdr1 (ptr, &info, &extra_info, RTLD_DL_LINKMAP) != 0); |
||||
+ TEST_VERIFY (extra_info == dlmopen_handle); |
||||
+ xdlclose (dlmopen_handle); |
||||
+ |
||||
+ /* Terminate the process with an error state. This does not happen |
||||
+ automatically because the audit module state is not shared with |
||||
+ the main program. */ |
||||
+ if (support_record_failure_is_failed ()) |
||||
+ { |
||||
+ fflush (stdout); |
||||
+ fflush (stderr); |
||||
+ _exit (1); |
||||
+ } |
||||
+ |
||||
+ return LAV_CURRENT; |
||||
+} |
||||
+ |
||||
+char * |
||||
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) |
||||
+{ |
||||
+ if (strcmp (name, "mapped to libc") == 0) |
||||
+ return (char *) LIBC_SO; |
||||
+ else |
||||
+ return (char *) name; |
||||
+} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
commit 83cc145830bdbefdabe03787ed884d548bea9c99 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Apr 22 19:34:52 2022 +0200 |
||||
|
||||
scripts/glibcelf.py: Mark as UNSUPPORTED on Python 3.5 and earlier |
||||
|
||||
enum.IntFlag and enum.EnumMeta._missing_ support are not part of |
||||
earlier Python versions. |
||||
|
||||
(cherry picked from commit b571f3adffdcbed23f35ea39b0ca43809dbb4f5b) |
||||
|
||||
diff --git a/scripts/glibcelf.py b/scripts/glibcelf.py |
||||
index 8f7d0ca184845714..da0d5380f33a195e 100644 |
||||
--- a/scripts/glibcelf.py |
||||
+++ b/scripts/glibcelf.py |
||||
@@ -28,6 +28,12 @@ import collections |
||||
import enum |
||||
import struct |
||||
|
||||
+if not hasattr(enum, 'IntFlag'): |
||||
+ import sys |
||||
+ sys.stdout.write( |
||||
+ 'warning: glibcelf.py needs Python 3.6 for enum support\n') |
||||
+ sys.exit(77) |
||||
+ |
||||
class _OpenIntEnum(enum.IntEnum): |
||||
"""Integer enumeration that supports arbitrary int values.""" |
||||
@classmethod |
@ -0,0 +1,254 @@
@@ -0,0 +1,254 @@
|
||||
commit 16245986fb9bfe396113fc7dfd1929f69a9e748e |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Fri Aug 20 06:42:24 2021 -0700 |
||||
|
||||
x86-64: Optimize load of all bits set into ZMM register [BZ #28252] |
||||
|
||||
Optimize loads of all bits set into ZMM register in AVX512 SVML codes |
||||
by replacing |
||||
|
||||
vpbroadcastq .L_2il0floatpacket.16(%rip), %zmmX |
||||
|
||||
and |
||||
|
||||
vmovups .L_2il0floatpacket.13(%rip), %zmmX |
||||
|
||||
with |
||||
vpternlogd $0xff, %zmmX, %zmmX, %zmmX |
||||
|
||||
This fixes BZ #28252. |
||||
|
||||
(cherry picked from commit 78c9ec9000f873abe7a15a91b87080a2e4308260) |
||||
|
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S |
||||
index e68fcdbb16a79f36..58e588a3d42a8bc9 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S |
||||
@@ -265,7 +265,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos |
||||
vmovaps %zmm0, %zmm8 |
||||
|
||||
/* Check for large arguments path */ |
||||
- vpbroadcastq .L_2il0floatpacket.16(%rip), %zmm2 |
||||
+ vpternlogd $0xff, %zmm2, %zmm2, %zmm2 |
||||
|
||||
/* |
||||
ARGUMENT RANGE REDUCTION: |
||||
@@ -456,8 +456,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN8v_cos_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.16: |
||||
- .long 0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.16,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S |
||||
index dfa2acafc486b56b..f5f117d474f66176 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S |
||||
@@ -274,7 +274,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log |
||||
|
||||
/* preserve mantissa, set input exponent to 2^(-10) */ |
||||
vpternlogq $248, _ExpMask(%rax), %zmm3, %zmm2 |
||||
- vpbroadcastq .L_2il0floatpacket.12(%rip), %zmm1 |
||||
+ vpternlogd $0xff, %zmm1, %zmm1, %zmm1 |
||||
vpsrlq $32, %zmm4, %zmm6 |
||||
|
||||
/* reciprocal approximation good to at least 11 bits */ |
||||
@@ -461,8 +461,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN8v_log_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.12: |
||||
- .long 0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.12,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S |
||||
index be8ab7c6e0e33819..48d251db16ccab9d 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S |
||||
@@ -261,7 +261,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin |
||||
andq $-64, %rsp |
||||
subq $1280, %rsp |
||||
movq __svml_d_trig_data@GOTPCREL(%rip), %rax |
||||
- vpbroadcastq .L_2il0floatpacket.14(%rip), %zmm14 |
||||
+ vpternlogd $0xff, %zmm1, %zmm1, %zmm14 |
||||
vmovups __dAbsMask(%rax), %zmm7 |
||||
vmovups __dInvPI(%rax), %zmm2 |
||||
vmovups __dRShifter(%rax), %zmm1 |
||||
@@ -458,8 +458,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN8v_sin_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.14: |
||||
- .long 0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.14,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S |
||||
index 611887082a545854..a4944a4feef6aa98 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S |
||||
@@ -430,7 +430,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN4vl8l8_sincos |
||||
|
||||
/* SinPoly = SinR*SinPoly */ |
||||
vfmadd213pd %zmm5, %zmm5, %zmm4 |
||||
- vpbroadcastq .L_2il0floatpacket.15(%rip), %zmm3 |
||||
+ vpternlogd $0xff, %zmm3, %zmm3, %zmm3 |
||||
|
||||
/* Update Cos result's sign */ |
||||
vxorpd %zmm2, %zmm1, %zmm1 |
||||
@@ -741,8 +741,3 @@ END (_ZGVeN8vvv_sincos_knl) |
||||
ENTRY (_ZGVeN8vvv_sincos_skx) |
||||
WRAPPER_AVX512_vvv_vl8l8 _ZGVeN8vl8l8_sincos_skx |
||||
END (_ZGVeN8vvv_sincos_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.15: |
||||
- .long 0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.15,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S |
||||
index f671d60d5dab5a0e..fe8474fed943e8ad 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S |
||||
@@ -278,7 +278,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf |
||||
X = X - Y*PI1 - Y*PI2 - Y*PI3 |
||||
*/ |
||||
vmovaps %zmm0, %zmm6 |
||||
- vmovups .L_2il0floatpacket.13(%rip), %zmm12 |
||||
+ vpternlogd $0xff, %zmm12, %zmm12, %zmm12 |
||||
vmovups __sRShifter(%rax), %zmm3 |
||||
vmovups __sPI1_FMA(%rax), %zmm5 |
||||
vmovups __sA9_FMA(%rax), %zmm9 |
||||
@@ -453,8 +453,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN16v_cosf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.13: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.13,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S |
||||
index 637bfe3c06ab9ad4..229b7828cde04db2 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S |
||||
@@ -264,7 +264,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf |
||||
vmovaps %zmm0, %zmm7 |
||||
|
||||
/* compare against threshold */ |
||||
- vmovups .L_2il0floatpacket.13(%rip), %zmm3 |
||||
+ vpternlogd $0xff, %zmm3, %zmm3, %zmm3 |
||||
vmovups __sInvLn2(%rax), %zmm4 |
||||
vmovups __sShifter(%rax), %zmm1 |
||||
vmovups __sLn2hi(%rax), %zmm6 |
||||
@@ -440,8 +440,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf |
||||
|
||||
#endif |
||||
END (_ZGVeN16v_expf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.13: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.13,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S |
||||
index 9d790fbf0ad6c8ec..fa2aae986f543582 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S |
||||
@@ -235,7 +235,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf |
||||
andq $-64, %rsp |
||||
subq $1280, %rsp |
||||
movq __svml_slog_data@GOTPCREL(%rip), %rax |
||||
- vmovups .L_2il0floatpacket.7(%rip), %zmm6 |
||||
+ vpternlogd $0xff, %zmm6, %zmm6, %zmm6 |
||||
vmovups _iBrkValue(%rax), %zmm4 |
||||
vmovups _sPoly_7(%rax), %zmm8 |
||||
|
||||
@@ -409,8 +409,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf |
||||
|
||||
#endif |
||||
END (_ZGVeN16v_logf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.7: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.7,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S |
||||
index c5c43c46ff7af5a3..6aea2a4f11d1f85f 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S |
||||
@@ -385,7 +385,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf |
||||
vpsrlq $32, %zmm3, %zmm2 |
||||
vpmovqd %zmm2, %ymm11 |
||||
vcvtps2pd %ymm14, %zmm13 |
||||
- vmovups .L_2il0floatpacket.23(%rip), %zmm14 |
||||
+ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 |
||||
vmovaps %zmm14, %zmm26 |
||||
vpandd _ABSMASK(%rax), %zmm1, %zmm8 |
||||
vpcmpd $1, _INF(%rax), %zmm8, %k2 |
||||
@@ -427,7 +427,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf |
||||
vpmovqd %zmm11, %ymm5 |
||||
vpxord %zmm10, %zmm10, %zmm10 |
||||
vgatherdpd _Log2Rcp_lookup(%rax,%ymm4), %zmm10{%k3} |
||||
- vpbroadcastq .L_2il0floatpacket.24(%rip), %zmm4 |
||||
+ vpternlogd $0xff, %zmm4, %zmm4, %zmm4 |
||||
vpxord %zmm11, %zmm11, %zmm11 |
||||
vcvtdq2pd %ymm7, %zmm7 |
||||
vgatherdpd _Log2Rcp_lookup(%rax,%ymm5), %zmm11{%k1} |
||||
@@ -643,11 +643,3 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN16vv_powf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.23: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.23,@object |
||||
-.L_2il0floatpacket.24: |
||||
- .long 0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.24,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S |
||||
index 9cf359c86ff9bd70..a446c504f63c9399 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S |
||||
@@ -317,7 +317,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN8vvv_sincosf |
||||
|
||||
/* Result sign calculations */ |
||||
vpternlogd $150, %zmm0, %zmm14, %zmm1 |
||||
- vmovups .L_2il0floatpacket.13(%rip), %zmm14 |
||||
+ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 |
||||
|
||||
/* Add correction term 0.5 for cos() part */ |
||||
vaddps %zmm8, %zmm5, %zmm15 |
||||
@@ -748,8 +748,3 @@ END (_ZGVeN16vvv_sincosf_knl) |
||||
ENTRY (_ZGVeN16vvv_sincosf_skx) |
||||
WRAPPER_AVX512_vvv_vl4l4 _ZGVeN16vl4l4_sincosf_skx |
||||
END (_ZGVeN16vvv_sincosf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.13: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.13,@object |
||||
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S |
||||
index bd05109a62181f22..c1b352d0ad1992cd 100644 |
||||
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S |
||||
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S |
||||
@@ -280,7 +280,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf |
||||
movq __svml_s_trig_data@GOTPCREL(%rip), %rax |
||||
|
||||
/* Check for large and special values */ |
||||
- vmovups .L_2il0floatpacket.11(%rip), %zmm14 |
||||
+ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 |
||||
vmovups __sAbsMask(%rax), %zmm5 |
||||
vmovups __sInvPI(%rax), %zmm1 |
||||
vmovups __sRShifter(%rax), %zmm2 |
||||
@@ -472,8 +472,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf |
||||
jmp .LBL_2_7 |
||||
#endif |
||||
END (_ZGVeN16v_sinf_skx) |
||||
- |
||||
- .section .rodata, "a" |
||||
-.L_2il0floatpacket.11: |
||||
- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff |
||||
- .type .L_2il0floatpacket.11,@object |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
commit b5a44a6a471aafd3677659a610f32468c40a666b |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Tue Sep 21 18:31:49 2021 -0500 |
||||
|
||||
x86: Modify ENTRY in sysdep.h so that p2align can be specified |
||||
|
||||
No bug. |
||||
|
||||
This change adds a new macro ENTRY_P2ALIGN which takes a second |
||||
argument, log2 of the desired function alignment. |
||||
|
||||
The old ENTRY(name) macro is just ENTRY_P2ALIGN(name, 4) so this |
||||
doesn't affect any existing functionality. |
||||
|
||||
Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
(cherry picked from commit fc5bd179ef3a953dff8d1655bd530d0e230ffe71) |
||||
|
||||
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h |
||||
index cac1d762fb3f99d0..937180c1bd791570 100644 |
||||
--- a/sysdeps/x86/sysdep.h |
||||
+++ b/sysdeps/x86/sysdep.h |
||||
@@ -78,15 +78,18 @@ enum cf_protection_level |
||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; |
||||
|
||||
/* Define an entry point visible from C. */ |
||||
-#define ENTRY(name) \ |
||||
+#define ENTRY_P2ALIGN(name, alignment) \ |
||||
.globl C_SYMBOL_NAME(name); \ |
||||
.type C_SYMBOL_NAME(name),@function; \ |
||||
- .align ALIGNARG(4); \ |
||||
+ .align ALIGNARG(alignment); \ |
||||
C_LABEL(name) \ |
||||
cfi_startproc; \ |
||||
_CET_ENDBR; \ |
||||
CALL_MCOUNT |
||||
|
||||
+/* Common entry 16 byte aligns. */ |
||||
+#define ENTRY(name) ENTRY_P2ALIGN (name, 4) |
||||
+ |
||||
#undef END |
||||
#define END(name) \ |
||||
cfi_endproc; \ |
@ -0,0 +1,653 @@
@@ -0,0 +1,653 @@
|
||||
commit 5ec3416853c4150c4d13312e05f93a053586d528 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Tue Sep 21 18:45:03 2021 -0500 |
||||
|
||||
x86: Optimize memcmp-evex-movbe.S for frontend behavior and size |
||||
|
||||
No bug. |
||||
|
||||
The frontend optimizations are to: |
||||
1. Reorganize logically connected basic blocks so they are either in |
||||
the same cache line or adjacent cache lines. |
||||
2. Avoid cases when basic blocks unnecissarily cross cache lines. |
||||
3. Try and 32 byte align any basic blocks possible without sacrificing |
||||
code size. Smaller / Less hot basic blocks are used for this. |
||||
|
||||
Overall code size shrunk by 168 bytes. This should make up for any |
||||
extra costs due to aligning to 64 bytes. |
||||
|
||||
In general performance before deviated a great deal dependending on |
||||
whether entry alignment % 64 was 0, 16, 32, or 48. These changes |
||||
essentially make it so that the current implementation is at least |
||||
equal to the best alignment of the original for any arguments. |
||||
|
||||
The only additional optimization is in the page cross case. Branch on |
||||
equals case was removed from the size == [4, 7] case. As well the [4, |
||||
7] and [2, 3] case where swapped as [4, 7] is likely a more hot |
||||
argument size. |
||||
|
||||
test-memcmp and test-wmemcmp are both passing. |
||||
|
||||
(cherry picked from commit 1bd8b8d58fc9967cc073d2c13bfb6befefca2faa) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
index 654dc7ac8ccb9445..2761b54f2e7dea9f 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
+++ b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
@@ -34,7 +34,24 @@ |
||||
area. |
||||
7. Use 2 vector compares when size is 2 * CHAR_PER_VEC or less. |
||||
8. Use 4 vector compares when size is 4 * CHAR_PER_VEC or less. |
||||
- 9. Use 8 vector compares when size is 8 * CHAR_PER_VEC or less. */ |
||||
+ 9. Use 8 vector compares when size is 8 * CHAR_PER_VEC or less. |
||||
+ |
||||
+When possible the implementation tries to optimize for frontend in the |
||||
+following ways: |
||||
+Throughput: |
||||
+ 1. All code sections that fit are able to run optimally out of the |
||||
+ LSD. |
||||
+ 2. All code sections that fit are able to run optimally out of the |
||||
+ DSB |
||||
+ 3. Basic blocks are contained in minimum number of fetch blocks |
||||
+ necessary. |
||||
+ |
||||
+Latency: |
||||
+ 1. Logically connected basic blocks are put in the same |
||||
+ cache-line. |
||||
+ 2. Logically connected basic blocks that do not fit in the same |
||||
+ cache-line are put in adjacent lines. This can get beneficial |
||||
+ L2 spatial prefetching and L1 next-line prefetching. */ |
||||
|
||||
# include <sysdep.h> |
||||
|
||||
@@ -47,9 +64,11 @@ |
||||
# ifdef USE_AS_WMEMCMP |
||||
# define CHAR_SIZE 4 |
||||
# define VPCMP vpcmpd |
||||
+# define VPTEST vptestmd |
||||
# else |
||||
# define CHAR_SIZE 1 |
||||
# define VPCMP vpcmpub |
||||
+# define VPTEST vptestmb |
||||
# endif |
||||
|
||||
# define VEC_SIZE 32 |
||||
@@ -75,7 +94,9 @@ |
||||
*/ |
||||
|
||||
.section .text.evex,"ax",@progbits |
||||
-ENTRY (MEMCMP) |
||||
+/* Cache align memcmp entry. This allows for much more thorough |
||||
+ frontend optimization. */ |
||||
+ENTRY_P2ALIGN (MEMCMP, 6) |
||||
# ifdef __ILP32__ |
||||
/* Clear the upper 32 bits. */ |
||||
movl %edx, %edx |
||||
@@ -89,7 +110,7 @@ ENTRY (MEMCMP) |
||||
VPCMP $4, (%rdi), %YMM1, %k1 |
||||
kmovd %k1, %eax |
||||
/* NB: eax must be destination register if going to |
||||
- L(return_vec_[0,2]). For L(return_vec_3 destination register |
||||
+ L(return_vec_[0,2]). For L(return_vec_3) destination register |
||||
must be ecx. */ |
||||
testl %eax, %eax |
||||
jnz L(return_vec_0) |
||||
@@ -121,10 +142,6 @@ ENTRY (MEMCMP) |
||||
testl %ecx, %ecx |
||||
jnz L(return_vec_3) |
||||
|
||||
- /* Zero YMM0. 4x VEC reduction is done with vpxor + vtern so |
||||
- compare with zero to get a mask is needed. */ |
||||
- vpxorq %XMM0, %XMM0, %XMM0 |
||||
- |
||||
/* Go to 4x VEC loop. */ |
||||
cmpq $(CHAR_PER_VEC * 8), %rdx |
||||
ja L(more_8x_vec) |
||||
@@ -148,47 +165,61 @@ ENTRY (MEMCMP) |
||||
|
||||
VMOVU (VEC_SIZE * 2)(%rsi), %YMM3 |
||||
vpxorq (VEC_SIZE * 2)(%rdi), %YMM3, %YMM3 |
||||
- /* Or together YMM1, YMM2, and YMM3 into YMM3. */ |
||||
- vpternlogd $0xfe, %YMM1, %YMM2, %YMM3 |
||||
|
||||
VMOVU (VEC_SIZE * 3)(%rsi), %YMM4 |
||||
/* Ternary logic to xor (VEC_SIZE * 3)(%rdi) with YMM4 while |
||||
- oring with YMM3. Result is stored in YMM4. */ |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM3, %YMM4 |
||||
- /* Compare YMM4 with 0. If any 1s s1 and s2 don't match. */ |
||||
- VPCMP $4, %YMM4, %YMM0, %k1 |
||||
+ oring with YMM1. Result is stored in YMM4. */ |
||||
+ vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
+ |
||||
+ /* Or together YMM2, YMM3, and YMM4 into YMM4. */ |
||||
+ vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
+ |
||||
+ /* Test YMM4 against itself. Store any CHAR mismatches in k1. |
||||
+ */ |
||||
+ VPTEST %YMM4, %YMM4, %k1 |
||||
+ /* k1 must go to ecx for L(return_vec_0_1_2_3). */ |
||||
kmovd %k1, %ecx |
||||
testl %ecx, %ecx |
||||
jnz L(return_vec_0_1_2_3) |
||||
/* NB: eax must be zero to reach here. */ |
||||
ret |
||||
|
||||
- /* NB: aligning 32 here allows for the rest of the jump targets |
||||
- to be tuned for 32 byte alignment. Most important this ensures |
||||
- the L(more_8x_vec) loop is 32 byte aligned. */ |
||||
- .p2align 5 |
||||
-L(less_vec): |
||||
- /* Check if one or less CHAR. This is necessary for size = 0 but |
||||
- is also faster for size = CHAR_SIZE. */ |
||||
- cmpl $1, %edx |
||||
- jbe L(one_or_less) |
||||
+ .p2align 4 |
||||
+L(8x_end_return_vec_0_1_2_3): |
||||
+ movq %rdx, %rdi |
||||
+L(8x_return_vec_0_1_2_3): |
||||
+ addq %rdi, %rsi |
||||
+L(return_vec_0_1_2_3): |
||||
+ VPTEST %YMM1, %YMM1, %k0 |
||||
+ kmovd %k0, %eax |
||||
+ testl %eax, %eax |
||||
+ jnz L(return_vec_0) |
||||
|
||||
- /* Check if loading one VEC from either s1 or s2 could cause a |
||||
- page cross. This can have false positives but is by far the |
||||
- fastest method. */ |
||||
- movl %edi, %eax |
||||
- orl %esi, %eax |
||||
- andl $(PAGE_SIZE - 1), %eax |
||||
- cmpl $(PAGE_SIZE - VEC_SIZE), %eax |
||||
- jg L(page_cross_less_vec) |
||||
+ VPTEST %YMM2, %YMM2, %k0 |
||||
+ kmovd %k0, %eax |
||||
+ testl %eax, %eax |
||||
+ jnz L(return_vec_1) |
||||
|
||||
- /* No page cross possible. */ |
||||
- VMOVU (%rsi), %YMM2 |
||||
- VPCMP $4, (%rdi), %YMM2, %k1 |
||||
- kmovd %k1, %eax |
||||
- /* Create mask in ecx for potentially in bound matches. */ |
||||
- bzhil %edx, %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
+ VPTEST %YMM3, %YMM3, %k0 |
||||
+ kmovd %k0, %eax |
||||
+ testl %eax, %eax |
||||
+ jnz L(return_vec_2) |
||||
+L(return_vec_3): |
||||
+ /* bsf saves 1 byte from tzcnt. This keep L(return_vec_3) in one |
||||
+ fetch block and the entire L(*return_vec_0_1_2_3) in 1 cache |
||||
+ line. */ |
||||
+ bsfl %ecx, %ecx |
||||
+# ifdef USE_AS_WMEMCMP |
||||
+ movl (VEC_SIZE * 3)(%rdi, %rcx, CHAR_SIZE), %eax |
||||
+ xorl %edx, %edx |
||||
+ cmpl (VEC_SIZE * 3)(%rsi, %rcx, CHAR_SIZE), %eax |
||||
+ setg %dl |
||||
+ leal -1(%rdx, %rdx), %eax |
||||
+# else |
||||
+ movzbl (VEC_SIZE * 3)(%rdi, %rcx), %eax |
||||
+ movzbl (VEC_SIZE * 3)(%rsi, %rcx), %ecx |
||||
+ subl %ecx, %eax |
||||
+# endif |
||||
ret |
||||
|
||||
.p2align 4 |
||||
@@ -209,10 +240,11 @@ L(return_vec_0): |
||||
# endif |
||||
ret |
||||
|
||||
- /* NB: No p2align necessary. Alignment % 16 is naturally 1 |
||||
- which is good enough for a target not in a loop. */ |
||||
+ .p2align 4 |
||||
L(return_vec_1): |
||||
- tzcntl %eax, %eax |
||||
+ /* bsf saves 1 byte over tzcnt and keeps L(return_vec_1) in one |
||||
+ fetch block. */ |
||||
+ bsfl %eax, %eax |
||||
# ifdef USE_AS_WMEMCMP |
||||
movl VEC_SIZE(%rdi, %rax, CHAR_SIZE), %ecx |
||||
xorl %edx, %edx |
||||
@@ -226,10 +258,11 @@ L(return_vec_1): |
||||
# endif |
||||
ret |
||||
|
||||
- /* NB: No p2align necessary. Alignment % 16 is naturally 2 |
||||
- which is good enough for a target not in a loop. */ |
||||
+ .p2align 4,, 10 |
||||
L(return_vec_2): |
||||
- tzcntl %eax, %eax |
||||
+ /* bsf saves 1 byte over tzcnt and keeps L(return_vec_2) in one |
||||
+ fetch block. */ |
||||
+ bsfl %eax, %eax |
||||
# ifdef USE_AS_WMEMCMP |
||||
movl (VEC_SIZE * 2)(%rdi, %rax, CHAR_SIZE), %ecx |
||||
xorl %edx, %edx |
||||
@@ -243,40 +276,6 @@ L(return_vec_2): |
||||
# endif |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
-L(8x_return_vec_0_1_2_3): |
||||
- /* Returning from L(more_8x_vec) requires restoring rsi. */ |
||||
- addq %rdi, %rsi |
||||
-L(return_vec_0_1_2_3): |
||||
- VPCMP $4, %YMM1, %YMM0, %k0 |
||||
- kmovd %k0, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
- |
||||
- VPCMP $4, %YMM2, %YMM0, %k0 |
||||
- kmovd %k0, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_1) |
||||
- |
||||
- VPCMP $4, %YMM3, %YMM0, %k0 |
||||
- kmovd %k0, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_2) |
||||
-L(return_vec_3): |
||||
- tzcntl %ecx, %ecx |
||||
-# ifdef USE_AS_WMEMCMP |
||||
- movl (VEC_SIZE * 3)(%rdi, %rcx, CHAR_SIZE), %eax |
||||
- xorl %edx, %edx |
||||
- cmpl (VEC_SIZE * 3)(%rsi, %rcx, CHAR_SIZE), %eax |
||||
- setg %dl |
||||
- leal -1(%rdx, %rdx), %eax |
||||
-# else |
||||
- movzbl (VEC_SIZE * 3)(%rdi, %rcx), %eax |
||||
- movzbl (VEC_SIZE * 3)(%rsi, %rcx), %ecx |
||||
- subl %ecx, %eax |
||||
-# endif |
||||
- ret |
||||
- |
||||
.p2align 4 |
||||
L(more_8x_vec): |
||||
/* Set end of s1 in rdx. */ |
||||
@@ -288,21 +287,19 @@ L(more_8x_vec): |
||||
andq $-VEC_SIZE, %rdi |
||||
/* Adjust because first 4x vec where check already. */ |
||||
subq $-(VEC_SIZE * 4), %rdi |
||||
+ |
||||
.p2align 4 |
||||
L(loop_4x_vec): |
||||
VMOVU (%rsi, %rdi), %YMM1 |
||||
vpxorq (%rdi), %YMM1, %YMM1 |
||||
- |
||||
VMOVU VEC_SIZE(%rsi, %rdi), %YMM2 |
||||
vpxorq VEC_SIZE(%rdi), %YMM2, %YMM2 |
||||
- |
||||
VMOVU (VEC_SIZE * 2)(%rsi, %rdi), %YMM3 |
||||
vpxorq (VEC_SIZE * 2)(%rdi), %YMM3, %YMM3 |
||||
- vpternlogd $0xfe, %YMM1, %YMM2, %YMM3 |
||||
- |
||||
VMOVU (VEC_SIZE * 3)(%rsi, %rdi), %YMM4 |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM3, %YMM4 |
||||
- VPCMP $4, %YMM4, %YMM0, %k1 |
||||
+ vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
+ vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
+ VPTEST %YMM4, %YMM4, %k1 |
||||
kmovd %k1, %ecx |
||||
testl %ecx, %ecx |
||||
jnz L(8x_return_vec_0_1_2_3) |
||||
@@ -319,28 +316,25 @@ L(loop_4x_vec): |
||||
cmpl $(VEC_SIZE * 2), %edi |
||||
jae L(8x_last_2x_vec) |
||||
|
||||
+ vpxorq (VEC_SIZE * 2)(%rdx), %YMM3, %YMM3 |
||||
+ |
||||
VMOVU (%rsi, %rdx), %YMM1 |
||||
vpxorq (%rdx), %YMM1, %YMM1 |
||||
|
||||
VMOVU VEC_SIZE(%rsi, %rdx), %YMM2 |
||||
vpxorq VEC_SIZE(%rdx), %YMM2, %YMM2 |
||||
- |
||||
- vpxorq (VEC_SIZE * 2)(%rdx), %YMM3, %YMM3 |
||||
- vpternlogd $0xfe, %YMM1, %YMM2, %YMM3 |
||||
- |
||||
VMOVU (VEC_SIZE * 3)(%rsi, %rdx), %YMM4 |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdx), %YMM3, %YMM4 |
||||
- VPCMP $4, %YMM4, %YMM0, %k1 |
||||
+ vpternlogd $0xde, (VEC_SIZE * 3)(%rdx), %YMM1, %YMM4 |
||||
+ vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
+ VPTEST %YMM4, %YMM4, %k1 |
||||
kmovd %k1, %ecx |
||||
- /* Restore s1 pointer to rdi. */ |
||||
- movq %rdx, %rdi |
||||
testl %ecx, %ecx |
||||
- jnz L(8x_return_vec_0_1_2_3) |
||||
+ jnz L(8x_end_return_vec_0_1_2_3) |
||||
/* NB: eax must be zero to reach here. */ |
||||
ret |
||||
|
||||
/* Only entry is from L(more_8x_vec). */ |
||||
- .p2align 4 |
||||
+ .p2align 4,, 10 |
||||
L(8x_last_2x_vec): |
||||
VPCMP $4, (VEC_SIZE * 2)(%rdx), %YMM3, %k1 |
||||
kmovd %k1, %eax |
||||
@@ -355,7 +349,31 @@ L(8x_last_1x_vec): |
||||
jnz L(8x_return_vec_3) |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
+ /* Not ideally aligned (at offset +9 bytes in fetch block) but |
||||
+ not aligning keeps it in the same cache line as |
||||
+ L(8x_last_1x/2x_vec) so likely worth it. As well, saves code |
||||
+ size. */ |
||||
+ .p2align 4,, 4 |
||||
+L(8x_return_vec_2): |
||||
+ subq $VEC_SIZE, %rdx |
||||
+L(8x_return_vec_3): |
||||
+ bsfl %eax, %eax |
||||
+# ifdef USE_AS_WMEMCMP |
||||
+ leaq (%rdx, %rax, CHAR_SIZE), %rax |
||||
+ movl (VEC_SIZE * 3)(%rax), %ecx |
||||
+ xorl %edx, %edx |
||||
+ cmpl (VEC_SIZE * 3)(%rsi, %rax), %ecx |
||||
+ setg %dl |
||||
+ leal -1(%rdx, %rdx), %eax |
||||
+# else |
||||
+ addq %rdx, %rax |
||||
+ movzbl (VEC_SIZE * 3)(%rsi, %rax), %ecx |
||||
+ movzbl (VEC_SIZE * 3)(%rax), %eax |
||||
+ subl %ecx, %eax |
||||
+# endif |
||||
+ ret |
||||
+ |
||||
+ .p2align 4,, 10 |
||||
L(last_2x_vec): |
||||
/* Check second to last VEC. */ |
||||
VMOVU -(VEC_SIZE * 2)(%rsi, %rdx, CHAR_SIZE), %YMM1 |
||||
@@ -374,26 +392,49 @@ L(last_1x_vec): |
||||
jnz L(return_vec_0_end) |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
-L(8x_return_vec_2): |
||||
- subq $VEC_SIZE, %rdx |
||||
-L(8x_return_vec_3): |
||||
- tzcntl %eax, %eax |
||||
+ .p2align 4,, 10 |
||||
+L(return_vec_1_end): |
||||
+ /* Use bsf to save code size. This is necessary to have |
||||
+ L(one_or_less) fit in aligning bytes between. */ |
||||
+ bsfl %eax, %eax |
||||
+ addl %edx, %eax |
||||
# ifdef USE_AS_WMEMCMP |
||||
- leaq (%rdx, %rax, CHAR_SIZE), %rax |
||||
- movl (VEC_SIZE * 3)(%rax), %ecx |
||||
+ movl -(VEC_SIZE * 2)(%rdi, %rax, CHAR_SIZE), %ecx |
||||
xorl %edx, %edx |
||||
- cmpl (VEC_SIZE * 3)(%rsi, %rax), %ecx |
||||
+ cmpl -(VEC_SIZE * 2)(%rsi, %rax, CHAR_SIZE), %ecx |
||||
setg %dl |
||||
leal -1(%rdx, %rdx), %eax |
||||
# else |
||||
- addq %rdx, %rax |
||||
- movzbl (VEC_SIZE * 3)(%rsi, %rax), %ecx |
||||
- movzbl (VEC_SIZE * 3)(%rax), %eax |
||||
+ movzbl -(VEC_SIZE * 2)(%rsi, %rax), %ecx |
||||
+ movzbl -(VEC_SIZE * 2)(%rdi, %rax), %eax |
||||
subl %ecx, %eax |
||||
# endif |
||||
ret |
||||
|
||||
+ /* NB: L(one_or_less) fits in alignment padding between |
||||
+ L(return_vec_1_end) and L(return_vec_0_end). */ |
||||
+# ifdef USE_AS_WMEMCMP |
||||
+L(one_or_less): |
||||
+ jb L(zero) |
||||
+ movl (%rdi), %ecx |
||||
+ xorl %edx, %edx |
||||
+ cmpl (%rsi), %ecx |
||||
+ je L(zero) |
||||
+ setg %dl |
||||
+ leal -1(%rdx, %rdx), %eax |
||||
+ ret |
||||
+# else |
||||
+L(one_or_less): |
||||
+ jb L(zero) |
||||
+ movzbl (%rsi), %ecx |
||||
+ movzbl (%rdi), %eax |
||||
+ subl %ecx, %eax |
||||
+ ret |
||||
+# endif |
||||
+L(zero): |
||||
+ xorl %eax, %eax |
||||
+ ret |
||||
+ |
||||
.p2align 4 |
||||
L(return_vec_0_end): |
||||
tzcntl %eax, %eax |
||||
@@ -412,23 +453,56 @@ L(return_vec_0_end): |
||||
ret |
||||
|
||||
.p2align 4 |
||||
-L(return_vec_1_end): |
||||
+L(less_vec): |
||||
+ /* Check if one or less CHAR. This is necessary for size == 0 |
||||
+ but is also faster for size == CHAR_SIZE. */ |
||||
+ cmpl $1, %edx |
||||
+ jbe L(one_or_less) |
||||
+ |
||||
+ /* Check if loading one VEC from either s1 or s2 could cause a |
||||
+ page cross. This can have false positives but is by far the |
||||
+ fastest method. */ |
||||
+ movl %edi, %eax |
||||
+ orl %esi, %eax |
||||
+ andl $(PAGE_SIZE - 1), %eax |
||||
+ cmpl $(PAGE_SIZE - VEC_SIZE), %eax |
||||
+ jg L(page_cross_less_vec) |
||||
+ |
||||
+ /* No page cross possible. */ |
||||
+ VMOVU (%rsi), %YMM2 |
||||
+ VPCMP $4, (%rdi), %YMM2, %k1 |
||||
+ kmovd %k1, %eax |
||||
+ /* Check if any matches where in bounds. Intentionally not |
||||
+ storing result in eax to limit dependency chain if it goes to |
||||
+ L(return_vec_0_lv). */ |
||||
+ bzhil %edx, %eax, %edx |
||||
+ jnz L(return_vec_0_lv) |
||||
+ xorl %eax, %eax |
||||
+ ret |
||||
+ |
||||
+ /* Essentially duplicate of L(return_vec_0). Ends up not costing |
||||
+ any code as shrinks L(less_vec) by allowing 2-byte encoding of |
||||
+ the jump and ends up fitting in aligning bytes. As well fits on |
||||
+ same cache line as L(less_vec) so also saves a line from having |
||||
+ to be fetched on cold calls to memcmp. */ |
||||
+ .p2align 4,, 4 |
||||
+L(return_vec_0_lv): |
||||
tzcntl %eax, %eax |
||||
- addl %edx, %eax |
||||
# ifdef USE_AS_WMEMCMP |
||||
- movl -(VEC_SIZE * 2)(%rdi, %rax, CHAR_SIZE), %ecx |
||||
+ movl (%rdi, %rax, CHAR_SIZE), %ecx |
||||
xorl %edx, %edx |
||||
- cmpl -(VEC_SIZE * 2)(%rsi, %rax, CHAR_SIZE), %ecx |
||||
+ cmpl (%rsi, %rax, CHAR_SIZE), %ecx |
||||
+ /* NB: no partial register stall here because xorl zero idiom |
||||
+ above. */ |
||||
setg %dl |
||||
leal -1(%rdx, %rdx), %eax |
||||
# else |
||||
- movzbl -(VEC_SIZE * 2)(%rsi, %rax), %ecx |
||||
- movzbl -(VEC_SIZE * 2)(%rdi, %rax), %eax |
||||
+ movzbl (%rsi, %rax), %ecx |
||||
+ movzbl (%rdi, %rax), %eax |
||||
subl %ecx, %eax |
||||
# endif |
||||
ret |
||||
|
||||
- |
||||
.p2align 4 |
||||
L(page_cross_less_vec): |
||||
/* if USE_AS_WMEMCMP it can only be 0, 4, 8, 12, 16, 20, 24, 28 |
||||
@@ -439,108 +513,84 @@ L(page_cross_less_vec): |
||||
cmpl $8, %edx |
||||
jae L(between_8_15) |
||||
cmpl $4, %edx |
||||
- jae L(between_4_7) |
||||
-L(between_2_3): |
||||
- /* Load as big endian to avoid branches. */ |
||||
- movzwl (%rdi), %eax |
||||
- movzwl (%rsi), %ecx |
||||
- shll $8, %eax |
||||
- shll $8, %ecx |
||||
- bswap %eax |
||||
- bswap %ecx |
||||
- movzbl -1(%rdi, %rdx), %edi |
||||
- movzbl -1(%rsi, %rdx), %esi |
||||
- orl %edi, %eax |
||||
- orl %esi, %ecx |
||||
- /* Subtraction is okay because the upper 8 bits are zero. */ |
||||
- subl %ecx, %eax |
||||
- ret |
||||
- .p2align 4 |
||||
-L(one_or_less): |
||||
- jb L(zero) |
||||
- movzbl (%rsi), %ecx |
||||
- movzbl (%rdi), %eax |
||||
- subl %ecx, %eax |
||||
+ jb L(between_2_3) |
||||
+ |
||||
+ /* Load as big endian with overlapping movbe to avoid branches. |
||||
+ */ |
||||
+ movbe (%rdi), %eax |
||||
+ movbe (%rsi), %ecx |
||||
+ shlq $32, %rax |
||||
+ shlq $32, %rcx |
||||
+ movbe -4(%rdi, %rdx), %edi |
||||
+ movbe -4(%rsi, %rdx), %esi |
||||
+ orq %rdi, %rax |
||||
+ orq %rsi, %rcx |
||||
+ subq %rcx, %rax |
||||
+ /* edx is guranteed to be positive int32 in range [4, 7]. */ |
||||
+ cmovne %edx, %eax |
||||
+ /* ecx is -1 if rcx > rax. Otherwise 0. */ |
||||
+ sbbl %ecx, %ecx |
||||
+ /* If rcx > rax, then ecx is 0 and eax is positive. If rcx == |
||||
+ rax then eax and ecx are zero. If rax < rax then ecx is -1 so |
||||
+ eax doesn't matter. */ |
||||
+ orl %ecx, %eax |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
+ .p2align 4,, 8 |
||||
L(between_8_15): |
||||
# endif |
||||
/* If USE_AS_WMEMCMP fall through into 8-15 byte case. */ |
||||
- vmovq (%rdi), %XMM1 |
||||
- vmovq (%rsi), %XMM2 |
||||
- VPCMP $4, %XMM1, %XMM2, %k1 |
||||
+ vmovq (%rdi), %xmm1 |
||||
+ vmovq (%rsi), %xmm2 |
||||
+ VPCMP $4, %xmm1, %xmm2, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
+ jnz L(return_vec_0_lv) |
||||
/* Use overlapping loads to avoid branches. */ |
||||
- leaq -8(%rdi, %rdx, CHAR_SIZE), %rdi |
||||
- leaq -8(%rsi, %rdx, CHAR_SIZE), %rsi |
||||
- vmovq (%rdi), %XMM1 |
||||
- vmovq (%rsi), %XMM2 |
||||
- VPCMP $4, %XMM1, %XMM2, %k1 |
||||
+ vmovq -8(%rdi, %rdx, CHAR_SIZE), %xmm1 |
||||
+ vmovq -8(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
+ VPCMP $4, %xmm1, %xmm2, %k1 |
||||
+ addl $(CHAR_PER_VEC - (8 / CHAR_SIZE)), %edx |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
- ret |
||||
- |
||||
- .p2align 4 |
||||
-L(zero): |
||||
- xorl %eax, %eax |
||||
+ jnz L(return_vec_0_end) |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
+ .p2align 4,, 8 |
||||
L(between_16_31): |
||||
/* From 16 to 31 bytes. No branch when size == 16. */ |
||||
- VMOVU (%rsi), %XMM2 |
||||
- VPCMP $4, (%rdi), %XMM2, %k1 |
||||
+ |
||||
+ /* Use movups to save code size. */ |
||||
+ movups (%rsi), %xmm2 |
||||
+ VPCMP $4, (%rdi), %xmm2, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
- |
||||
+ jnz L(return_vec_0_lv) |
||||
/* Use overlapping loads to avoid branches. */ |
||||
- |
||||
- VMOVU -16(%rsi, %rdx, CHAR_SIZE), %XMM2 |
||||
- leaq -16(%rdi, %rdx, CHAR_SIZE), %rdi |
||||
- leaq -16(%rsi, %rdx, CHAR_SIZE), %rsi |
||||
- VPCMP $4, (%rdi), %XMM2, %k1 |
||||
+ movups -16(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
+ VPCMP $4, -16(%rdi, %rdx, CHAR_SIZE), %xmm2, %k1 |
||||
+ addl $(CHAR_PER_VEC - (16 / CHAR_SIZE)), %edx |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
- jnz L(return_vec_0) |
||||
- ret |
||||
- |
||||
-# ifdef USE_AS_WMEMCMP |
||||
- .p2align 4 |
||||
-L(one_or_less): |
||||
- jb L(zero) |
||||
- movl (%rdi), %ecx |
||||
- xorl %edx, %edx |
||||
- cmpl (%rsi), %ecx |
||||
- je L(zero) |
||||
- setg %dl |
||||
- leal -1(%rdx, %rdx), %eax |
||||
+ jnz L(return_vec_0_end) |
||||
ret |
||||
-# else |
||||
|
||||
- .p2align 4 |
||||
-L(between_4_7): |
||||
- /* Load as big endian with overlapping movbe to avoid branches. |
||||
- */ |
||||
- movbe (%rdi), %eax |
||||
- movbe (%rsi), %ecx |
||||
- shlq $32, %rax |
||||
- shlq $32, %rcx |
||||
- movbe -4(%rdi, %rdx), %edi |
||||
- movbe -4(%rsi, %rdx), %esi |
||||
- orq %rdi, %rax |
||||
- orq %rsi, %rcx |
||||
- subq %rcx, %rax |
||||
- jz L(zero_4_7) |
||||
- sbbl %eax, %eax |
||||
- orl $1, %eax |
||||
-L(zero_4_7): |
||||
+# ifndef USE_AS_WMEMCMP |
||||
+L(between_2_3): |
||||
+ /* Load as big endian to avoid branches. */ |
||||
+ movzwl (%rdi), %eax |
||||
+ movzwl (%rsi), %ecx |
||||
+ shll $8, %eax |
||||
+ shll $8, %ecx |
||||
+ bswap %eax |
||||
+ bswap %ecx |
||||
+ movzbl -1(%rdi, %rdx), %edi |
||||
+ movzbl -1(%rsi, %rdx), %esi |
||||
+ orl %edi, %eax |
||||
+ orl %esi, %ecx |
||||
+ /* Subtraction is okay because the upper 8 bits are zero. */ |
||||
+ subl %ecx, %eax |
||||
ret |
||||
# endif |
||||
- |
||||
END (MEMCMP) |
||||
#endif |
@ -0,0 +1,497 @@
@@ -0,0 +1,497 @@
|
||||
commit 6d18a93dbbde2958001d65dff3080beed7ae675a |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Mon Sep 20 16:20:15 2021 -0500 |
||||
|
||||
x86: Optimize memset-vec-unaligned-erms.S |
||||
|
||||
No bug. |
||||
|
||||
Optimization are |
||||
|
||||
1. change control flow for L(more_2x_vec) to fall through to loop and |
||||
jump for L(less_4x_vec) and L(less_8x_vec). This uses less code |
||||
size and saves jumps for length > 4x VEC_SIZE. |
||||
|
||||
2. For EVEX/AVX512 move L(less_vec) closer to entry. |
||||
|
||||
3. Avoid complex address mode for length > 2x VEC_SIZE |
||||
|
||||
4. Slightly better aligning code for the loop from the perspective of |
||||
code size and uops. |
||||
|
||||
5. Align targets so they make full use of their fetch block and if |
||||
possible cache line. |
||||
|
||||
6. Try and reduce total number of icache lines that will need to be |
||||
pulled in for a given length. |
||||
|
||||
7. Include "local" version of stosb target. For AVX2/EVEX/AVX512 |
||||
jumping to the stosb target in the sse2 code section will almost |
||||
certainly be to a new page. The new version does increase code size |
||||
marginally by duplicating the target but should get better iTLB |
||||
behavior as a result. |
||||
|
||||
test-memset, test-wmemset, and test-bzero are all passing. |
||||
|
||||
Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit e59ced238482fd71f3e493717f14f6507346741e) |
||||
|
||||
diff --git a/sysdeps/x86_64/memset.S b/sysdeps/x86_64/memset.S |
||||
index 7d4a327eba29ecb4..0137eba4cdd9f830 100644 |
||||
--- a/sysdeps/x86_64/memset.S |
||||
+++ b/sysdeps/x86_64/memset.S |
||||
@@ -18,13 +18,15 @@ |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
#include <sysdep.h> |
||||
+#define USE_WITH_SSE2 1 |
||||
|
||||
#define VEC_SIZE 16 |
||||
+#define MOV_SIZE 3 |
||||
+#define RET_SIZE 1 |
||||
+ |
||||
#define VEC(i) xmm##i |
||||
-/* Don't use movups and movaps since it will get larger nop paddings for |
||||
- alignment. */ |
||||
-#define VMOVU movdqu |
||||
-#define VMOVA movdqa |
||||
+#define VMOVU movups |
||||
+#define VMOVA movaps |
||||
|
||||
#define MEMSET_VDUP_TO_VEC0_AND_SET_RETURN(d, r) \ |
||||
movd d, %xmm0; \ |
||||
diff --git a/sysdeps/x86_64/multiarch/memset-avx2-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-avx2-unaligned-erms.S |
||||
index ae0860f36a47d594..1af668af0aeda59e 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memset-avx2-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memset-avx2-unaligned-erms.S |
||||
@@ -1,8 +1,14 @@ |
||||
#if IS_IN (libc) |
||||
+# define USE_WITH_AVX2 1 |
||||
+ |
||||
# define VEC_SIZE 32 |
||||
+# define MOV_SIZE 4 |
||||
+# define RET_SIZE 4 |
||||
+ |
||||
# define VEC(i) ymm##i |
||||
-# define VMOVU vmovdqu |
||||
-# define VMOVA vmovdqa |
||||
+ |
||||
+# define VMOVU vmovdqu |
||||
+# define VMOVA vmovdqa |
||||
|
||||
# define MEMSET_VDUP_TO_VEC0_AND_SET_RETURN(d, r) \ |
||||
vmovd d, %xmm0; \ |
||||
diff --git a/sysdeps/x86_64/multiarch/memset-avx512-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-avx512-unaligned-erms.S |
||||
index 8ad842fc2f140527..f14d6f8493c21a36 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memset-avx512-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memset-avx512-unaligned-erms.S |
||||
@@ -1,11 +1,18 @@ |
||||
#if IS_IN (libc) |
||||
+# define USE_WITH_AVX512 1 |
||||
+ |
||||
# define VEC_SIZE 64 |
||||
+# define MOV_SIZE 6 |
||||
+# define RET_SIZE 1 |
||||
+ |
||||
# define XMM0 xmm16 |
||||
# define YMM0 ymm16 |
||||
# define VEC0 zmm16 |
||||
# define VEC(i) VEC##i |
||||
-# define VMOVU vmovdqu64 |
||||
-# define VMOVA vmovdqa64 |
||||
+ |
||||
+# define VMOVU vmovdqu64 |
||||
+# define VMOVA vmovdqa64 |
||||
+ |
||||
# define VZEROUPPER |
||||
|
||||
# define MEMSET_VDUP_TO_VEC0_AND_SET_RETURN(d, r) \ |
||||
diff --git a/sysdeps/x86_64/multiarch/memset-evex-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-evex-unaligned-erms.S |
||||
index 640f092903302ad0..64b09e77cc20cc42 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memset-evex-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memset-evex-unaligned-erms.S |
||||
@@ -1,11 +1,18 @@ |
||||
#if IS_IN (libc) |
||||
+# define USE_WITH_EVEX 1 |
||||
+ |
||||
# define VEC_SIZE 32 |
||||
+# define MOV_SIZE 6 |
||||
+# define RET_SIZE 1 |
||||
+ |
||||
# define XMM0 xmm16 |
||||
# define YMM0 ymm16 |
||||
# define VEC0 ymm16 |
||||
# define VEC(i) VEC##i |
||||
-# define VMOVU vmovdqu64 |
||||
-# define VMOVA vmovdqa64 |
||||
+ |
||||
+# define VMOVU vmovdqu64 |
||||
+# define VMOVA vmovdqa64 |
||||
+ |
||||
# define VZEROUPPER |
||||
|
||||
# define MEMSET_VDUP_TO_VEC0_AND_SET_RETURN(d, r) \ |
||||
diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
index ff196844a093dc3b..e723413a664c088f 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
@@ -63,8 +63,27 @@ |
||||
# endif |
||||
#endif |
||||
|
||||
+#if VEC_SIZE == 64 |
||||
+# define LOOP_4X_OFFSET (VEC_SIZE * 4) |
||||
+#else |
||||
+# define LOOP_4X_OFFSET (0) |
||||
+#endif |
||||
+ |
||||
+#if defined USE_WITH_EVEX || defined USE_WITH_AVX512 |
||||
+# define END_REG rcx |
||||
+# define LOOP_REG rdi |
||||
+#else |
||||
+# define END_REG rdi |
||||
+# define LOOP_REG rdx |
||||
+#endif |
||||
+ |
||||
#define PAGE_SIZE 4096 |
||||
|
||||
+/* Macro to calculate size of small memset block for aligning |
||||
+ purposes. */ |
||||
+#define SMALL_MEMSET_ALIGN(mov_sz, ret_sz) (2 * (mov_sz) + (ret_sz) + 1) |
||||
+ |
||||
+ |
||||
#ifndef SECTION |
||||
# error SECTION is not defined! |
||||
#endif |
||||
@@ -74,6 +93,7 @@ |
||||
ENTRY (__bzero) |
||||
mov %RDI_LP, %RAX_LP /* Set return value. */ |
||||
mov %RSI_LP, %RDX_LP /* Set n. */ |
||||
+ xorl %esi, %esi |
||||
pxor %XMM0, %XMM0 |
||||
jmp L(entry_from_bzero) |
||||
END (__bzero) |
||||
@@ -158,7 +178,7 @@ ENTRY_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned_erms)) |
||||
END_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned_erms)) |
||||
# endif |
||||
|
||||
-ENTRY (MEMSET_SYMBOL (__memset, unaligned_erms)) |
||||
+ENTRY_P2ALIGN (MEMSET_SYMBOL (__memset, unaligned_erms), 6) |
||||
MEMSET_VDUP_TO_VEC0_AND_SET_RETURN (%esi, %rdi) |
||||
# ifdef __ILP32__ |
||||
/* Clear the upper 32 bits. */ |
||||
@@ -168,75 +188,43 @@ ENTRY (MEMSET_SYMBOL (__memset, unaligned_erms)) |
||||
jb L(less_vec) |
||||
cmp $(VEC_SIZE * 2), %RDX_LP |
||||
ja L(stosb_more_2x_vec) |
||||
- /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. */ |
||||
- VMOVU %VEC(0), -VEC_SIZE(%rdi,%rdx) |
||||
- VMOVU %VEC(0), (%rdi) |
||||
+ /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. |
||||
+ */ |
||||
+ VMOVU %VEC(0), (%rax) |
||||
+ VMOVU %VEC(0), -VEC_SIZE(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
- |
||||
- .p2align 4 |
||||
-L(stosb_more_2x_vec): |
||||
- cmp __x86_rep_stosb_threshold(%rip), %RDX_LP |
||||
- ja L(stosb) |
||||
-#else |
||||
- .p2align 4 |
||||
#endif |
||||
-L(more_2x_vec): |
||||
- /* Stores to first 2x VEC before cmp as any path forward will |
||||
- require it. */ |
||||
- VMOVU %VEC(0), (%rdi) |
||||
- VMOVU %VEC(0), VEC_SIZE(%rdi) |
||||
- cmpq $(VEC_SIZE * 4), %rdx |
||||
- ja L(loop_start) |
||||
- VMOVU %VEC(0), -(VEC_SIZE * 2)(%rdi,%rdx) |
||||
- VMOVU %VEC(0), -VEC_SIZE(%rdi,%rdx) |
||||
-L(return): |
||||
-#if VEC_SIZE > 16 |
||||
- ZERO_UPPER_VEC_REGISTERS_RETURN |
||||
+ |
||||
+ .p2align 4,, 10 |
||||
+L(last_2x_vec): |
||||
+#ifdef USE_LESS_VEC_MASK_STORE |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 2 + LOOP_4X_OFFSET)(%rcx) |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 3 + LOOP_4X_OFFSET)(%rcx) |
||||
#else |
||||
- ret |
||||
+ VMOVU %VEC(0), (VEC_SIZE * -2)(%rdi) |
||||
+ VMOVU %VEC(0), (VEC_SIZE * -1)(%rdi) |
||||
#endif |
||||
+ VZEROUPPER_RETURN |
||||
|
||||
-L(loop_start): |
||||
- VMOVU %VEC(0), (VEC_SIZE * 2)(%rdi) |
||||
- VMOVU %VEC(0), (VEC_SIZE * 3)(%rdi) |
||||
- cmpq $(VEC_SIZE * 8), %rdx |
||||
- jbe L(loop_end) |
||||
- andq $-(VEC_SIZE * 2), %rdi |
||||
- subq $-(VEC_SIZE * 4), %rdi |
||||
- leaq -(VEC_SIZE * 4)(%rax, %rdx), %rcx |
||||
- .p2align 4 |
||||
-L(loop): |
||||
- VMOVA %VEC(0), (%rdi) |
||||
- VMOVA %VEC(0), VEC_SIZE(%rdi) |
||||
- VMOVA %VEC(0), (VEC_SIZE * 2)(%rdi) |
||||
- VMOVA %VEC(0), (VEC_SIZE * 3)(%rdi) |
||||
- subq $-(VEC_SIZE * 4), %rdi |
||||
- cmpq %rcx, %rdi |
||||
- jb L(loop) |
||||
-L(loop_end): |
||||
- /* NB: rax is set as ptr in MEMSET_VDUP_TO_VEC0_AND_SET_RETURN. |
||||
- rdx as length is also unchanged. */ |
||||
- VMOVU %VEC(0), -(VEC_SIZE * 4)(%rax, %rdx) |
||||
- VMOVU %VEC(0), -(VEC_SIZE * 3)(%rax, %rdx) |
||||
- VMOVU %VEC(0), -(VEC_SIZE * 2)(%rax, %rdx) |
||||
- VMOVU %VEC(0), -VEC_SIZE(%rax, %rdx) |
||||
- VZEROUPPER_SHORT_RETURN |
||||
- |
||||
- .p2align 4 |
||||
+ /* If have AVX512 mask instructions put L(less_vec) close to |
||||
+ entry as it doesn't take much space and is likely a hot target. |
||||
+ */ |
||||
+#ifdef USE_LESS_VEC_MASK_STORE |
||||
+ .p2align 4,, 10 |
||||
L(less_vec): |
||||
/* Less than 1 VEC. */ |
||||
# if VEC_SIZE != 16 && VEC_SIZE != 32 && VEC_SIZE != 64 |
||||
# error Unsupported VEC_SIZE! |
||||
# endif |
||||
-# ifdef USE_LESS_VEC_MASK_STORE |
||||
/* Clear high bits from edi. Only keeping bits relevant to page |
||||
cross check. Note that we are using rax which is set in |
||||
- MEMSET_VDUP_TO_VEC0_AND_SET_RETURN as ptr from here on out. |
||||
- */ |
||||
+ MEMSET_VDUP_TO_VEC0_AND_SET_RETURN as ptr from here on out. */ |
||||
andl $(PAGE_SIZE - 1), %edi |
||||
- /* Check if VEC_SIZE store cross page. Mask stores suffer serious |
||||
- performance degradation when it has to fault supress. */ |
||||
+ /* Check if VEC_SIZE store cross page. Mask stores suffer |
||||
+ serious performance degradation when it has to fault supress. |
||||
+ */ |
||||
cmpl $(PAGE_SIZE - VEC_SIZE), %edi |
||||
+ /* This is generally considered a cold target. */ |
||||
ja L(cross_page) |
||||
# if VEC_SIZE > 32 |
||||
movq $-1, %rcx |
||||
@@ -247,58 +235,185 @@ L(less_vec): |
||||
bzhil %edx, %ecx, %ecx |
||||
kmovd %ecx, %k1 |
||||
# endif |
||||
- vmovdqu8 %VEC(0), (%rax) {%k1} |
||||
+ vmovdqu8 %VEC(0), (%rax){%k1} |
||||
VZEROUPPER_RETURN |
||||
|
||||
+# if defined USE_MULTIARCH && IS_IN (libc) |
||||
+ /* Include L(stosb_local) here if including L(less_vec) between |
||||
+ L(stosb_more_2x_vec) and ENTRY. This is to cache align the |
||||
+ L(stosb_more_2x_vec) target. */ |
||||
+ .p2align 4,, 10 |
||||
+L(stosb_local): |
||||
+ movzbl %sil, %eax |
||||
+ mov %RDX_LP, %RCX_LP |
||||
+ mov %RDI_LP, %RDX_LP |
||||
+ rep stosb |
||||
+ mov %RDX_LP, %RAX_LP |
||||
+ VZEROUPPER_RETURN |
||||
+# endif |
||||
+#endif |
||||
+ |
||||
+#if defined USE_MULTIARCH && IS_IN (libc) |
||||
.p2align 4 |
||||
-L(cross_page): |
||||
+L(stosb_more_2x_vec): |
||||
+ cmp __x86_rep_stosb_threshold(%rip), %RDX_LP |
||||
+ ja L(stosb_local) |
||||
+#endif |
||||
+ /* Fallthrough goes to L(loop_4x_vec). Tests for memset (2x, 4x] |
||||
+ and (4x, 8x] jump to target. */ |
||||
+L(more_2x_vec): |
||||
+ |
||||
+ /* Two different methods of setting up pointers / compare. The |
||||
+ two methods are based on the fact that EVEX/AVX512 mov |
||||
+ instructions take more bytes then AVX2/SSE2 mov instructions. As |
||||
+ well that EVEX/AVX512 machines also have fast LEA_BID. Both |
||||
+ setup and END_REG to avoid complex address mode. For EVEX/AVX512 |
||||
+ this saves code size and keeps a few targets in one fetch block. |
||||
+ For AVX2/SSE2 this helps prevent AGU bottlenecks. */ |
||||
+#if defined USE_WITH_EVEX || defined USE_WITH_AVX512 |
||||
+ /* If EVEX/AVX512 compute END_REG - (VEC_SIZE * 4 + |
||||
+ LOOP_4X_OFFSET) with LEA_BID. */ |
||||
+ |
||||
+ /* END_REG is rcx for EVEX/AVX512. */ |
||||
+ leaq -(VEC_SIZE * 4 + LOOP_4X_OFFSET)(%rdi, %rdx), %END_REG |
||||
+#endif |
||||
+ |
||||
+ /* Stores to first 2x VEC before cmp as any path forward will |
||||
+ require it. */ |
||||
+ VMOVU %VEC(0), (%rax) |
||||
+ VMOVU %VEC(0), VEC_SIZE(%rax) |
||||
+ |
||||
+ |
||||
+#if !(defined USE_WITH_EVEX || defined USE_WITH_AVX512) |
||||
+ /* If AVX2/SSE2 compute END_REG (rdi) with ALU. */ |
||||
+ addq %rdx, %END_REG |
||||
+#endif |
||||
+ |
||||
+ cmpq $(VEC_SIZE * 4), %rdx |
||||
+ jbe L(last_2x_vec) |
||||
+ |
||||
+ /* Store next 2x vec regardless. */ |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 2)(%rax) |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 3)(%rax) |
||||
+ |
||||
+ |
||||
+#if defined USE_WITH_EVEX || defined USE_WITH_AVX512 |
||||
+ /* If LOOP_4X_OFFSET don't readjust LOOP_REG (rdi), just add |
||||
+ extra offset to addresses in loop. Used for AVX512 to save space |
||||
+ as no way to get (VEC_SIZE * 4) in imm8. */ |
||||
+# if LOOP_4X_OFFSET == 0 |
||||
+ subq $-(VEC_SIZE * 4), %LOOP_REG |
||||
# endif |
||||
-# if VEC_SIZE > 32 |
||||
- cmpb $32, %dl |
||||
- jae L(between_32_63) |
||||
+ /* Avoid imm32 compare here to save code size. */ |
||||
+ cmpq %rdi, %rcx |
||||
+#else |
||||
+ addq $-(VEC_SIZE * 4), %END_REG |
||||
+ cmpq $(VEC_SIZE * 8), %rdx |
||||
+#endif |
||||
+ jbe L(last_4x_vec) |
||||
+#if !(defined USE_WITH_EVEX || defined USE_WITH_AVX512) |
||||
+ /* Set LOOP_REG (rdx). */ |
||||
+ leaq (VEC_SIZE * 4)(%rax), %LOOP_REG |
||||
+#endif |
||||
+ /* Align dst for loop. */ |
||||
+ andq $(VEC_SIZE * -2), %LOOP_REG |
||||
+ .p2align 4 |
||||
+L(loop): |
||||
+ VMOVA %VEC(0), LOOP_4X_OFFSET(%LOOP_REG) |
||||
+ VMOVA %VEC(0), (VEC_SIZE + LOOP_4X_OFFSET)(%LOOP_REG) |
||||
+ VMOVA %VEC(0), (VEC_SIZE * 2 + LOOP_4X_OFFSET)(%LOOP_REG) |
||||
+ VMOVA %VEC(0), (VEC_SIZE * 3 + LOOP_4X_OFFSET)(%LOOP_REG) |
||||
+ subq $-(VEC_SIZE * 4), %LOOP_REG |
||||
+ cmpq %END_REG, %LOOP_REG |
||||
+ jb L(loop) |
||||
+ .p2align 4,, MOV_SIZE |
||||
+L(last_4x_vec): |
||||
+ VMOVU %VEC(0), LOOP_4X_OFFSET(%END_REG) |
||||
+ VMOVU %VEC(0), (VEC_SIZE + LOOP_4X_OFFSET)(%END_REG) |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 2 + LOOP_4X_OFFSET)(%END_REG) |
||||
+ VMOVU %VEC(0), (VEC_SIZE * 3 + LOOP_4X_OFFSET)(%END_REG) |
||||
+L(return): |
||||
+#if VEC_SIZE > 16 |
||||
+ ZERO_UPPER_VEC_REGISTERS_RETURN |
||||
+#else |
||||
+ ret |
||||
+#endif |
||||
+ |
||||
+ .p2align 4,, 10 |
||||
+#ifndef USE_LESS_VEC_MASK_STORE |
||||
+# if defined USE_MULTIARCH && IS_IN (libc) |
||||
+ /* If no USE_LESS_VEC_MASK put L(stosb_local) here. Will be in |
||||
+ range for 2-byte jump encoding. */ |
||||
+L(stosb_local): |
||||
+ movzbl %sil, %eax |
||||
+ mov %RDX_LP, %RCX_LP |
||||
+ mov %RDI_LP, %RDX_LP |
||||
+ rep stosb |
||||
+ mov %RDX_LP, %RAX_LP |
||||
+ VZEROUPPER_RETURN |
||||
# endif |
||||
-# if VEC_SIZE > 16 |
||||
- cmpb $16, %dl |
||||
+ /* Define L(less_vec) only if not otherwise defined. */ |
||||
+ .p2align 4 |
||||
+L(less_vec): |
||||
+#endif |
||||
+L(cross_page): |
||||
+#if VEC_SIZE > 32 |
||||
+ cmpl $32, %edx |
||||
+ jae L(between_32_63) |
||||
+#endif |
||||
+#if VEC_SIZE > 16 |
||||
+ cmpl $16, %edx |
||||
jae L(between_16_31) |
||||
-# endif |
||||
- MOVQ %XMM0, %rcx |
||||
- cmpb $8, %dl |
||||
+#endif |
||||
+ MOVQ %XMM0, %rdi |
||||
+ cmpl $8, %edx |
||||
jae L(between_8_15) |
||||
- cmpb $4, %dl |
||||
+ cmpl $4, %edx |
||||
jae L(between_4_7) |
||||
- cmpb $1, %dl |
||||
+ cmpl $1, %edx |
||||
ja L(between_2_3) |
||||
- jb 1f |
||||
- movb %cl, (%rax) |
||||
-1: |
||||
+ jb L(return) |
||||
+ movb %sil, (%rax) |
||||
VZEROUPPER_RETURN |
||||
-# if VEC_SIZE > 32 |
||||
+ |
||||
+ /* Align small targets only if not doing so would cross a fetch |
||||
+ line. */ |
||||
+#if VEC_SIZE > 32 |
||||
+ .p2align 4,, SMALL_MEMSET_ALIGN(MOV_SIZE, RET_SIZE) |
||||
/* From 32 to 63. No branch when size == 32. */ |
||||
L(between_32_63): |
||||
- VMOVU %YMM0, -32(%rax,%rdx) |
||||
VMOVU %YMM0, (%rax) |
||||
+ VMOVU %YMM0, -32(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
-# endif |
||||
-# if VEC_SIZE > 16 |
||||
- /* From 16 to 31. No branch when size == 16. */ |
||||
+#endif |
||||
+ |
||||
+#if VEC_SIZE >= 32 |
||||
+ .p2align 4,, SMALL_MEMSET_ALIGN(MOV_SIZE, RET_SIZE) |
||||
L(between_16_31): |
||||
- VMOVU %XMM0, -16(%rax,%rdx) |
||||
+ /* From 16 to 31. No branch when size == 16. */ |
||||
VMOVU %XMM0, (%rax) |
||||
+ VMOVU %XMM0, -16(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
-# endif |
||||
- /* From 8 to 15. No branch when size == 8. */ |
||||
+#endif |
||||
+ |
||||
+ .p2align 4,, SMALL_MEMSET_ALIGN(3, RET_SIZE) |
||||
L(between_8_15): |
||||
- movq %rcx, -8(%rax,%rdx) |
||||
- movq %rcx, (%rax) |
||||
+ /* From 8 to 15. No branch when size == 8. */ |
||||
+ movq %rdi, (%rax) |
||||
+ movq %rdi, -8(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
+ |
||||
+ .p2align 4,, SMALL_MEMSET_ALIGN(2, RET_SIZE) |
||||
L(between_4_7): |
||||
/* From 4 to 7. No branch when size == 4. */ |
||||
- movl %ecx, -4(%rax,%rdx) |
||||
- movl %ecx, (%rax) |
||||
+ movl %edi, (%rax) |
||||
+ movl %edi, -4(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
+ |
||||
+ .p2align 4,, SMALL_MEMSET_ALIGN(3, RET_SIZE) |
||||
L(between_2_3): |
||||
/* From 2 to 3. No branch when size == 2. */ |
||||
- movw %cx, -2(%rax,%rdx) |
||||
- movw %cx, (%rax) |
||||
+ movw %di, (%rax) |
||||
+ movb %dil, -1(%rax, %rdx) |
||||
VZEROUPPER_RETURN |
||||
END (MEMSET_SYMBOL (__memset, unaligned_erms)) |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
commit baf3ece63453adac59c5688930324a78ced5b2e4 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Sat Oct 23 01:26:47 2021 -0400 |
||||
|
||||
x86: Replace sse2 instructions with avx in memcmp-evex-movbe.S |
||||
|
||||
This commit replaces two usages of SSE2 'movups' with AVX 'vmovdqu'. |
||||
|
||||
it could potentially be dangerous to use SSE2 if this function is ever |
||||
called without using 'vzeroupper' beforehand. While compilers appear |
||||
to use 'vzeroupper' before function calls if AVX2 has been used, using |
||||
SSE2 here is more brittle. Since it is not absolutely necessary it |
||||
should be avoided. |
||||
|
||||
It costs 2-extra bytes but the extra bytes should only eat into |
||||
alignment padding. |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
|
||||
(cherry picked from commit bad852b61b79503fcb3c5fc379c70f768df3e1fb) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
index 2761b54f2e7dea9f..640f6757fac8a356 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
+++ b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
@@ -561,13 +561,13 @@ L(between_16_31): |
||||
/* From 16 to 31 bytes. No branch when size == 16. */ |
||||
|
||||
/* Use movups to save code size. */ |
||||
- movups (%rsi), %xmm2 |
||||
+ vmovdqu (%rsi), %xmm2 |
||||
VPCMP $4, (%rdi), %xmm2, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
jnz L(return_vec_0_lv) |
||||
/* Use overlapping loads to avoid branches. */ |
||||
- movups -16(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
+ vmovdqu -16(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
VPCMP $4, -16(%rdi, %rdx, CHAR_SIZE), %xmm2, %k1 |
||||
addl $(CHAR_PER_VEC - (16 / CHAR_SIZE)), %edx |
||||
kmovd %k1, %eax |
@ -0,0 +1,690 @@
@@ -0,0 +1,690 @@
|
||||
commit f35ad30da4880a1574996df0674986ecf82fa7ae |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Fri Oct 29 12:40:20 2021 -0700 |
||||
|
||||
x86-64: Improve EVEX strcmp with masked load |
||||
|
||||
In strcmp-evex.S, to compare 2 32-byte strings, replace |
||||
|
||||
VMOVU (%rdi, %rdx), %YMM0 |
||||
VMOVU (%rsi, %rdx), %YMM1 |
||||
/* Each bit in K0 represents a mismatch in YMM0 and YMM1. */ |
||||
VPCMP $4, %YMM0, %YMM1, %k0 |
||||
VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
VPCMP $0, %YMMZERO, %YMM1, %k2 |
||||
/* Each bit in K1 represents a NULL in YMM0 or YMM1. */ |
||||
kord %k1, %k2, %k1 |
||||
/* Each bit in K1 represents a NULL or a mismatch. */ |
||||
kord %k0, %k1, %k1 |
||||
kmovd %k1, %ecx |
||||
testl %ecx, %ecx |
||||
jne L(last_vector) |
||||
|
||||
with |
||||
|
||||
VMOVU (%rdi, %rdx), %YMM0 |
||||
VPTESTM %YMM0, %YMM0, %k2 |
||||
/* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
in YMM0 and 32 bytes at (%rsi, %rdx). */ |
||||
VPCMP $0, (%rsi, %rdx), %YMM0, %k1{%k2} |
||||
kmovd %k1, %ecx |
||||
incl %ecx |
||||
jne L(last_vector) |
||||
|
||||
It makes EVEX strcmp faster than AVX2 strcmp by up to 40% on Tiger Lake |
||||
and Ice Lake. |
||||
|
||||
Co-Authored-By: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
(cherry picked from commit c46e9afb2df5fc9e39ff4d13777e4b4c26e04e55) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
index d5aa6daa46c7ed25..82f12ac89bcae20b 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
@@ -41,6 +41,8 @@ |
||||
# ifdef USE_AS_WCSCMP |
||||
/* Compare packed dwords. */ |
||||
# define VPCMP vpcmpd |
||||
+# define VPMINU vpminud |
||||
+# define VPTESTM vptestmd |
||||
# define SHIFT_REG32 r8d |
||||
# define SHIFT_REG64 r8 |
||||
/* 1 dword char == 4 bytes. */ |
||||
@@ -48,6 +50,8 @@ |
||||
# else |
||||
/* Compare packed bytes. */ |
||||
# define VPCMP vpcmpb |
||||
+# define VPMINU vpminub |
||||
+# define VPTESTM vptestmb |
||||
# define SHIFT_REG32 ecx |
||||
# define SHIFT_REG64 rcx |
||||
/* 1 byte char == 1 byte. */ |
||||
@@ -67,6 +71,9 @@ |
||||
# define YMM5 ymm22 |
||||
# define YMM6 ymm23 |
||||
# define YMM7 ymm24 |
||||
+# define YMM8 ymm25 |
||||
+# define YMM9 ymm26 |
||||
+# define YMM10 ymm27 |
||||
|
||||
/* Warning! |
||||
wcscmp/wcsncmp have to use SIGNED comparison for elements. |
||||
@@ -76,7 +83,7 @@ |
||||
/* The main idea of the string comparison (byte or dword) using 256-bit |
||||
EVEX instructions consists of comparing (VPCMP) two ymm vectors. The |
||||
latter can be on either packed bytes or dwords depending on |
||||
- USE_AS_WCSCMP. In order to check the null char, algorithm keeps the |
||||
+ USE_AS_WCSCMP. In order to check the null CHAR, algorithm keeps the |
||||
matched bytes/dwords, requiring 5 EVEX instructions (3 VPCMP and 2 |
||||
KORD). In general, the costs of comparing VEC_SIZE bytes (32-bytes) |
||||
are 3 VPCMP and 2 KORD instructions, together with VMOVU and ktestd |
||||
@@ -123,27 +130,21 @@ ENTRY (STRCMP) |
||||
jg L(cross_page) |
||||
/* Start comparing 4 vectors. */ |
||||
VMOVU (%rdi), %YMM0 |
||||
- VMOVU (%rsi), %YMM1 |
||||
|
||||
- /* Each bit in K0 represents a mismatch in YMM0 and YMM1. */ |
||||
- VPCMP $4, %YMM0, %YMM1, %k0 |
||||
+ /* Each bit set in K2 represents a non-null CHAR in YMM0. */ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
|
||||
- /* Check for NULL in YMM0. */ |
||||
- VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
- /* Check for NULL in YMM1. */ |
||||
- VPCMP $0, %YMMZERO, %YMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in YMM0 or YMM1. */ |
||||
- kord %k1, %k2, %k1 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at (%rsi). */ |
||||
+ VPCMP $0, (%rsi), %YMM0, %k1{%k2} |
||||
|
||||
- /* Each bit in K1 represents: |
||||
- 1. A mismatch in YMM0 and YMM1. Or |
||||
- 2. A NULL in YMM0 or YMM1. |
||||
- */ |
||||
- kord %k0, %k1, %k1 |
||||
- |
||||
- ktestd %k1, %k1 |
||||
- je L(next_3_vectors) |
||||
kmovd %k1, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
+ je L(next_3_vectors) |
||||
tzcntl %ecx, %edx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -172,9 +173,7 @@ L(return): |
||||
# endif |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
L(return_vec_size): |
||||
- kmovd %k1, %ecx |
||||
tzcntl %ecx, %edx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -210,9 +209,7 @@ L(return_vec_size): |
||||
# endif |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
L(return_2_vec_size): |
||||
- kmovd %k1, %ecx |
||||
tzcntl %ecx, %edx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -248,9 +245,7 @@ L(return_2_vec_size): |
||||
# endif |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
L(return_3_vec_size): |
||||
- kmovd %k1, %ecx |
||||
tzcntl %ecx, %edx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -289,43 +284,45 @@ L(return_3_vec_size): |
||||
.p2align 4 |
||||
L(next_3_vectors): |
||||
VMOVU VEC_SIZE(%rdi), %YMM0 |
||||
- VMOVU VEC_SIZE(%rsi), %YMM1 |
||||
- /* Each bit in K0 represents a mismatch in YMM0 and YMM1. */ |
||||
- VPCMP $4, %YMM0, %YMM1, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in YMM0 or YMM1. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
- ktestd %k1, %k1 |
||||
+ /* Each bit set in K2 represents a non-null CHAR in YMM0. */ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at VEC_SIZE(%rsi). */ |
||||
+ VPCMP $0, VEC_SIZE(%rsi), %YMM0, %k1{%k2} |
||||
+ kmovd %k1, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
jne L(return_vec_size) |
||||
|
||||
- VMOVU (VEC_SIZE * 2)(%rdi), %YMM2 |
||||
- VMOVU (VEC_SIZE * 3)(%rdi), %YMM3 |
||||
- VMOVU (VEC_SIZE * 2)(%rsi), %YMM4 |
||||
- VMOVU (VEC_SIZE * 3)(%rsi), %YMM5 |
||||
- |
||||
- /* Each bit in K0 represents a mismatch in YMM2 and YMM4. */ |
||||
- VPCMP $4, %YMM2, %YMM4, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM2, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM4, %k2 |
||||
- /* Each bit in K1 represents a NULL in YMM2 or YMM4. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
- ktestd %k1, %k1 |
||||
+ VMOVU (VEC_SIZE * 2)(%rdi), %YMM0 |
||||
+ /* Each bit set in K2 represents a non-null CHAR in YMM0. */ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at (VEC_SIZE * 2)(%rsi). */ |
||||
+ VPCMP $0, (VEC_SIZE * 2)(%rsi), %YMM0, %k1{%k2} |
||||
+ kmovd %k1, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
jne L(return_2_vec_size) |
||||
|
||||
- /* Each bit in K0 represents a mismatch in YMM3 and YMM5. */ |
||||
- VPCMP $4, %YMM3, %YMM5, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM3, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM5, %k2 |
||||
- /* Each bit in K1 represents a NULL in YMM3 or YMM5. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
- ktestd %k1, %k1 |
||||
+ VMOVU (VEC_SIZE * 3)(%rdi), %YMM0 |
||||
+ /* Each bit set in K2 represents a non-null CHAR in YMM0. */ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at (VEC_SIZE * 2)(%rsi). */ |
||||
+ VPCMP $0, (VEC_SIZE * 3)(%rsi), %YMM0, %k1{%k2} |
||||
+ kmovd %k1, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
jne L(return_3_vec_size) |
||||
L(main_loop_header): |
||||
leaq (VEC_SIZE * 4)(%rdi), %rdx |
||||
@@ -375,56 +372,51 @@ L(back_to_loop): |
||||
VMOVA VEC_SIZE(%rax), %YMM2 |
||||
VMOVA (VEC_SIZE * 2)(%rax), %YMM4 |
||||
VMOVA (VEC_SIZE * 3)(%rax), %YMM6 |
||||
- VMOVU (%rdx), %YMM1 |
||||
- VMOVU VEC_SIZE(%rdx), %YMM3 |
||||
- VMOVU (VEC_SIZE * 2)(%rdx), %YMM5 |
||||
- VMOVU (VEC_SIZE * 3)(%rdx), %YMM7 |
||||
- |
||||
- VPCMP $4, %YMM0, %YMM1, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM1, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K4 represents a NULL or a mismatch in YMM0 and |
||||
- YMM1. */ |
||||
- kord %k0, %k1, %k4 |
||||
- |
||||
- VPCMP $4, %YMM2, %YMM3, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM2, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM3, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K5 represents a NULL or a mismatch in YMM2 and |
||||
- YMM3. */ |
||||
- kord %k0, %k1, %k5 |
||||
- |
||||
- VPCMP $4, %YMM4, %YMM5, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM4, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM5, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K6 represents a NULL or a mismatch in YMM4 and |
||||
- YMM5. */ |
||||
- kord %k0, %k1, %k6 |
||||
- |
||||
- VPCMP $4, %YMM6, %YMM7, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM6, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM7, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K7 represents a NULL or a mismatch in YMM6 and |
||||
- YMM7. */ |
||||
- kord %k0, %k1, %k7 |
||||
- |
||||
- kord %k4, %k5, %k0 |
||||
- kord %k6, %k7, %k1 |
||||
- |
||||
- /* Test each mask (32 bits) individually because for VEC_SIZE |
||||
- == 32 is not possible to OR the four masks and keep all bits |
||||
- in a 64-bit integer register, differing from SSE2 strcmp |
||||
- where ORing is possible. */ |
||||
- kortestd %k0, %k1 |
||||
- je L(loop) |
||||
- ktestd %k4, %k4 |
||||
+ |
||||
+ VPMINU %YMM0, %YMM2, %YMM8 |
||||
+ VPMINU %YMM4, %YMM6, %YMM9 |
||||
+ |
||||
+ /* A zero CHAR in YMM8 means that there is a null CHAR. */ |
||||
+ VPMINU %YMM8, %YMM9, %YMM8 |
||||
+ |
||||
+ /* Each bit set in K1 represents a non-null CHAR in YMM8. */ |
||||
+ VPTESTM %YMM8, %YMM8, %k1 |
||||
+ |
||||
+ /* (YMM ^ YMM): A non-zero CHAR represents a mismatch. */ |
||||
+ vpxorq (%rdx), %YMM0, %YMM1 |
||||
+ vpxorq VEC_SIZE(%rdx), %YMM2, %YMM3 |
||||
+ vpxorq (VEC_SIZE * 2)(%rdx), %YMM4, %YMM5 |
||||
+ vpxorq (VEC_SIZE * 3)(%rdx), %YMM6, %YMM7 |
||||
+ |
||||
+ vporq %YMM1, %YMM3, %YMM9 |
||||
+ vporq %YMM5, %YMM7, %YMM10 |
||||
+ |
||||
+ /* A non-zero CHAR in YMM9 represents a mismatch. */ |
||||
+ vporq %YMM9, %YMM10, %YMM9 |
||||
+ |
||||
+ /* Each bit cleared in K0 represents a mismatch or a null CHAR. */ |
||||
+ VPCMP $0, %YMMZERO, %YMM9, %k0{%k1} |
||||
+ kmovd %k0, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
+ je L(loop) |
||||
+ |
||||
+ /* Each bit set in K1 represents a non-null CHAR in YMM0. */ |
||||
+ VPTESTM %YMM0, %YMM0, %k1 |
||||
+ /* Each bit cleared in K0 represents a mismatch or a null CHAR |
||||
+ in YMM0 and (%rdx). */ |
||||
+ VPCMP $0, %YMMZERO, %YMM1, %k0{%k1} |
||||
+ kmovd %k0, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
je L(test_vec) |
||||
- kmovd %k4, %edi |
||||
- tzcntl %edi, %ecx |
||||
+ tzcntl %ecx, %ecx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
sall $2, %ecx |
||||
@@ -466,9 +458,18 @@ L(test_vec): |
||||
cmpq $VEC_SIZE, %r11 |
||||
jbe L(zero) |
||||
# endif |
||||
- ktestd %k5, %k5 |
||||
+ /* Each bit set in K1 represents a non-null CHAR in YMM2. */ |
||||
+ VPTESTM %YMM2, %YMM2, %k1 |
||||
+ /* Each bit cleared in K0 represents a mismatch or a null CHAR |
||||
+ in YMM2 and VEC_SIZE(%rdx). */ |
||||
+ VPCMP $0, %YMMZERO, %YMM3, %k0{%k1} |
||||
+ kmovd %k0, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
je L(test_2_vec) |
||||
- kmovd %k5, %ecx |
||||
tzcntl %ecx, %edi |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -512,9 +513,18 @@ L(test_2_vec): |
||||
cmpq $(VEC_SIZE * 2), %r11 |
||||
jbe L(zero) |
||||
# endif |
||||
- ktestd %k6, %k6 |
||||
+ /* Each bit set in K1 represents a non-null CHAR in YMM4. */ |
||||
+ VPTESTM %YMM4, %YMM4, %k1 |
||||
+ /* Each bit cleared in K0 represents a mismatch or a null CHAR |
||||
+ in YMM4 and (VEC_SIZE * 2)(%rdx). */ |
||||
+ VPCMP $0, %YMMZERO, %YMM5, %k0{%k1} |
||||
+ kmovd %k0, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
je L(test_3_vec) |
||||
- kmovd %k6, %ecx |
||||
tzcntl %ecx, %edi |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
@@ -558,8 +568,18 @@ L(test_3_vec): |
||||
cmpq $(VEC_SIZE * 3), %r11 |
||||
jbe L(zero) |
||||
# endif |
||||
- kmovd %k7, %esi |
||||
- tzcntl %esi, %ecx |
||||
+ /* Each bit set in K1 represents a non-null CHAR in YMM6. */ |
||||
+ VPTESTM %YMM6, %YMM6, %k1 |
||||
+ /* Each bit cleared in K0 represents a mismatch or a null CHAR |
||||
+ in YMM6 and (VEC_SIZE * 3)(%rdx). */ |
||||
+ VPCMP $0, %YMMZERO, %YMM7, %k0{%k1} |
||||
+ kmovd %k0, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
+ tzcntl %ecx, %ecx |
||||
# ifdef USE_AS_WCSCMP |
||||
/* NB: Multiply wchar_t count by 4 to get the number of bytes. */ |
||||
sall $2, %ecx |
||||
@@ -615,39 +635,51 @@ L(loop_cross_page): |
||||
|
||||
VMOVU (%rax, %r10), %YMM2 |
||||
VMOVU VEC_SIZE(%rax, %r10), %YMM3 |
||||
- VMOVU (%rdx, %r10), %YMM4 |
||||
- VMOVU VEC_SIZE(%rdx, %r10), %YMM5 |
||||
- |
||||
- VPCMP $4, %YMM4, %YMM2, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM2, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM4, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch in YMM2 and |
||||
- YMM4. */ |
||||
- kord %k0, %k1, %k1 |
||||
- |
||||
- VPCMP $4, %YMM5, %YMM3, %k3 |
||||
- VPCMP $0, %YMMZERO, %YMM3, %k4 |
||||
- VPCMP $0, %YMMZERO, %YMM5, %k5 |
||||
- kord %k4, %k5, %k4 |
||||
- /* Each bit in K3 represents a NULL or a mismatch in YMM3 and |
||||
- YMM5. */ |
||||
- kord %k3, %k4, %k3 |
||||
+ |
||||
+ /* Each bit set in K2 represents a non-null CHAR in YMM2. */ |
||||
+ VPTESTM %YMM2, %YMM2, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM2 and 32 bytes at (%rdx, %r10). */ |
||||
+ VPCMP $0, (%rdx, %r10), %YMM2, %k1{%k2} |
||||
+ kmovd %k1, %r9d |
||||
+ /* Don't use subl since it is the lower 16/32 bits of RDI |
||||
+ below. */ |
||||
+ notl %r9d |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ /* Only last 8 bits are valid. */ |
||||
+ andl $0xff, %r9d |
||||
+# endif |
||||
+ |
||||
+ /* Each bit set in K4 represents a non-null CHAR in YMM3. */ |
||||
+ VPTESTM %YMM3, %YMM3, %k4 |
||||
+ /* Each bit cleared in K3 represents a mismatch or a null CHAR |
||||
+ in YMM3 and 32 bytes at VEC_SIZE(%rdx, %r10). */ |
||||
+ VPCMP $0, VEC_SIZE(%rdx, %r10), %YMM3, %k3{%k4} |
||||
+ kmovd %k3, %edi |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ /* Don't use subl since it is the upper 8 bits of EDI below. */ |
||||
+ notl %edi |
||||
+ andl $0xff, %edi |
||||
+# else |
||||
+ incl %edi |
||||
+# endif |
||||
|
||||
# ifdef USE_AS_WCSCMP |
||||
- /* NB: Each bit in K1/K3 represents 4-byte element. */ |
||||
- kshiftlw $8, %k3, %k2 |
||||
+ /* NB: Each bit in EDI/R9D represents 4-byte element. */ |
||||
+ sall $8, %edi |
||||
/* NB: Divide shift count by 4 since each bit in K1 represent 4 |
||||
bytes. */ |
||||
movl %ecx, %SHIFT_REG32 |
||||
sarl $2, %SHIFT_REG32 |
||||
+ |
||||
+ /* Each bit in EDI represents a null CHAR or a mismatch. */ |
||||
+ orl %r9d, %edi |
||||
# else |
||||
- kshiftlq $32, %k3, %k2 |
||||
-# endif |
||||
+ salq $32, %rdi |
||||
|
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- korq %k1, %k2, %k1 |
||||
- kmovq %k1, %rdi |
||||
+ /* Each bit in RDI represents a null CHAR or a mismatch. */ |
||||
+ orq %r9, %rdi |
||||
+# endif |
||||
|
||||
/* Since ECX < VEC_SIZE * 2, simply skip the first ECX bytes. */ |
||||
shrxq %SHIFT_REG64, %rdi, %rdi |
||||
@@ -692,35 +724,45 @@ L(loop_cross_page_2_vec): |
||||
/* The first VEC_SIZE * 2 bytes match or are ignored. */ |
||||
VMOVU (VEC_SIZE * 2)(%rax, %r10), %YMM0 |
||||
VMOVU (VEC_SIZE * 3)(%rax, %r10), %YMM1 |
||||
- VMOVU (VEC_SIZE * 2)(%rdx, %r10), %YMM2 |
||||
- VMOVU (VEC_SIZE * 3)(%rdx, %r10), %YMM3 |
||||
- |
||||
- VPCMP $4, %YMM0, %YMM2, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM2, %k2 |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch in YMM0 and |
||||
- YMM2. */ |
||||
- kord %k0, %k1, %k1 |
||||
- |
||||
- VPCMP $4, %YMM1, %YMM3, %k3 |
||||
- VPCMP $0, %YMMZERO, %YMM1, %k4 |
||||
- VPCMP $0, %YMMZERO, %YMM3, %k5 |
||||
- kord %k4, %k5, %k4 |
||||
- /* Each bit in K3 represents a NULL or a mismatch in YMM1 and |
||||
- YMM3. */ |
||||
- kord %k3, %k4, %k3 |
||||
|
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at (VEC_SIZE * 2)(%rdx, %r10). */ |
||||
+ VPCMP $0, (VEC_SIZE * 2)(%rdx, %r10), %YMM0, %k1{%k2} |
||||
+ kmovd %k1, %r9d |
||||
+ /* Don't use subl since it is the lower 16/32 bits of RDI |
||||
+ below. */ |
||||
+ notl %r9d |
||||
# ifdef USE_AS_WCSCMP |
||||
- /* NB: Each bit in K1/K3 represents 4-byte element. */ |
||||
- kshiftlw $8, %k3, %k2 |
||||
+ /* Only last 8 bits are valid. */ |
||||
+ andl $0xff, %r9d |
||||
+# endif |
||||
+ |
||||
+ VPTESTM %YMM1, %YMM1, %k4 |
||||
+ /* Each bit cleared in K3 represents a mismatch or a null CHAR |
||||
+ in YMM1 and 32 bytes at (VEC_SIZE * 3)(%rdx, %r10). */ |
||||
+ VPCMP $0, (VEC_SIZE * 3)(%rdx, %r10), %YMM1, %k3{%k4} |
||||
+ kmovd %k3, %edi |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ /* Don't use subl since it is the upper 8 bits of EDI below. */ |
||||
+ notl %edi |
||||
+ andl $0xff, %edi |
||||
# else |
||||
- kshiftlq $32, %k3, %k2 |
||||
+ incl %edi |
||||
# endif |
||||
|
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- korq %k1, %k2, %k1 |
||||
- kmovq %k1, %rdi |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ /* NB: Each bit in EDI/R9D represents 4-byte element. */ |
||||
+ sall $8, %edi |
||||
+ |
||||
+ /* Each bit in EDI represents a null CHAR or a mismatch. */ |
||||
+ orl %r9d, %edi |
||||
+# else |
||||
+ salq $32, %rdi |
||||
+ |
||||
+ /* Each bit in RDI represents a null CHAR or a mismatch. */ |
||||
+ orq %r9, %rdi |
||||
+# endif |
||||
|
||||
xorl %r8d, %r8d |
||||
/* If ECX > VEC_SIZE * 2, skip ECX - (VEC_SIZE * 2) bytes. */ |
||||
@@ -729,12 +771,15 @@ L(loop_cross_page_2_vec): |
||||
/* R8 has number of bytes skipped. */ |
||||
movl %ecx, %r8d |
||||
# ifdef USE_AS_WCSCMP |
||||
- /* NB: Divide shift count by 4 since each bit in K1 represent 4 |
||||
+ /* NB: Divide shift count by 4 since each bit in RDI represent 4 |
||||
bytes. */ |
||||
sarl $2, %ecx |
||||
-# endif |
||||
+ /* Skip ECX bytes. */ |
||||
+ shrl %cl, %edi |
||||
+# else |
||||
/* Skip ECX bytes. */ |
||||
shrq %cl, %rdi |
||||
+# endif |
||||
1: |
||||
/* Before jumping back to the loop, set ESI to the number of |
||||
VEC_SIZE * 4 blocks before page crossing. */ |
||||
@@ -818,7 +863,7 @@ L(cross_page_loop): |
||||
movzbl (%rdi, %rdx), %eax |
||||
movzbl (%rsi, %rdx), %ecx |
||||
# endif |
||||
- /* Check null char. */ |
||||
+ /* Check null CHAR. */ |
||||
testl %eax, %eax |
||||
jne L(cross_page_loop) |
||||
/* Since %eax == 0, subtract is OK for both SIGNED and UNSIGNED |
||||
@@ -901,18 +946,17 @@ L(cross_page): |
||||
jg L(cross_page_1_vector) |
||||
L(loop_1_vector): |
||||
VMOVU (%rdi, %rdx), %YMM0 |
||||
- VMOVU (%rsi, %rdx), %YMM1 |
||||
- |
||||
- /* Each bit in K0 represents a mismatch in YMM0 and YMM1. */ |
||||
- VPCMP $4, %YMM0, %YMM1, %k0 |
||||
- VPCMP $0, %YMMZERO, %YMM0, %k1 |
||||
- VPCMP $0, %YMMZERO, %YMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in YMM0 or YMM1. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
+ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in YMM0 and 32 bytes at (%rsi, %rdx). */ |
||||
+ VPCMP $0, (%rsi, %rdx), %YMM0, %k1{%k2} |
||||
kmovd %k1, %ecx |
||||
- testl %ecx, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xff, %ecx |
||||
+# else |
||||
+ incl %ecx |
||||
+# endif |
||||
jne L(last_vector) |
||||
|
||||
addl $VEC_SIZE, %edx |
||||
@@ -931,18 +975,17 @@ L(cross_page_1_vector): |
||||
cmpl $(PAGE_SIZE - 16), %eax |
||||
jg L(cross_page_1_xmm) |
||||
VMOVU (%rdi, %rdx), %XMM0 |
||||
- VMOVU (%rsi, %rdx), %XMM1 |
||||
- |
||||
- /* Each bit in K0 represents a mismatch in XMM0 and XMM1. */ |
||||
- VPCMP $4, %XMM0, %XMM1, %k0 |
||||
- VPCMP $0, %XMMZERO, %XMM0, %k1 |
||||
- VPCMP $0, %XMMZERO, %XMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in XMM0 or XMM1. */ |
||||
- korw %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- korw %k0, %k1, %k1 |
||||
- kmovw %k1, %ecx |
||||
- testl %ecx, %ecx |
||||
+ |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in XMM0 and 16 bytes at (%rsi, %rdx). */ |
||||
+ VPCMP $0, (%rsi, %rdx), %XMM0, %k1{%k2} |
||||
+ kmovd %k1, %ecx |
||||
+# ifdef USE_AS_WCSCMP |
||||
+ subl $0xf, %ecx |
||||
+# else |
||||
+ subl $0xffff, %ecx |
||||
+# endif |
||||
jne L(last_vector) |
||||
|
||||
addl $16, %edx |
||||
@@ -965,25 +1008,16 @@ L(cross_page_1_xmm): |
||||
vmovq (%rdi, %rdx), %XMM0 |
||||
vmovq (%rsi, %rdx), %XMM1 |
||||
|
||||
- /* Each bit in K0 represents a mismatch in XMM0 and XMM1. */ |
||||
- VPCMP $4, %XMM0, %XMM1, %k0 |
||||
- VPCMP $0, %XMMZERO, %XMM0, %k1 |
||||
- VPCMP $0, %XMMZERO, %XMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in XMM0 or XMM1. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
- kmovd %k1, %ecx |
||||
- |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in XMM0 and XMM1. */ |
||||
+ VPCMP $0, %XMM1, %XMM0, %k1{%k2} |
||||
+ kmovb %k1, %ecx |
||||
# ifdef USE_AS_WCSCMP |
||||
- /* Only last 2 bits are valid. */ |
||||
- andl $0x3, %ecx |
||||
+ subl $0x3, %ecx |
||||
# else |
||||
- /* Only last 8 bits are valid. */ |
||||
- andl $0xff, %ecx |
||||
+ subl $0xff, %ecx |
||||
# endif |
||||
- |
||||
- testl %ecx, %ecx |
||||
jne L(last_vector) |
||||
|
||||
addl $8, %edx |
||||
@@ -1002,25 +1036,16 @@ L(cross_page_8bytes): |
||||
vmovd (%rdi, %rdx), %XMM0 |
||||
vmovd (%rsi, %rdx), %XMM1 |
||||
|
||||
- /* Each bit in K0 represents a mismatch in XMM0 and XMM1. */ |
||||
- VPCMP $4, %XMM0, %XMM1, %k0 |
||||
- VPCMP $0, %XMMZERO, %XMM0, %k1 |
||||
- VPCMP $0, %XMMZERO, %XMM1, %k2 |
||||
- /* Each bit in K1 represents a NULL in XMM0 or XMM1. */ |
||||
- kord %k1, %k2, %k1 |
||||
- /* Each bit in K1 represents a NULL or a mismatch. */ |
||||
- kord %k0, %k1, %k1 |
||||
+ VPTESTM %YMM0, %YMM0, %k2 |
||||
+ /* Each bit cleared in K1 represents a mismatch or a null CHAR |
||||
+ in XMM0 and XMM1. */ |
||||
+ VPCMP $0, %XMM1, %XMM0, %k1{%k2} |
||||
kmovd %k1, %ecx |
||||
- |
||||
# ifdef USE_AS_WCSCMP |
||||
- /* Only the last bit is valid. */ |
||||
- andl $0x1, %ecx |
||||
+ subl $0x1, %ecx |
||||
# else |
||||
- /* Only last 4 bits are valid. */ |
||||
- andl $0xf, %ecx |
||||
+ subl $0xf, %ecx |
||||
# endif |
||||
- |
||||
- testl %ecx, %ecx |
||||
jne L(last_vector) |
||||
|
||||
addl $4, %edx |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
commit a182bb7a3922404f79def09d79ef89678b4049f0 |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Fri Oct 29 12:56:53 2021 -0700 |
||||
|
||||
x86-64: Remove Prefer_AVX2_STRCMP |
||||
|
||||
Remove Prefer_AVX2_STRCMP to enable EVEX strcmp. When comparing 2 32-byte |
||||
strings, EVEX strcmp has been improved to require 1 load, 1 VPTESTM, 1 |
||||
VPCMP, 1 KMOVD and 1 INCL instead of 2 loads, 3 VPCMPs, 2 KORDs, 1 KMOVD |
||||
and 1 TESTL while AVX2 strcmp requires 1 load, 2 VPCMPEQs, 1 VPMINU, 1 |
||||
VPMOVMSKB and 1 TESTL. EVEX strcmp is now faster than AVX2 strcmp by up |
||||
to 40% on Tiger Lake and Ice Lake. |
||||
|
||||
(cherry picked from commit 14dbbf46a007ae5df36646b51ad0c9e5f5259f30) |
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c |
||||
index de4e3c3b7258120d..f4d4049e391cbabd 100644 |
||||
--- a/sysdeps/x86/cpu-features.c |
||||
+++ b/sysdeps/x86/cpu-features.c |
||||
@@ -574,14 +574,6 @@ disable_tsx: |
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM)) |
||||
cpu_features->preferred[index_arch_Prefer_No_VZEROUPPER] |
||||
|= bit_arch_Prefer_No_VZEROUPPER; |
||||
- |
||||
- /* Since to compare 2 32-byte strings, 256-bit EVEX strcmp |
||||
- requires 2 loads, 3 VPCMPs and 2 KORDs while AVX2 strcmp |
||||
- requires 1 load, 2 VPCMPEQs, 1 VPMINU and 1 VPMOVMSKB, |
||||
- AVX2 strcmp is faster than EVEX strcmp. */ |
||||
- if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)) |
||||
- cpu_features->preferred[index_arch_Prefer_AVX2_STRCMP] |
||||
- |= bit_arch_Prefer_AVX2_STRCMP; |
||||
} |
||||
|
||||
/* Avoid avoid short distance REP MOVSB on processor with FSRM. */ |
||||
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c |
||||
index 58f2fad4323d5d91..957db3ad229ba39f 100644 |
||||
--- a/sysdeps/x86/cpu-tunables.c |
||||
+++ b/sysdeps/x86/cpu-tunables.c |
||||
@@ -239,8 +239,6 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) |
||||
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, |
||||
Fast_Copy_Backward, |
||||
disable, 18); |
||||
- CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH |
||||
- (n, cpu_features, Prefer_AVX2_STRCMP, AVX2, disable, 18); |
||||
} |
||||
break; |
||||
case 19: |
||||
diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
index 3bdc76cf71007948..8250bfcbecd29a9f 100644 |
||||
--- a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
+++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
@@ -31,5 +31,4 @@ BIT (Prefer_ERMS) |
||||
BIT (Prefer_No_AVX512) |
||||
BIT (MathVec_Prefer_No_AVX512) |
||||
BIT (Prefer_FSRM) |
||||
-BIT (Prefer_AVX2_STRCMP) |
||||
BIT (Avoid_Short_Distance_REP_MOVSB) |
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c |
||||
index 62b7abeeee646ab4..7c2901bf44456259 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp.c |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp.c |
||||
@@ -43,8 +43,7 @@ IFUNC_SELECTOR (void) |
||||
{ |
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) |
||||
&& CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) |
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2) |
||||
- && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_AVX2_STRCMP)) |
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)) |
||||
return OPTIMIZE (evex); |
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM)) |
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c |
||||
index 60ba0fe356b31779..f94a421784bfe923 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strncmp.c |
||||
+++ b/sysdeps/x86_64/multiarch/strncmp.c |
||||
@@ -43,8 +43,7 @@ IFUNC_SELECTOR (void) |
||||
{ |
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) |
||||
&& CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) |
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2) |
||||
- && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_AVX2_STRCMP)) |
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)) |
||||
return OPTIMIZE (evex); |
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM)) |
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
commit 2e64237a8744dd50f9222293275fa52e7248ff76 |
||||
Author: Fangrui Song <maskray@google.com> |
||||
Date: Tue Nov 2 20:59:52 2021 -0700 |
||||
|
||||
x86-64: Replace movzx with movzbl |
||||
|
||||
Clang cannot assemble movzx in the AT&T dialect mode. |
||||
|
||||
../sysdeps/x86_64/strcmp.S:2232:16: error: invalid operand for instruction |
||||
movzx (%rsi), %ecx |
||||
^~~~ |
||||
|
||||
Change movzx to movzbl, which follows the AT&T dialect and is used |
||||
elsewhere in the file. |
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit 6720d36b6623c5e48c070d86acf61198b33e144e) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-sse42.S b/sysdeps/x86_64/multiarch/strcmp-sse42.S |
||||
index bc19547b09639071..6197a723b9e0606e 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp-sse42.S |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-sse42.S |
||||
@@ -1771,8 +1771,8 @@ LABEL(strcmp_exitz): |
||||
.p2align 4 |
||||
// XXX Same as code above |
||||
LABEL(Byte0): |
||||
- movzx (%rsi), %ecx |
||||
- movzx (%rdi), %eax |
||||
+ movzbl (%rsi), %ecx |
||||
+ movzbl (%rdi), %eax |
||||
|
||||
#if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L |
||||
leaq _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx |
||||
diff --git a/sysdeps/x86_64/strcmp.S b/sysdeps/x86_64/strcmp.S |
||||
index 824e648230a15739..7f8a1bc756f86aee 100644 |
||||
--- a/sysdeps/x86_64/strcmp.S |
||||
+++ b/sysdeps/x86_64/strcmp.S |
||||
@@ -2232,8 +2232,8 @@ LABEL(strcmp_exitz): |
||||
|
||||
.p2align 4 |
||||
LABEL(Byte0): |
||||
- movzx (%rsi), %ecx |
||||
- movzx (%rdi), %eax |
||||
+ movzbl (%rsi), %ecx |
||||
+ movzbl (%rdi), %eax |
||||
|
||||
#if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L |
||||
leaq _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx |
@ -0,0 +1,843 @@
@@ -0,0 +1,843 @@
|
||||
commit a7392db2ff2b9dd906500941ac6361dbe2211b0d |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Mon Nov 1 00:49:51 2021 -0500 |
||||
|
||||
x86: Optimize memmove-vec-unaligned-erms.S |
||||
|
||||
No bug. |
||||
|
||||
The optimizations are as follows: |
||||
|
||||
1) Always align entry to 64 bytes. This makes behavior more |
||||
predictable and makes other frontend optimizations easier. |
||||
|
||||
2) Make the L(more_8x_vec) cases 4k aliasing aware. This can have |
||||
significant benefits in the case that: |
||||
0 < (dst - src) < [256, 512] |
||||
|
||||
3) Align before `rep movsb`. For ERMS this is roughly a [0, 30%] |
||||
improvement and for FSRM [-10%, 25%]. |
||||
|
||||
In addition to these primary changes there is general cleanup |
||||
throughout to optimize the aligning routines and control flow logic. |
||||
|
||||
Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit a6b7502ec0c2da89a7437f43171f160d713e39c6) |
||||
|
||||
diff --git a/sysdeps/x86_64/memmove.S b/sysdeps/x86_64/memmove.S |
||||
index db106a7a1f23f268..b2b318084823dceb 100644 |
||||
--- a/sysdeps/x86_64/memmove.S |
||||
+++ b/sysdeps/x86_64/memmove.S |
||||
@@ -25,7 +25,7 @@ |
||||
/* Use movups and movaps for smaller code sizes. */ |
||||
#define VMOVU movups |
||||
#define VMOVA movaps |
||||
- |
||||
+#define MOV_SIZE 3 |
||||
#define SECTION(p) p |
||||
|
||||
#ifdef USE_MULTIARCH |
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms-rtm.S b/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms-rtm.S |
||||
index 1ec1962e861dbf63..67a55f0c85af841c 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms-rtm.S |
||||
+++ b/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms-rtm.S |
||||
@@ -4,7 +4,7 @@ |
||||
# define VMOVNT vmovntdq |
||||
# define VMOVU vmovdqu |
||||
# define VMOVA vmovdqa |
||||
- |
||||
+# define MOV_SIZE 4 |
||||
# define ZERO_UPPER_VEC_REGISTERS_RETURN \ |
||||
ZERO_UPPER_VEC_REGISTERS_RETURN_XTEST |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms.S |
||||
index e195e93f153c9512..975ae6c0515b83cb 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memmove-avx-unaligned-erms.S |
||||
@@ -4,7 +4,7 @@ |
||||
# define VMOVNT vmovntdq |
||||
# define VMOVU vmovdqu |
||||
# define VMOVA vmovdqa |
||||
- |
||||
+# define MOV_SIZE 4 |
||||
# define SECTION(p) p##.avx |
||||
# define MEMMOVE_SYMBOL(p,s) p##_avx_##s |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-avx512-unaligned-erms.S |
||||
index 848848ab39ff9326..0fa7126830af7acb 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memmove-avx512-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memmove-avx512-unaligned-erms.S |
||||
@@ -25,7 +25,7 @@ |
||||
# define VMOVU vmovdqu64 |
||||
# define VMOVA vmovdqa64 |
||||
# define VZEROUPPER |
||||
- |
||||
+# define MOV_SIZE 6 |
||||
# define SECTION(p) p##.evex512 |
||||
# define MEMMOVE_SYMBOL(p,s) p##_avx512_##s |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-evex-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-evex-unaligned-erms.S |
||||
index 0cbce8f944da51a0..88715441feaaccf5 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memmove-evex-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memmove-evex-unaligned-erms.S |
||||
@@ -25,7 +25,7 @@ |
||||
# define VMOVU vmovdqu64 |
||||
# define VMOVA vmovdqa64 |
||||
# define VZEROUPPER |
||||
- |
||||
+# define MOV_SIZE 6 |
||||
# define SECTION(p) p##.evex |
||||
# define MEMMOVE_SYMBOL(p,s) p##_evex_##s |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S |
||||
index abde8438d41f2320..7b27cbdda5fb99f7 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S |
||||
@@ -76,6 +76,25 @@ |
||||
# endif |
||||
#endif |
||||
|
||||
+/* Whether to align before movsb. Ultimately we want 64 byte |
||||
+ align and not worth it to load 4x VEC for VEC_SIZE == 16. */ |
||||
+#define ALIGN_MOVSB (VEC_SIZE > 16) |
||||
+/* Number of bytes to align movsb to. */ |
||||
+#define MOVSB_ALIGN_TO 64 |
||||
+ |
||||
+#define SMALL_MOV_SIZE (MOV_SIZE <= 4) |
||||
+#define LARGE_MOV_SIZE (MOV_SIZE > 4) |
||||
+ |
||||
+#if SMALL_MOV_SIZE + LARGE_MOV_SIZE != 1 |
||||
+# error MOV_SIZE Unknown |
||||
+#endif |
||||
+ |
||||
+#if LARGE_MOV_SIZE |
||||
+# define SMALL_SIZE_OFFSET (4) |
||||
+#else |
||||
+# define SMALL_SIZE_OFFSET (0) |
||||
+#endif |
||||
+ |
||||
#ifndef PAGE_SIZE |
||||
# define PAGE_SIZE 4096 |
||||
#endif |
||||
@@ -199,25 +218,21 @@ L(start): |
||||
# endif |
||||
cmp $VEC_SIZE, %RDX_LP |
||||
jb L(less_vec) |
||||
+ /* Load regardless. */ |
||||
+ VMOVU (%rsi), %VEC(0) |
||||
cmp $(VEC_SIZE * 2), %RDX_LP |
||||
ja L(more_2x_vec) |
||||
-#if !defined USE_MULTIARCH || !IS_IN (libc) |
||||
-L(last_2x_vec): |
||||
-#endif |
||||
/* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. */ |
||||
- VMOVU (%rsi), %VEC(0) |
||||
VMOVU -VEC_SIZE(%rsi,%rdx), %VEC(1) |
||||
VMOVU %VEC(0), (%rdi) |
||||
VMOVU %VEC(1), -VEC_SIZE(%rdi,%rdx) |
||||
-#if !defined USE_MULTIARCH || !IS_IN (libc) |
||||
-L(nop): |
||||
- ret |
||||
+#if !(defined USE_MULTIARCH && IS_IN (libc)) |
||||
+ ZERO_UPPER_VEC_REGISTERS_RETURN |
||||
#else |
||||
VZEROUPPER_RETURN |
||||
#endif |
||||
#if defined USE_MULTIARCH && IS_IN (libc) |
||||
END (MEMMOVE_SYMBOL (__memmove, unaligned)) |
||||
- |
||||
# if VEC_SIZE == 16 |
||||
ENTRY (__mempcpy_chk_erms) |
||||
cmp %RDX_LP, %RCX_LP |
||||
@@ -289,7 +304,7 @@ ENTRY (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned_erms)) |
||||
END (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned_erms)) |
||||
# endif |
||||
|
||||
-ENTRY (MEMMOVE_SYMBOL (__memmove, unaligned_erms)) |
||||
+ENTRY_P2ALIGN (MEMMOVE_SYMBOL (__memmove, unaligned_erms), 6) |
||||
movq %rdi, %rax |
||||
L(start_erms): |
||||
# ifdef __ILP32__ |
||||
@@ -298,310 +313,448 @@ L(start_erms): |
||||
# endif |
||||
cmp $VEC_SIZE, %RDX_LP |
||||
jb L(less_vec) |
||||
+ /* Load regardless. */ |
||||
+ VMOVU (%rsi), %VEC(0) |
||||
cmp $(VEC_SIZE * 2), %RDX_LP |
||||
ja L(movsb_more_2x_vec) |
||||
-L(last_2x_vec): |
||||
- /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. */ |
||||
- VMOVU (%rsi), %VEC(0) |
||||
- VMOVU -VEC_SIZE(%rsi,%rdx), %VEC(1) |
||||
+ /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. |
||||
+ */ |
||||
+ VMOVU -VEC_SIZE(%rsi, %rdx), %VEC(1) |
||||
VMOVU %VEC(0), (%rdi) |
||||
- VMOVU %VEC(1), -VEC_SIZE(%rdi,%rdx) |
||||
+ VMOVU %VEC(1), -VEC_SIZE(%rdi, %rdx) |
||||
L(return): |
||||
-#if VEC_SIZE > 16 |
||||
+# if VEC_SIZE > 16 |
||||
ZERO_UPPER_VEC_REGISTERS_RETURN |
||||
-#else |
||||
+# else |
||||
ret |
||||
+# endif |
||||
#endif |
||||
|
||||
-L(movsb): |
||||
- cmp __x86_rep_movsb_stop_threshold(%rip), %RDX_LP |
||||
- jae L(more_8x_vec) |
||||
- cmpq %rsi, %rdi |
||||
- jb 1f |
||||
- /* Source == destination is less common. */ |
||||
- je L(nop) |
||||
- leaq (%rsi,%rdx), %r9 |
||||
- cmpq %r9, %rdi |
||||
- /* Avoid slow backward REP MOVSB. */ |
||||
- jb L(more_8x_vec_backward) |
||||
-# if AVOID_SHORT_DISTANCE_REP_MOVSB |
||||
- testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) |
||||
- jz 3f |
||||
- movq %rdi, %rcx |
||||
- subq %rsi, %rcx |
||||
- jmp 2f |
||||
-# endif |
||||
-1: |
||||
-# if AVOID_SHORT_DISTANCE_REP_MOVSB |
||||
- testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) |
||||
- jz 3f |
||||
- movq %rsi, %rcx |
||||
- subq %rdi, %rcx |
||||
-2: |
||||
-/* Avoid "rep movsb" if RCX, the distance between source and destination, |
||||
- is N*4GB + [1..63] with N >= 0. */ |
||||
- cmpl $63, %ecx |
||||
- jbe L(more_2x_vec) /* Avoid "rep movsb" if ECX <= 63. */ |
||||
-3: |
||||
-# endif |
||||
- mov %RDX_LP, %RCX_LP |
||||
- rep movsb |
||||
-L(nop): |
||||
+#if LARGE_MOV_SIZE |
||||
+ /* If LARGE_MOV_SIZE this fits in the aligning bytes between the |
||||
+ ENTRY block and L(less_vec). */ |
||||
+ .p2align 4,, 8 |
||||
+L(between_4_7): |
||||
+ /* From 4 to 7. No branch when size == 4. */ |
||||
+ movl (%rsi), %ecx |
||||
+ movl (%rsi, %rdx), %esi |
||||
+ movl %ecx, (%rdi) |
||||
+ movl %esi, (%rdi, %rdx) |
||||
ret |
||||
#endif |
||||
|
||||
+ .p2align 4 |
||||
L(less_vec): |
||||
/* Less than 1 VEC. */ |
||||
#if VEC_SIZE != 16 && VEC_SIZE != 32 && VEC_SIZE != 64 |
||||
# error Unsupported VEC_SIZE! |
||||
#endif |
||||
#if VEC_SIZE > 32 |
||||
- cmpb $32, %dl |
||||
+ cmpl $32, %edx |
||||
jae L(between_32_63) |
||||
#endif |
||||
#if VEC_SIZE > 16 |
||||
- cmpb $16, %dl |
||||
+ cmpl $16, %edx |
||||
jae L(between_16_31) |
||||
#endif |
||||
- cmpb $8, %dl |
||||
+ cmpl $8, %edx |
||||
jae L(between_8_15) |
||||
- cmpb $4, %dl |
||||
+#if SMALL_MOV_SIZE |
||||
+ cmpl $4, %edx |
||||
+#else |
||||
+ subq $4, %rdx |
||||
+#endif |
||||
jae L(between_4_7) |
||||
- cmpb $1, %dl |
||||
- ja L(between_2_3) |
||||
- jb 1f |
||||
- movzbl (%rsi), %ecx |
||||
+ cmpl $(1 - SMALL_SIZE_OFFSET), %edx |
||||
+ jl L(copy_0) |
||||
+ movb (%rsi), %cl |
||||
+ je L(copy_1) |
||||
+ movzwl (-2 + SMALL_SIZE_OFFSET)(%rsi, %rdx), %esi |
||||
+ movw %si, (-2 + SMALL_SIZE_OFFSET)(%rdi, %rdx) |
||||
+L(copy_1): |
||||
movb %cl, (%rdi) |
||||
-1: |
||||
+L(copy_0): |
||||
ret |
||||
+ |
||||
+#if SMALL_MOV_SIZE |
||||
+ .p2align 4,, 8 |
||||
+L(between_4_7): |
||||
+ /* From 4 to 7. No branch when size == 4. */ |
||||
+ movl -4(%rsi, %rdx), %ecx |
||||
+ movl (%rsi), %esi |
||||
+ movl %ecx, -4(%rdi, %rdx) |
||||
+ movl %esi, (%rdi) |
||||
+ ret |
||||
+#endif |
||||
+ |
||||
+#if VEC_SIZE > 16 |
||||
+ /* From 16 to 31. No branch when size == 16. */ |
||||
+ .p2align 4,, 8 |
||||
+L(between_16_31): |
||||
+ vmovdqu (%rsi), %xmm0 |
||||
+ vmovdqu -16(%rsi, %rdx), %xmm1 |
||||
+ vmovdqu %xmm0, (%rdi) |
||||
+ vmovdqu %xmm1, -16(%rdi, %rdx) |
||||
+ /* No ymm registers have been touched. */ |
||||
+ ret |
||||
+#endif |
||||
+ |
||||
#if VEC_SIZE > 32 |
||||
+ .p2align 4,, 10 |
||||
L(between_32_63): |
||||
/* From 32 to 63. No branch when size == 32. */ |
||||
VMOVU (%rsi), %YMM0 |
||||
- VMOVU -32(%rsi,%rdx), %YMM1 |
||||
+ VMOVU -32(%rsi, %rdx), %YMM1 |
||||
VMOVU %YMM0, (%rdi) |
||||
- VMOVU %YMM1, -32(%rdi,%rdx) |
||||
- VZEROUPPER_RETURN |
||||
-#endif |
||||
-#if VEC_SIZE > 16 |
||||
- /* From 16 to 31. No branch when size == 16. */ |
||||
-L(between_16_31): |
||||
- VMOVU (%rsi), %XMM0 |
||||
- VMOVU -16(%rsi,%rdx), %XMM1 |
||||
- VMOVU %XMM0, (%rdi) |
||||
- VMOVU %XMM1, -16(%rdi,%rdx) |
||||
+ VMOVU %YMM1, -32(%rdi, %rdx) |
||||
VZEROUPPER_RETURN |
||||
#endif |
||||
+ |
||||
+ .p2align 4,, 10 |
||||
L(between_8_15): |
||||
/* From 8 to 15. No branch when size == 8. */ |
||||
- movq -8(%rsi,%rdx), %rcx |
||||
+ movq -8(%rsi, %rdx), %rcx |
||||
movq (%rsi), %rsi |
||||
- movq %rcx, -8(%rdi,%rdx) |
||||
movq %rsi, (%rdi) |
||||
+ movq %rcx, -8(%rdi, %rdx) |
||||
ret |
||||
-L(between_4_7): |
||||
- /* From 4 to 7. No branch when size == 4. */ |
||||
- movl -4(%rsi,%rdx), %ecx |
||||
- movl (%rsi), %esi |
||||
- movl %ecx, -4(%rdi,%rdx) |
||||
- movl %esi, (%rdi) |
||||
- ret |
||||
-L(between_2_3): |
||||
- /* From 2 to 3. No branch when size == 2. */ |
||||
- movzwl -2(%rsi,%rdx), %ecx |
||||
- movzwl (%rsi), %esi |
||||
- movw %cx, -2(%rdi,%rdx) |
||||
- movw %si, (%rdi) |
||||
- ret |
||||
|
||||
+ .p2align 4,, 10 |
||||
+L(last_4x_vec): |
||||
+ /* Copy from 2 * VEC + 1 to 4 * VEC, inclusively. */ |
||||
+ |
||||
+ /* VEC(0) and VEC(1) have already been loaded. */ |
||||
+ VMOVU -VEC_SIZE(%rsi, %rdx), %VEC(2) |
||||
+ VMOVU -(VEC_SIZE * 2)(%rsi, %rdx), %VEC(3) |
||||
+ VMOVU %VEC(0), (%rdi) |
||||
+ VMOVU %VEC(1), VEC_SIZE(%rdi) |
||||
+ VMOVU %VEC(2), -VEC_SIZE(%rdi, %rdx) |
||||
+ VMOVU %VEC(3), -(VEC_SIZE * 2)(%rdi, %rdx) |
||||
+ VZEROUPPER_RETURN |
||||
+ |
||||
+ .p2align 4 |
||||
#if defined USE_MULTIARCH && IS_IN (libc) |
||||
L(movsb_more_2x_vec): |
||||
cmp __x86_rep_movsb_threshold(%rip), %RDX_LP |
||||
ja L(movsb) |
||||
#endif |
||||
L(more_2x_vec): |
||||
- /* More than 2 * VEC and there may be overlap between destination |
||||
- and source. */ |
||||
+ /* More than 2 * VEC and there may be overlap between |
||||
+ destination and source. */ |
||||
cmpq $(VEC_SIZE * 8), %rdx |
||||
ja L(more_8x_vec) |
||||
+ /* Load VEC(1) regardless. VEC(0) has already been loaded. */ |
||||
+ VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
cmpq $(VEC_SIZE * 4), %rdx |
||||
jbe L(last_4x_vec) |
||||
- /* Copy from 4 * VEC + 1 to 8 * VEC, inclusively. */ |
||||
- VMOVU (%rsi), %VEC(0) |
||||
- VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
+ /* Copy from 4 * VEC + 1 to 8 * VEC, inclusively. */ |
||||
VMOVU (VEC_SIZE * 2)(%rsi), %VEC(2) |
||||
VMOVU (VEC_SIZE * 3)(%rsi), %VEC(3) |
||||
- VMOVU -VEC_SIZE(%rsi,%rdx), %VEC(4) |
||||
- VMOVU -(VEC_SIZE * 2)(%rsi,%rdx), %VEC(5) |
||||
- VMOVU -(VEC_SIZE * 3)(%rsi,%rdx), %VEC(6) |
||||
- VMOVU -(VEC_SIZE * 4)(%rsi,%rdx), %VEC(7) |
||||
+ VMOVU -VEC_SIZE(%rsi, %rdx), %VEC(4) |
||||
+ VMOVU -(VEC_SIZE * 2)(%rsi, %rdx), %VEC(5) |
||||
+ VMOVU -(VEC_SIZE * 3)(%rsi, %rdx), %VEC(6) |
||||
+ VMOVU -(VEC_SIZE * 4)(%rsi, %rdx), %VEC(7) |
||||
VMOVU %VEC(0), (%rdi) |
||||
VMOVU %VEC(1), VEC_SIZE(%rdi) |
||||
VMOVU %VEC(2), (VEC_SIZE * 2)(%rdi) |
||||
VMOVU %VEC(3), (VEC_SIZE * 3)(%rdi) |
||||
- VMOVU %VEC(4), -VEC_SIZE(%rdi,%rdx) |
||||
- VMOVU %VEC(5), -(VEC_SIZE * 2)(%rdi,%rdx) |
||||
- VMOVU %VEC(6), -(VEC_SIZE * 3)(%rdi,%rdx) |
||||
- VMOVU %VEC(7), -(VEC_SIZE * 4)(%rdi,%rdx) |
||||
- VZEROUPPER_RETURN |
||||
-L(last_4x_vec): |
||||
- /* Copy from 2 * VEC + 1 to 4 * VEC, inclusively. */ |
||||
- VMOVU (%rsi), %VEC(0) |
||||
- VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
- VMOVU -VEC_SIZE(%rsi,%rdx), %VEC(2) |
||||
- VMOVU -(VEC_SIZE * 2)(%rsi,%rdx), %VEC(3) |
||||
- VMOVU %VEC(0), (%rdi) |
||||
- VMOVU %VEC(1), VEC_SIZE(%rdi) |
||||
- VMOVU %VEC(2), -VEC_SIZE(%rdi,%rdx) |
||||
- VMOVU %VEC(3), -(VEC_SIZE * 2)(%rdi,%rdx) |
||||
+ VMOVU %VEC(4), -VEC_SIZE(%rdi, %rdx) |
||||
+ VMOVU %VEC(5), -(VEC_SIZE * 2)(%rdi, %rdx) |
||||
+ VMOVU %VEC(6), -(VEC_SIZE * 3)(%rdi, %rdx) |
||||
+ VMOVU %VEC(7), -(VEC_SIZE * 4)(%rdi, %rdx) |
||||
VZEROUPPER_RETURN |
||||
|
||||
+ .p2align 4,, 4 |
||||
L(more_8x_vec): |
||||
+ movq %rdi, %rcx |
||||
+ subq %rsi, %rcx |
||||
+ /* Go to backwards temporal copy if overlap no matter what as |
||||
+ backward REP MOVSB is slow and we don't want to use NT stores if |
||||
+ there is overlap. */ |
||||
+ cmpq %rdx, %rcx |
||||
+ /* L(more_8x_vec_backward_check_nop) checks for src == dst. */ |
||||
+ jb L(more_8x_vec_backward_check_nop) |
||||
/* Check if non-temporal move candidate. */ |
||||
#if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) |
||||
/* Check non-temporal store threshold. */ |
||||
- cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP |
||||
+ cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP |
||||
ja L(large_memcpy_2x) |
||||
#endif |
||||
- /* Entry if rdx is greater than non-temporal threshold but there |
||||
- is overlap. */ |
||||
+ /* To reach this point there cannot be overlap and dst > src. So |
||||
+ check for overlap and src > dst in which case correctness |
||||
+ requires forward copy. Otherwise decide between backward/forward |
||||
+ copy depending on address aliasing. */ |
||||
+ |
||||
+ /* Entry if rdx is greater than __x86_rep_movsb_stop_threshold |
||||
+ but less than __x86_shared_non_temporal_threshold. */ |
||||
L(more_8x_vec_check): |
||||
- cmpq %rsi, %rdi |
||||
- ja L(more_8x_vec_backward) |
||||
- /* Source == destination is less common. */ |
||||
- je L(nop) |
||||
- /* Load the first VEC and last 4 * VEC to support overlapping |
||||
- addresses. */ |
||||
- VMOVU (%rsi), %VEC(4) |
||||
+ /* rcx contains dst - src. Add back length (rdx). */ |
||||
+ leaq (%rcx, %rdx), %r8 |
||||
+ /* If r8 has different sign than rcx then there is overlap so we |
||||
+ must do forward copy. */ |
||||
+ xorq %rcx, %r8 |
||||
+ /* Isolate just sign bit of r8. */ |
||||
+ shrq $63, %r8 |
||||
+ /* Get 4k difference dst - src. */ |
||||
+ andl $(PAGE_SIZE - 256), %ecx |
||||
+ /* If r8 is non-zero must do foward for correctness. Otherwise |
||||
+ if ecx is non-zero there is 4k False Alaising so do backward |
||||
+ copy. */ |
||||
+ addl %r8d, %ecx |
||||
+ jz L(more_8x_vec_backward) |
||||
+ |
||||
+ /* if rdx is greater than __x86_shared_non_temporal_threshold |
||||
+ but there is overlap, or from short distance movsb. */ |
||||
+L(more_8x_vec_forward): |
||||
+ /* Load first and last 4 * VEC to support overlapping addresses. |
||||
+ */ |
||||
+ |
||||
+ /* First vec was already loaded into VEC(0). */ |
||||
VMOVU -VEC_SIZE(%rsi, %rdx), %VEC(5) |
||||
VMOVU -(VEC_SIZE * 2)(%rsi, %rdx), %VEC(6) |
||||
+ /* Save begining of dst. */ |
||||
+ movq %rdi, %rcx |
||||
+ /* Align dst to VEC_SIZE - 1. */ |
||||
+ orq $(VEC_SIZE - 1), %rdi |
||||
VMOVU -(VEC_SIZE * 3)(%rsi, %rdx), %VEC(7) |
||||
VMOVU -(VEC_SIZE * 4)(%rsi, %rdx), %VEC(8) |
||||
- /* Save start and stop of the destination buffer. */ |
||||
- movq %rdi, %r11 |
||||
- leaq -VEC_SIZE(%rdi, %rdx), %rcx |
||||
- /* Align destination for aligned stores in the loop. Compute |
||||
- how much destination is misaligned. */ |
||||
- movq %rdi, %r8 |
||||
- andq $(VEC_SIZE - 1), %r8 |
||||
- /* Get the negative of offset for alignment. */ |
||||
- subq $VEC_SIZE, %r8 |
||||
- /* Adjust source. */ |
||||
- subq %r8, %rsi |
||||
- /* Adjust destination which should be aligned now. */ |
||||
- subq %r8, %rdi |
||||
- /* Adjust length. */ |
||||
- addq %r8, %rdx |
||||
|
||||
- .p2align 4 |
||||
+ /* Subtract dst from src. Add back after dst aligned. */ |
||||
+ subq %rcx, %rsi |
||||
+ /* Finish aligning dst. */ |
||||
+ incq %rdi |
||||
+ /* Restore src adjusted with new value for aligned dst. */ |
||||
+ addq %rdi, %rsi |
||||
+ /* Store end of buffer minus tail in rdx. */ |
||||
+ leaq (VEC_SIZE * -4)(%rcx, %rdx), %rdx |
||||
+ |
||||
+ /* Dont use multi-byte nop to align. */ |
||||
+ .p2align 4,, 11 |
||||
L(loop_4x_vec_forward): |
||||
/* Copy 4 * VEC a time forward. */ |
||||
- VMOVU (%rsi), %VEC(0) |
||||
- VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
- VMOVU (VEC_SIZE * 2)(%rsi), %VEC(2) |
||||
- VMOVU (VEC_SIZE * 3)(%rsi), %VEC(3) |
||||
+ VMOVU (%rsi), %VEC(1) |
||||
+ VMOVU VEC_SIZE(%rsi), %VEC(2) |
||||
+ VMOVU (VEC_SIZE * 2)(%rsi), %VEC(3) |
||||
+ VMOVU (VEC_SIZE * 3)(%rsi), %VEC(4) |
||||
subq $-(VEC_SIZE * 4), %rsi |
||||
- addq $-(VEC_SIZE * 4), %rdx |
||||
- VMOVA %VEC(0), (%rdi) |
||||
- VMOVA %VEC(1), VEC_SIZE(%rdi) |
||||
- VMOVA %VEC(2), (VEC_SIZE * 2)(%rdi) |
||||
- VMOVA %VEC(3), (VEC_SIZE * 3)(%rdi) |
||||
+ VMOVA %VEC(1), (%rdi) |
||||
+ VMOVA %VEC(2), VEC_SIZE(%rdi) |
||||
+ VMOVA %VEC(3), (VEC_SIZE * 2)(%rdi) |
||||
+ VMOVA %VEC(4), (VEC_SIZE * 3)(%rdi) |
||||
subq $-(VEC_SIZE * 4), %rdi |
||||
- cmpq $(VEC_SIZE * 4), %rdx |
||||
+ cmpq %rdi, %rdx |
||||
ja L(loop_4x_vec_forward) |
||||
/* Store the last 4 * VEC. */ |
||||
- VMOVU %VEC(5), (%rcx) |
||||
- VMOVU %VEC(6), -VEC_SIZE(%rcx) |
||||
- VMOVU %VEC(7), -(VEC_SIZE * 2)(%rcx) |
||||
- VMOVU %VEC(8), -(VEC_SIZE * 3)(%rcx) |
||||
+ VMOVU %VEC(5), (VEC_SIZE * 3)(%rdx) |
||||
+ VMOVU %VEC(6), (VEC_SIZE * 2)(%rdx) |
||||
+ VMOVU %VEC(7), VEC_SIZE(%rdx) |
||||
+ VMOVU %VEC(8), (%rdx) |
||||
/* Store the first VEC. */ |
||||
- VMOVU %VEC(4), (%r11) |
||||
+ VMOVU %VEC(0), (%rcx) |
||||
+ /* Keep L(nop_backward) target close to jmp for 2-byte encoding. |
||||
+ */ |
||||
+L(nop_backward): |
||||
VZEROUPPER_RETURN |
||||
|
||||
+ .p2align 4,, 8 |
||||
+L(more_8x_vec_backward_check_nop): |
||||
+ /* rcx contains dst - src. Test for dst == src to skip all of |
||||
+ memmove. */ |
||||
+ testq %rcx, %rcx |
||||
+ jz L(nop_backward) |
||||
L(more_8x_vec_backward): |
||||
/* Load the first 4 * VEC and last VEC to support overlapping |
||||
addresses. */ |
||||
- VMOVU (%rsi), %VEC(4) |
||||
+ |
||||
+ /* First vec was also loaded into VEC(0). */ |
||||
VMOVU VEC_SIZE(%rsi), %VEC(5) |
||||
VMOVU (VEC_SIZE * 2)(%rsi), %VEC(6) |
||||
+ /* Begining of region for 4x backward copy stored in rcx. */ |
||||
+ leaq (VEC_SIZE * -4 + -1)(%rdi, %rdx), %rcx |
||||
VMOVU (VEC_SIZE * 3)(%rsi), %VEC(7) |
||||
- VMOVU -VEC_SIZE(%rsi,%rdx), %VEC(8) |
||||
- /* Save stop of the destination buffer. */ |
||||
- leaq -VEC_SIZE(%rdi, %rdx), %r11 |
||||
- /* Align destination end for aligned stores in the loop. Compute |
||||
- how much destination end is misaligned. */ |
||||
- leaq -VEC_SIZE(%rsi, %rdx), %rcx |
||||
- movq %r11, %r9 |
||||
- movq %r11, %r8 |
||||
- andq $(VEC_SIZE - 1), %r8 |
||||
- /* Adjust source. */ |
||||
- subq %r8, %rcx |
||||
- /* Adjust the end of destination which should be aligned now. */ |
||||
- subq %r8, %r9 |
||||
- /* Adjust length. */ |
||||
- subq %r8, %rdx |
||||
- |
||||
- .p2align 4 |
||||
+ VMOVU -VEC_SIZE(%rsi, %rdx), %VEC(8) |
||||
+ /* Subtract dst from src. Add back after dst aligned. */ |
||||
+ subq %rdi, %rsi |
||||
+ /* Align dst. */ |
||||
+ andq $-(VEC_SIZE), %rcx |
||||
+ /* Restore src. */ |
||||
+ addq %rcx, %rsi |
||||
+ |
||||
+ /* Don't use multi-byte nop to align. */ |
||||
+ .p2align 4,, 11 |
||||
L(loop_4x_vec_backward): |
||||
/* Copy 4 * VEC a time backward. */ |
||||
- VMOVU (%rcx), %VEC(0) |
||||
- VMOVU -VEC_SIZE(%rcx), %VEC(1) |
||||
- VMOVU -(VEC_SIZE * 2)(%rcx), %VEC(2) |
||||
- VMOVU -(VEC_SIZE * 3)(%rcx), %VEC(3) |
||||
- addq $-(VEC_SIZE * 4), %rcx |
||||
- addq $-(VEC_SIZE * 4), %rdx |
||||
- VMOVA %VEC(0), (%r9) |
||||
- VMOVA %VEC(1), -VEC_SIZE(%r9) |
||||
- VMOVA %VEC(2), -(VEC_SIZE * 2)(%r9) |
||||
- VMOVA %VEC(3), -(VEC_SIZE * 3)(%r9) |
||||
- addq $-(VEC_SIZE * 4), %r9 |
||||
- cmpq $(VEC_SIZE * 4), %rdx |
||||
- ja L(loop_4x_vec_backward) |
||||
+ VMOVU (VEC_SIZE * 3)(%rsi), %VEC(1) |
||||
+ VMOVU (VEC_SIZE * 2)(%rsi), %VEC(2) |
||||
+ VMOVU (VEC_SIZE * 1)(%rsi), %VEC(3) |
||||
+ VMOVU (VEC_SIZE * 0)(%rsi), %VEC(4) |
||||
+ addq $(VEC_SIZE * -4), %rsi |
||||
+ VMOVA %VEC(1), (VEC_SIZE * 3)(%rcx) |
||||
+ VMOVA %VEC(2), (VEC_SIZE * 2)(%rcx) |
||||
+ VMOVA %VEC(3), (VEC_SIZE * 1)(%rcx) |
||||
+ VMOVA %VEC(4), (VEC_SIZE * 0)(%rcx) |
||||
+ addq $(VEC_SIZE * -4), %rcx |
||||
+ cmpq %rcx, %rdi |
||||
+ jb L(loop_4x_vec_backward) |
||||
/* Store the first 4 * VEC. */ |
||||
- VMOVU %VEC(4), (%rdi) |
||||
+ VMOVU %VEC(0), (%rdi) |
||||
VMOVU %VEC(5), VEC_SIZE(%rdi) |
||||
VMOVU %VEC(6), (VEC_SIZE * 2)(%rdi) |
||||
VMOVU %VEC(7), (VEC_SIZE * 3)(%rdi) |
||||
/* Store the last VEC. */ |
||||
- VMOVU %VEC(8), (%r11) |
||||
+ VMOVU %VEC(8), -VEC_SIZE(%rdx, %rdi) |
||||
+ VZEROUPPER_RETURN |
||||
+ |
||||
+#if defined USE_MULTIARCH && IS_IN (libc) |
||||
+ /* L(skip_short_movsb_check) is only used with ERMS. Not for |
||||
+ FSRM. */ |
||||
+ .p2align 5,, 16 |
||||
+# if ALIGN_MOVSB |
||||
+L(skip_short_movsb_check): |
||||
+# if MOVSB_ALIGN_TO > VEC_SIZE |
||||
+ VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
+# endif |
||||
+# if MOVSB_ALIGN_TO > (VEC_SIZE * 2) |
||||
+# error Unsupported MOVSB_ALIGN_TO |
||||
+# endif |
||||
+ /* If CPU does not have FSRM two options for aligning. Align src |
||||
+ if dst and src 4k alias. Otherwise align dst. */ |
||||
+ testl $(PAGE_SIZE - 512), %ecx |
||||
+ jnz L(movsb_align_dst) |
||||
+ /* Fall through. dst and src 4k alias. It's better to align src |
||||
+ here because the bottleneck will be loads dues to the false |
||||
+ dependency on dst. */ |
||||
+ |
||||
+ /* rcx already has dst - src. */ |
||||
+ movq %rcx, %r9 |
||||
+ /* Add src to len. Subtract back after src aligned. -1 because |
||||
+ src is initially aligned to MOVSB_ALIGN_TO - 1. */ |
||||
+ leaq -1(%rsi, %rdx), %rcx |
||||
+ /* Inclusively align src to MOVSB_ALIGN_TO - 1. */ |
||||
+ orq $(MOVSB_ALIGN_TO - 1), %rsi |
||||
+ /* Restore dst and len adjusted with new values for aligned dst. |
||||
+ */ |
||||
+ leaq 1(%rsi, %r9), %rdi |
||||
+ subq %rsi, %rcx |
||||
+ /* Finish aligning src. */ |
||||
+ incq %rsi |
||||
+ |
||||
+ rep movsb |
||||
+ |
||||
+ VMOVU %VEC(0), (%r8) |
||||
+# if MOVSB_ALIGN_TO > VEC_SIZE |
||||
+ VMOVU %VEC(1), VEC_SIZE(%r8) |
||||
+# endif |
||||
VZEROUPPER_RETURN |
||||
+# endif |
||||
+ |
||||
+ .p2align 4,, 12 |
||||
+L(movsb): |
||||
+ movq %rdi, %rcx |
||||
+ subq %rsi, %rcx |
||||
+ /* Go to backwards temporal copy if overlap no matter what as |
||||
+ backward REP MOVSB is slow and we don't want to use NT stores if |
||||
+ there is overlap. */ |
||||
+ cmpq %rdx, %rcx |
||||
+ /* L(more_8x_vec_backward_check_nop) checks for src == dst. */ |
||||
+ jb L(more_8x_vec_backward_check_nop) |
||||
+# if ALIGN_MOVSB |
||||
+ /* Save dest for storing aligning VECs later. */ |
||||
+ movq %rdi, %r8 |
||||
+# endif |
||||
+ /* If above __x86_rep_movsb_stop_threshold most likely is |
||||
+ candidate for NT moves aswell. */ |
||||
+ cmp __x86_rep_movsb_stop_threshold(%rip), %RDX_LP |
||||
+ jae L(large_memcpy_2x_check) |
||||
+# if AVOID_SHORT_DISTANCE_REP_MOVSB || ALIGN_MOVSB |
||||
+ /* Only avoid short movsb if CPU has FSRM. */ |
||||
+ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) |
||||
+ jz L(skip_short_movsb_check) |
||||
+# if AVOID_SHORT_DISTANCE_REP_MOVSB |
||||
+ /* Avoid "rep movsb" if RCX, the distance between source and |
||||
+ destination, is N*4GB + [1..63] with N >= 0. */ |
||||
+ |
||||
+ /* ecx contains dst - src. Early check for backward copy |
||||
+ conditions means only case of slow movsb with src = dst + [0, |
||||
+ 63] is ecx in [-63, 0]. Use unsigned comparison with -64 check |
||||
+ for that case. */ |
||||
+ cmpl $-64, %ecx |
||||
+ ja L(more_8x_vec_forward) |
||||
+# endif |
||||
+# endif |
||||
+# if ALIGN_MOVSB |
||||
+# if MOVSB_ALIGN_TO > VEC_SIZE |
||||
+ VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
+# endif |
||||
+# if MOVSB_ALIGN_TO > (VEC_SIZE * 2) |
||||
+# error Unsupported MOVSB_ALIGN_TO |
||||
+# endif |
||||
+ /* Fall through means cpu has FSRM. In that case exclusively |
||||
+ align destination. */ |
||||
+L(movsb_align_dst): |
||||
+ /* Subtract dst from src. Add back after dst aligned. */ |
||||
+ subq %rdi, %rsi |
||||
+ /* Exclusively align dst to MOVSB_ALIGN_TO (64). */ |
||||
+ addq $(MOVSB_ALIGN_TO - 1), %rdi |
||||
+ /* Add dst to len. Subtract back after dst aligned. */ |
||||
+ leaq (%r8, %rdx), %rcx |
||||
+ /* Finish aligning dst. */ |
||||
+ andq $-(MOVSB_ALIGN_TO), %rdi |
||||
+ /* Restore src and len adjusted with new values for aligned dst. |
||||
+ */ |
||||
+ addq %rdi, %rsi |
||||
+ subq %rdi, %rcx |
||||
+ |
||||
+ rep movsb |
||||
+ |
||||
+ /* Store VECs loaded for aligning. */ |
||||
+ VMOVU %VEC(0), (%r8) |
||||
+# if MOVSB_ALIGN_TO > VEC_SIZE |
||||
+ VMOVU %VEC(1), VEC_SIZE(%r8) |
||||
+# endif |
||||
+ VZEROUPPER_RETURN |
||||
+# else /* !ALIGN_MOVSB. */ |
||||
+L(skip_short_movsb_check): |
||||
+ mov %RDX_LP, %RCX_LP |
||||
+ rep movsb |
||||
+ ret |
||||
+# endif |
||||
+#endif |
||||
|
||||
+ .p2align 4,, 10 |
||||
#if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) |
||||
- .p2align 4 |
||||
+L(large_memcpy_2x_check): |
||||
+ cmp __x86_rep_movsb_threshold(%rip), %RDX_LP |
||||
+ jb L(more_8x_vec_check) |
||||
L(large_memcpy_2x): |
||||
- /* Compute absolute value of difference between source and |
||||
- destination. */ |
||||
- movq %rdi, %r9 |
||||
- subq %rsi, %r9 |
||||
- movq %r9, %r8 |
||||
- leaq -1(%r9), %rcx |
||||
- sarq $63, %r8 |
||||
- xorq %r8, %r9 |
||||
- subq %r8, %r9 |
||||
- /* Don't use non-temporal store if there is overlap between |
||||
- destination and source since destination may be in cache when |
||||
- source is loaded. */ |
||||
- cmpq %r9, %rdx |
||||
- ja L(more_8x_vec_check) |
||||
+ /* To reach this point it is impossible for dst > src and |
||||
+ overlap. Remaining to check is src > dst and overlap. rcx |
||||
+ already contains dst - src. Negate rcx to get src - dst. If |
||||
+ length > rcx then there is overlap and forward copy is best. */ |
||||
+ negq %rcx |
||||
+ cmpq %rcx, %rdx |
||||
+ ja L(more_8x_vec_forward) |
||||
|
||||
/* Cache align destination. First store the first 64 bytes then |
||||
adjust alignments. */ |
||||
- VMOVU (%rsi), %VEC(8) |
||||
-#if VEC_SIZE < 64 |
||||
- VMOVU VEC_SIZE(%rsi), %VEC(9) |
||||
-#if VEC_SIZE < 32 |
||||
- VMOVU (VEC_SIZE * 2)(%rsi), %VEC(10) |
||||
- VMOVU (VEC_SIZE * 3)(%rsi), %VEC(11) |
||||
-#endif |
||||
-#endif |
||||
- VMOVU %VEC(8), (%rdi) |
||||
-#if VEC_SIZE < 64 |
||||
- VMOVU %VEC(9), VEC_SIZE(%rdi) |
||||
-#if VEC_SIZE < 32 |
||||
- VMOVU %VEC(10), (VEC_SIZE * 2)(%rdi) |
||||
- VMOVU %VEC(11), (VEC_SIZE * 3)(%rdi) |
||||
-#endif |
||||
-#endif |
||||
+ |
||||
+ /* First vec was also loaded into VEC(0). */ |
||||
+# if VEC_SIZE < 64 |
||||
+ VMOVU VEC_SIZE(%rsi), %VEC(1) |
||||
+# if VEC_SIZE < 32 |
||||
+ VMOVU (VEC_SIZE * 2)(%rsi), %VEC(2) |
||||
+ VMOVU (VEC_SIZE * 3)(%rsi), %VEC(3) |
||||
+# endif |
||||
+# endif |
||||
+ VMOVU %VEC(0), (%rdi) |
||||
+# if VEC_SIZE < 64 |
||||
+ VMOVU %VEC(1), VEC_SIZE(%rdi) |
||||
+# if VEC_SIZE < 32 |
||||
+ VMOVU %VEC(2), (VEC_SIZE * 2)(%rdi) |
||||
+ VMOVU %VEC(3), (VEC_SIZE * 3)(%rdi) |
||||
+# endif |
||||
+# endif |
||||
+ |
||||
/* Adjust source, destination, and size. */ |
||||
movq %rdi, %r8 |
||||
andq $63, %r8 |
||||
@@ -614,9 +767,13 @@ L(large_memcpy_2x): |
||||
/* Adjust length. */ |
||||
addq %r8, %rdx |
||||
|
||||
- /* Test if source and destination addresses will alias. If they do |
||||
- the larger pipeline in large_memcpy_4x alleviated the |
||||
+ /* Test if source and destination addresses will alias. If they |
||||
+ do the larger pipeline in large_memcpy_4x alleviated the |
||||
performance drop. */ |
||||
+ |
||||
+ /* ecx contains -(dst - src). not ecx will return dst - src - 1 |
||||
+ which works for testing aliasing. */ |
||||
+ notl %ecx |
||||
testl $(PAGE_SIZE - VEC_SIZE * 8), %ecx |
||||
jz L(large_memcpy_4x) |
||||
|
||||
@@ -704,8 +861,8 @@ L(loop_large_memcpy_4x_outer): |
||||
/* ecx stores inner loop counter. */ |
||||
movl $(PAGE_SIZE / LARGE_LOAD_SIZE), %ecx |
||||
L(loop_large_memcpy_4x_inner): |
||||
- /* Only one prefetch set per page as doing 4 pages give more time |
||||
- for prefetcher to keep up. */ |
||||
+ /* Only one prefetch set per page as doing 4 pages give more |
||||
+ time for prefetcher to keep up. */ |
||||
PREFETCH_ONE_SET(1, (%rsi), PREFETCHED_LOAD_SIZE) |
||||
PREFETCH_ONE_SET(1, (%rsi), PAGE_SIZE + PREFETCHED_LOAD_SIZE) |
||||
PREFETCH_ONE_SET(1, (%rsi), PAGE_SIZE * 2 + PREFETCHED_LOAD_SIZE) |
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
commit cecbac52123456e2fbcff062a4165bf7b9174797 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Mon Nov 1 00:49:52 2021 -0500 |
||||
|
||||
x86: Double size of ERMS rep_movsb_threshold in dl-cacheinfo.h |
||||
|
||||
No bug. |
||||
|
||||
This patch doubles the rep_movsb_threshold when using ERMS. Based on |
||||
benchmarks the vector copy loop, especially now that it handles 4k |
||||
aliasing, is better for these medium ranged. |
||||
|
||||
On Skylake with ERMS: |
||||
|
||||
Size, Align1, Align2, dst>src,(rep movsb) / (vec copy) |
||||
4096, 0, 0, 0, 0.975 |
||||
4096, 0, 0, 1, 0.953 |
||||
4096, 12, 0, 0, 0.969 |
||||
4096, 12, 0, 1, 0.872 |
||||
4096, 44, 0, 0, 0.979 |
||||
4096, 44, 0, 1, 0.83 |
||||
4096, 0, 12, 0, 1.006 |
||||
4096, 0, 12, 1, 0.989 |
||||
4096, 0, 44, 0, 0.739 |
||||
4096, 0, 44, 1, 0.942 |
||||
4096, 12, 12, 0, 1.009 |
||||
4096, 12, 12, 1, 0.973 |
||||
4096, 44, 44, 0, 0.791 |
||||
4096, 44, 44, 1, 0.961 |
||||
4096, 2048, 0, 0, 0.978 |
||||
4096, 2048, 0, 1, 0.951 |
||||
4096, 2060, 0, 0, 0.986 |
||||
4096, 2060, 0, 1, 0.963 |
||||
4096, 2048, 12, 0, 0.971 |
||||
4096, 2048, 12, 1, 0.941 |
||||
4096, 2060, 12, 0, 0.977 |
||||
4096, 2060, 12, 1, 0.949 |
||||
8192, 0, 0, 0, 0.85 |
||||
8192, 0, 0, 1, 0.845 |
||||
8192, 13, 0, 0, 0.937 |
||||
8192, 13, 0, 1, 0.939 |
||||
8192, 45, 0, 0, 0.932 |
||||
8192, 45, 0, 1, 0.927 |
||||
8192, 0, 13, 0, 0.621 |
||||
8192, 0, 13, 1, 0.62 |
||||
8192, 0, 45, 0, 0.53 |
||||
8192, 0, 45, 1, 0.516 |
||||
8192, 13, 13, 0, 0.664 |
||||
8192, 13, 13, 1, 0.659 |
||||
8192, 45, 45, 0, 0.593 |
||||
8192, 45, 45, 1, 0.575 |
||||
8192, 2048, 0, 0, 0.854 |
||||
8192, 2048, 0, 1, 0.834 |
||||
8192, 2061, 0, 0, 0.863 |
||||
8192, 2061, 0, 1, 0.857 |
||||
8192, 2048, 13, 0, 0.63 |
||||
8192, 2048, 13, 1, 0.629 |
||||
8192, 2061, 13, 0, 0.627 |
||||
8192, 2061, 13, 1, 0.62 |
||||
|
||||
Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit 475b63702ef38b69558fc3d31a0b66776a70f1d3) |
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h |
||||
index e6c94dfd023a25dc..2e43e67e4f4037d3 100644 |
||||
--- a/sysdeps/x86/dl-cacheinfo.h |
||||
+++ b/sysdeps/x86/dl-cacheinfo.h |
||||
@@ -866,12 +866,14 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
/* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */ |
||||
unsigned int minimum_rep_movsb_threshold; |
||||
#endif |
||||
- /* NB: The default REP MOVSB threshold is 2048 * (VEC_SIZE / 16). */ |
||||
+ /* NB: The default REP MOVSB threshold is 4096 * (VEC_SIZE / 16) for |
||||
+ VEC_SIZE == 64 or 32. For VEC_SIZE == 16, the default REP MOVSB |
||||
+ threshold is 2048 * (VEC_SIZE / 16). */ |
||||
unsigned int rep_movsb_threshold; |
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) |
||||
&& !CPU_FEATURE_PREFERRED_P (cpu_features, Prefer_No_AVX512)) |
||||
{ |
||||
- rep_movsb_threshold = 2048 * (64 / 16); |
||||
+ rep_movsb_threshold = 4096 * (64 / 16); |
||||
#if HAVE_TUNABLES |
||||
minimum_rep_movsb_threshold = 64 * 8; |
||||
#endif |
||||
@@ -879,7 +881,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
else if (CPU_FEATURE_PREFERRED_P (cpu_features, |
||||
AVX_Fast_Unaligned_Load)) |
||||
{ |
||||
- rep_movsb_threshold = 2048 * (32 / 16); |
||||
+ rep_movsb_threshold = 4096 * (32 / 16); |
||||
#if HAVE_TUNABLES |
||||
minimum_rep_movsb_threshold = 32 * 8; |
||||
#endif |
||||
diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list |
||||
index dd6e1d65c9490d4f..419313804d49cf65 100644 |
||||
--- a/sysdeps/x86/dl-tunables.list |
||||
+++ b/sysdeps/x86/dl-tunables.list |
||||
@@ -32,17 +32,21 @@ glibc { |
||||
} |
||||
x86_rep_movsb_threshold { |
||||
type: SIZE_T |
||||
- # Since there is overhead to set up REP MOVSB operation, REP MOVSB |
||||
- # isn't faster on short data. The memcpy micro benchmark in glibc |
||||
- # shows that 2KB is the approximate value above which REP MOVSB |
||||
- # becomes faster than SSE2 optimization on processors with Enhanced |
||||
- # REP MOVSB. Since larger register size can move more data with a |
||||
- # single load and store, the threshold is higher with larger register |
||||
- # size. Note: Since the REP MOVSB threshold must be greater than 8 |
||||
- # times of vector size and the default value is 2048 * (vector size |
||||
- # / 16), the default value and the minimum value must be updated at |
||||
- # run-time. NB: Don't set the default value since we can't tell if |
||||
- # the tunable value is set by user or not [BZ #27069]. |
||||
+ # Since there is overhead to set up REP MOVSB operation, REP |
||||
+ # MOVSB isn't faster on short data. The memcpy micro benchmark |
||||
+ # in glibc shows that 2KB is the approximate value above which |
||||
+ # REP MOVSB becomes faster than SSE2 optimization on processors |
||||
+ # with Enhanced REP MOVSB. Since larger register size can move |
||||
+ # more data with a single load and store, the threshold is |
||||
+ # higher with larger register size. Micro benchmarks show AVX |
||||
+ # REP MOVSB becomes faster apprximately at 8KB. The AVX512 |
||||
+ # threshold is extrapolated to 16KB. For machines with FSRM the |
||||
+ # threshold is universally set at 2112 bytes. Note: Since the |
||||
+ # REP MOVSB threshold must be greater than 8 times of vector |
||||
+ # size and the default value is 4096 * (vector size / 16), the |
||||
+ # default value and the minimum value must be updated at |
||||
+ # run-time. NB: Don't set the default value since we can't tell |
||||
+ # if the tunable value is set by user or not [BZ #27069]. |
||||
minval: 1 |
||||
} |
||||
x86_rep_stosb_threshold { |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
commit 4bbd0f866ad0ff197f72346f776ebee9b7e1a706 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Fri Dec 3 15:29:25 2021 -0800 |
||||
|
||||
x86-64: Use notl in EVEX strcmp [BZ #28646] |
||||
|
||||
Must use notl %edi here as lower bits are for CHAR comparisons |
||||
potentially out of range thus can be 0 without indicating mismatch. |
||||
This fixes BZ #28646. |
||||
|
||||
Co-Authored-By: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit 4df1fa6ddc8925a75f3da644d5da3bb16eb33f02) |
||||
|
||||
diff --git a/string/test-strcmp.c b/string/test-strcmp.c |
||||
index 7feababf4ddc5603..a0255b9625fbcedd 100644 |
||||
--- a/string/test-strcmp.c |
||||
+++ b/string/test-strcmp.c |
||||
@@ -25,6 +25,7 @@ |
||||
# define TEST_NAME "strcmp" |
||||
#endif |
||||
#include "test-string.h" |
||||
+#include <support/test-driver.h> |
||||
|
||||
#ifdef WIDE |
||||
# include <wchar.h> |
||||
@@ -392,6 +393,32 @@ check2 (void) |
||||
} |
||||
} |
||||
|
||||
+static void |
||||
+check3 (void) |
||||
+{ |
||||
+ size_t size = 0xd000 + 0x4000; |
||||
+ CHAR *s1, *s2; |
||||
+ CHAR *buffer1 = mmap (NULL, size, PROT_READ | PROT_WRITE, |
||||
+ MAP_PRIVATE | MAP_ANON, -1, 0); |
||||
+ CHAR *buffer2 = mmap (NULL, size, PROT_READ | PROT_WRITE, |
||||
+ MAP_PRIVATE | MAP_ANON, -1, 0); |
||||
+ if (buffer1 == MAP_FAILED || buffer1 == MAP_FAILED) |
||||
+ error (EXIT_UNSUPPORTED, errno, "mmap failed"); |
||||
+ |
||||
+ s1 = (CHAR *) (buffer1 + 0x8f8 / sizeof (CHAR)); |
||||
+ s2 = (CHAR *) (buffer2 + 0xcff3 / sizeof (CHAR)); |
||||
+ |
||||
+ STRCPY(s1, L("/export/redhat/rpms/BUILD/java-1.8.0-openjdk-1.8.0.312.b07-2.fc35.x86_64/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java")); |
||||
+ STRCPY(s2, L("/export/redhat/rpms/BUILD/java-1.8.0-openjdk-1.8.0.312.b07-2.fc35.x86_64/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java")); |
||||
+ |
||||
+ int exp_result = SIMPLE_STRCMP (s1, s2); |
||||
+ FOR_EACH_IMPL (impl, 0) |
||||
+ check_result (impl, s1, s2, exp_result); |
||||
+ |
||||
+ munmap ((void *) buffer1, size); |
||||
+ munmap ((void *) buffer2, size); |
||||
+} |
||||
+ |
||||
int |
||||
test_main (void) |
||||
{ |
||||
@@ -400,6 +427,7 @@ test_main (void) |
||||
test_init (); |
||||
check(); |
||||
check2 (); |
||||
+ check3 (); |
||||
|
||||
printf ("%23s", ""); |
||||
FOR_EACH_IMPL (impl, 0) |
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
index 82f12ac89bcae20b..6f5c4bf984da2b80 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-evex.S |
||||
@@ -656,12 +656,13 @@ L(loop_cross_page): |
||||
in YMM3 and 32 bytes at VEC_SIZE(%rdx, %r10). */ |
||||
VPCMP $0, VEC_SIZE(%rdx, %r10), %YMM3, %k3{%k4} |
||||
kmovd %k3, %edi |
||||
+ /* Must use notl %edi here as lower bits are for CHAR |
||||
+ comparisons potentially out of range thus can be 0 without |
||||
+ indicating mismatch. */ |
||||
+ notl %edi |
||||
# ifdef USE_AS_WCSCMP |
||||
/* Don't use subl since it is the upper 8 bits of EDI below. */ |
||||
- notl %edi |
||||
andl $0xff, %edi |
||||
-# else |
||||
- incl %edi |
||||
# endif |
||||
|
||||
# ifdef USE_AS_WCSCMP |
||||
@@ -743,12 +744,13 @@ L(loop_cross_page_2_vec): |
||||
in YMM1 and 32 bytes at (VEC_SIZE * 3)(%rdx, %r10). */ |
||||
VPCMP $0, (VEC_SIZE * 3)(%rdx, %r10), %YMM1, %k3{%k4} |
||||
kmovd %k3, %edi |
||||
+ /* Must use notl %edi here as lower bits are for CHAR |
||||
+ comparisons potentially out of range thus can be 0 without |
||||
+ indicating mismatch. */ |
||||
+ notl %edi |
||||
# ifdef USE_AS_WCSCMP |
||||
/* Don't use subl since it is the upper 8 bits of EDI below. */ |
||||
- notl %edi |
||||
andl $0xff, %edi |
||||
-# else |
||||
- incl %edi |
||||
# endif |
||||
|
||||
# ifdef USE_AS_WCSCMP |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
commit f3a99b2216114f89b20329ae7664b764248b4bbd |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Mon Dec 6 07:14:12 2021 -0800 |
||||
|
||||
x86: Don't set Prefer_No_AVX512 for processors with AVX512 and AVX-VNNI |
||||
|
||||
Don't set Prefer_No_AVX512 on processors with AVX512 and AVX-VNNI since |
||||
they won't lower CPU frequency when ZMM load and store instructions are |
||||
used. |
||||
|
||||
(cherry picked from commit ceeffe968c01b1202e482f4855cb6baf5c6cb713) |
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c |
||||
index f4d4049e391cbabd..09590d8794b1c6fb 100644 |
||||
--- a/sysdeps/x86/cpu-features.c |
||||
+++ b/sysdeps/x86/cpu-features.c |
||||
@@ -566,8 +566,11 @@ disable_tsx: |
||||
|= bit_arch_Prefer_No_VZEROUPPER; |
||||
else |
||||
{ |
||||
- cpu_features->preferred[index_arch_Prefer_No_AVX512] |
||||
- |= bit_arch_Prefer_No_AVX512; |
||||
+ /* Processors with AVX512 and AVX-VNNI won't lower CPU frequency |
||||
+ when ZMM load and store instructions are used. */ |
||||
+ if (!CPU_FEATURES_CPU_P (cpu_features, AVX_VNNI)) |
||||
+ cpu_features->preferred[index_arch_Prefer_No_AVX512] |
||||
+ |= bit_arch_Prefer_No_AVX512; |
||||
|
||||
/* Avoid RTM abort triggered by VZEROUPPER inside a |
||||
transactionally executing RTM region. */ |
@ -0,0 +1,384 @@
@@ -0,0 +1,384 @@
|
||||
commit c796418d00f65c8c5fbed477f3ba6da2bee64ece |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Fri Dec 24 18:54:41 2021 -0600 |
||||
|
||||
x86: Optimize L(less_vec) case in memcmp-evex-movbe.S |
||||
|
||||
No bug. |
||||
Optimizations are twofold. |
||||
|
||||
1) Replace page cross and 0/1 checks with masked load instructions in |
||||
L(less_vec). In applications this reduces branch-misses in the |
||||
hot [0, 32] case. |
||||
2) Change controlflow so that L(less_vec) case gets the fall through. |
||||
|
||||
Change 2) helps copies in the [0, 32] size range but comes at the cost |
||||
of copies in the [33, 64] size range. From profiles of GCC and |
||||
Python3, 94%+ and 99%+ of calls are in the [0, 32] range so this |
||||
appears to the the right tradeoff. |
||||
|
||||
Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
(cherry picked from commit abddd61de090ae84e380aff68a98bd94ef704667) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
index 640f6757fac8a356..d2899e7c7078cd41 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
+++ b/sysdeps/x86_64/multiarch/memcmp-evex-movbe.S |
||||
@@ -62,15 +62,18 @@ Latency: |
||||
# define VMOVU vmovdqu64 |
||||
|
||||
# ifdef USE_AS_WMEMCMP |
||||
+# define VMOVU_MASK vmovdqu32 |
||||
# define CHAR_SIZE 4 |
||||
# define VPCMP vpcmpd |
||||
# define VPTEST vptestmd |
||||
# else |
||||
+# define VMOVU_MASK vmovdqu8 |
||||
# define CHAR_SIZE 1 |
||||
# define VPCMP vpcmpub |
||||
# define VPTEST vptestmb |
||||
# endif |
||||
|
||||
+ |
||||
# define VEC_SIZE 32 |
||||
# define PAGE_SIZE 4096 |
||||
# define CHAR_PER_VEC (VEC_SIZE / CHAR_SIZE) |
||||
@@ -102,12 +105,48 @@ ENTRY_P2ALIGN (MEMCMP, 6) |
||||
movl %edx, %edx |
||||
# endif |
||||
cmp $CHAR_PER_VEC, %RDX_LP |
||||
- jb L(less_vec) |
||||
+ /* Fall through for [0, VEC_SIZE] as its the hottest. */ |
||||
+ ja L(more_1x_vec) |
||||
+ |
||||
+ /* Create mask for CHAR's we want to compare. This allows us to |
||||
+ avoid having to include page cross logic. */ |
||||
+ movl $-1, %ecx |
||||
+ bzhil %edx, %ecx, %ecx |
||||
+ kmovd %ecx, %k2 |
||||
+ |
||||
+ /* Safe to load full ymm with mask. */ |
||||
+ VMOVU_MASK (%rsi), %YMM2{%k2} |
||||
+ VPCMP $4,(%rdi), %YMM2, %k1{%k2} |
||||
+ kmovd %k1, %eax |
||||
+ testl %eax, %eax |
||||
+ jnz L(return_vec_0) |
||||
+ ret |
||||
|
||||
+ .p2align 4 |
||||
+L(return_vec_0): |
||||
+ tzcntl %eax, %eax |
||||
+# ifdef USE_AS_WMEMCMP |
||||
+ movl (%rdi, %rax, CHAR_SIZE), %ecx |
||||
+ xorl %edx, %edx |
||||
+ cmpl (%rsi, %rax, CHAR_SIZE), %ecx |
||||
+ /* NB: no partial register stall here because xorl zero idiom |
||||
+ above. */ |
||||
+ setg %dl |
||||
+ leal -1(%rdx, %rdx), %eax |
||||
+# else |
||||
+ movzbl (%rsi, %rax), %ecx |
||||
+ movzbl (%rdi, %rax), %eax |
||||
+ subl %ecx, %eax |
||||
+# endif |
||||
+ ret |
||||
+ |
||||
+ |
||||
+ .p2align 4 |
||||
+L(more_1x_vec): |
||||
/* From VEC to 2 * VEC. No branch when size == VEC_SIZE. */ |
||||
VMOVU (%rsi), %YMM1 |
||||
/* Use compare not equals to directly check for mismatch. */ |
||||
- VPCMP $4, (%rdi), %YMM1, %k1 |
||||
+ VPCMP $4,(%rdi), %YMM1, %k1 |
||||
kmovd %k1, %eax |
||||
/* NB: eax must be destination register if going to |
||||
L(return_vec_[0,2]). For L(return_vec_3) destination register |
||||
@@ -131,13 +170,13 @@ ENTRY_P2ALIGN (MEMCMP, 6) |
||||
|
||||
/* Check third and fourth VEC no matter what. */ |
||||
VMOVU (VEC_SIZE * 2)(%rsi), %YMM3 |
||||
- VPCMP $4, (VEC_SIZE * 2)(%rdi), %YMM3, %k1 |
||||
+ VPCMP $4,(VEC_SIZE * 2)(%rdi), %YMM3, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
jnz L(return_vec_2) |
||||
|
||||
VMOVU (VEC_SIZE * 3)(%rsi), %YMM4 |
||||
- VPCMP $4, (VEC_SIZE * 3)(%rdi), %YMM4, %k1 |
||||
+ VPCMP $4,(VEC_SIZE * 3)(%rdi), %YMM4, %k1 |
||||
kmovd %k1, %ecx |
||||
testl %ecx, %ecx |
||||
jnz L(return_vec_3) |
||||
@@ -169,7 +208,7 @@ ENTRY_P2ALIGN (MEMCMP, 6) |
||||
VMOVU (VEC_SIZE * 3)(%rsi), %YMM4 |
||||
/* Ternary logic to xor (VEC_SIZE * 3)(%rdi) with YMM4 while |
||||
oring with YMM1. Result is stored in YMM4. */ |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
+ vpternlogd $0xde,(VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
|
||||
/* Or together YMM2, YMM3, and YMM4 into YMM4. */ |
||||
vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
@@ -184,7 +223,8 @@ ENTRY_P2ALIGN (MEMCMP, 6) |
||||
/* NB: eax must be zero to reach here. */ |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
+ |
||||
+ .p2align 4,, 8 |
||||
L(8x_end_return_vec_0_1_2_3): |
||||
movq %rdx, %rdi |
||||
L(8x_return_vec_0_1_2_3): |
||||
@@ -222,23 +262,6 @@ L(return_vec_3): |
||||
# endif |
||||
ret |
||||
|
||||
- .p2align 4 |
||||
-L(return_vec_0): |
||||
- tzcntl %eax, %eax |
||||
-# ifdef USE_AS_WMEMCMP |
||||
- movl (%rdi, %rax, CHAR_SIZE), %ecx |
||||
- xorl %edx, %edx |
||||
- cmpl (%rsi, %rax, CHAR_SIZE), %ecx |
||||
- /* NB: no partial register stall here because xorl zero idiom |
||||
- above. */ |
||||
- setg %dl |
||||
- leal -1(%rdx, %rdx), %eax |
||||
-# else |
||||
- movzbl (%rsi, %rax), %ecx |
||||
- movzbl (%rdi, %rax), %eax |
||||
- subl %ecx, %eax |
||||
-# endif |
||||
- ret |
||||
|
||||
.p2align 4 |
||||
L(return_vec_1): |
||||
@@ -297,7 +320,7 @@ L(loop_4x_vec): |
||||
VMOVU (VEC_SIZE * 2)(%rsi, %rdi), %YMM3 |
||||
vpxorq (VEC_SIZE * 2)(%rdi), %YMM3, %YMM3 |
||||
VMOVU (VEC_SIZE * 3)(%rsi, %rdi), %YMM4 |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
+ vpternlogd $0xde,(VEC_SIZE * 3)(%rdi), %YMM1, %YMM4 |
||||
vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
VPTEST %YMM4, %YMM4, %k1 |
||||
kmovd %k1, %ecx |
||||
@@ -324,7 +347,7 @@ L(loop_4x_vec): |
||||
VMOVU VEC_SIZE(%rsi, %rdx), %YMM2 |
||||
vpxorq VEC_SIZE(%rdx), %YMM2, %YMM2 |
||||
VMOVU (VEC_SIZE * 3)(%rsi, %rdx), %YMM4 |
||||
- vpternlogd $0xde, (VEC_SIZE * 3)(%rdx), %YMM1, %YMM4 |
||||
+ vpternlogd $0xde,(VEC_SIZE * 3)(%rdx), %YMM1, %YMM4 |
||||
vpternlogd $0xfe, %YMM2, %YMM3, %YMM4 |
||||
VPTEST %YMM4, %YMM4, %k1 |
||||
kmovd %k1, %ecx |
||||
@@ -336,14 +359,14 @@ L(loop_4x_vec): |
||||
/* Only entry is from L(more_8x_vec). */ |
||||
.p2align 4,, 10 |
||||
L(8x_last_2x_vec): |
||||
- VPCMP $4, (VEC_SIZE * 2)(%rdx), %YMM3, %k1 |
||||
+ VPCMP $4,(VEC_SIZE * 2)(%rdx), %YMM3, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
jnz L(8x_return_vec_2) |
||||
/* Naturally aligned to 16 bytes. */ |
||||
L(8x_last_1x_vec): |
||||
VMOVU (VEC_SIZE * 3)(%rsi, %rdx), %YMM1 |
||||
- VPCMP $4, (VEC_SIZE * 3)(%rdx), %YMM1, %k1 |
||||
+ VPCMP $4,(VEC_SIZE * 3)(%rdx), %YMM1, %k1 |
||||
kmovd %k1, %eax |
||||
testl %eax, %eax |
||||
jnz L(8x_return_vec_3) |
||||
@@ -392,7 +415,9 @@ L(last_1x_vec): |
||||
jnz L(return_vec_0_end) |
||||
ret |
||||
|
||||
- .p2align 4,, 10 |
||||
+ |
||||
+ /* Don't align. Takes 2-fetch blocks either way and aligning |
||||
+ will cause code to spill into another cacheline. */ |
||||
L(return_vec_1_end): |
||||
/* Use bsf to save code size. This is necessary to have |
||||
L(one_or_less) fit in aligning bytes between. */ |
||||
@@ -411,31 +436,8 @@ L(return_vec_1_end): |
||||
# endif |
||||
ret |
||||
|
||||
- /* NB: L(one_or_less) fits in alignment padding between |
||||
- L(return_vec_1_end) and L(return_vec_0_end). */ |
||||
-# ifdef USE_AS_WMEMCMP |
||||
-L(one_or_less): |
||||
- jb L(zero) |
||||
- movl (%rdi), %ecx |
||||
- xorl %edx, %edx |
||||
- cmpl (%rsi), %ecx |
||||
- je L(zero) |
||||
- setg %dl |
||||
- leal -1(%rdx, %rdx), %eax |
||||
- ret |
||||
-# else |
||||
-L(one_or_less): |
||||
- jb L(zero) |
||||
- movzbl (%rsi), %ecx |
||||
- movzbl (%rdi), %eax |
||||
- subl %ecx, %eax |
||||
- ret |
||||
-# endif |
||||
-L(zero): |
||||
- xorl %eax, %eax |
||||
- ret |
||||
- |
||||
- .p2align 4 |
||||
+ /* Don't align. Takes 2-fetch blocks either way and aligning |
||||
+ will cause code to spill into another cacheline. */ |
||||
L(return_vec_0_end): |
||||
tzcntl %eax, %eax |
||||
addl %edx, %eax |
||||
@@ -451,146 +453,7 @@ L(return_vec_0_end): |
||||
subl %ecx, %eax |
||||
# endif |
||||
ret |
||||
+ /* 1-byte until next cache line. */ |
||||
|
||||
- .p2align 4 |
||||
-L(less_vec): |
||||
- /* Check if one or less CHAR. This is necessary for size == 0 |
||||
- but is also faster for size == CHAR_SIZE. */ |
||||
- cmpl $1, %edx |
||||
- jbe L(one_or_less) |
||||
- |
||||
- /* Check if loading one VEC from either s1 or s2 could cause a |
||||
- page cross. This can have false positives but is by far the |
||||
- fastest method. */ |
||||
- movl %edi, %eax |
||||
- orl %esi, %eax |
||||
- andl $(PAGE_SIZE - 1), %eax |
||||
- cmpl $(PAGE_SIZE - VEC_SIZE), %eax |
||||
- jg L(page_cross_less_vec) |
||||
- |
||||
- /* No page cross possible. */ |
||||
- VMOVU (%rsi), %YMM2 |
||||
- VPCMP $4, (%rdi), %YMM2, %k1 |
||||
- kmovd %k1, %eax |
||||
- /* Check if any matches where in bounds. Intentionally not |
||||
- storing result in eax to limit dependency chain if it goes to |
||||
- L(return_vec_0_lv). */ |
||||
- bzhil %edx, %eax, %edx |
||||
- jnz L(return_vec_0_lv) |
||||
- xorl %eax, %eax |
||||
- ret |
||||
- |
||||
- /* Essentially duplicate of L(return_vec_0). Ends up not costing |
||||
- any code as shrinks L(less_vec) by allowing 2-byte encoding of |
||||
- the jump and ends up fitting in aligning bytes. As well fits on |
||||
- same cache line as L(less_vec) so also saves a line from having |
||||
- to be fetched on cold calls to memcmp. */ |
||||
- .p2align 4,, 4 |
||||
-L(return_vec_0_lv): |
||||
- tzcntl %eax, %eax |
||||
-# ifdef USE_AS_WMEMCMP |
||||
- movl (%rdi, %rax, CHAR_SIZE), %ecx |
||||
- xorl %edx, %edx |
||||
- cmpl (%rsi, %rax, CHAR_SIZE), %ecx |
||||
- /* NB: no partial register stall here because xorl zero idiom |
||||
- above. */ |
||||
- setg %dl |
||||
- leal -1(%rdx, %rdx), %eax |
||||
-# else |
||||
- movzbl (%rsi, %rax), %ecx |
||||
- movzbl (%rdi, %rax), %eax |
||||
- subl %ecx, %eax |
||||
-# endif |
||||
- ret |
||||
- |
||||
- .p2align 4 |
||||
-L(page_cross_less_vec): |
||||
- /* if USE_AS_WMEMCMP it can only be 0, 4, 8, 12, 16, 20, 24, 28 |
||||
- bytes. */ |
||||
- cmpl $(16 / CHAR_SIZE), %edx |
||||
- jae L(between_16_31) |
||||
-# ifndef USE_AS_WMEMCMP |
||||
- cmpl $8, %edx |
||||
- jae L(between_8_15) |
||||
- cmpl $4, %edx |
||||
- jb L(between_2_3) |
||||
- |
||||
- /* Load as big endian with overlapping movbe to avoid branches. |
||||
- */ |
||||
- movbe (%rdi), %eax |
||||
- movbe (%rsi), %ecx |
||||
- shlq $32, %rax |
||||
- shlq $32, %rcx |
||||
- movbe -4(%rdi, %rdx), %edi |
||||
- movbe -4(%rsi, %rdx), %esi |
||||
- orq %rdi, %rax |
||||
- orq %rsi, %rcx |
||||
- subq %rcx, %rax |
||||
- /* edx is guranteed to be positive int32 in range [4, 7]. */ |
||||
- cmovne %edx, %eax |
||||
- /* ecx is -1 if rcx > rax. Otherwise 0. */ |
||||
- sbbl %ecx, %ecx |
||||
- /* If rcx > rax, then ecx is 0 and eax is positive. If rcx == |
||||
- rax then eax and ecx are zero. If rax < rax then ecx is -1 so |
||||
- eax doesn't matter. */ |
||||
- orl %ecx, %eax |
||||
- ret |
||||
- |
||||
- .p2align 4,, 8 |
||||
-L(between_8_15): |
||||
-# endif |
||||
- /* If USE_AS_WMEMCMP fall through into 8-15 byte case. */ |
||||
- vmovq (%rdi), %xmm1 |
||||
- vmovq (%rsi), %xmm2 |
||||
- VPCMP $4, %xmm1, %xmm2, %k1 |
||||
- kmovd %k1, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_0_lv) |
||||
- /* Use overlapping loads to avoid branches. */ |
||||
- vmovq -8(%rdi, %rdx, CHAR_SIZE), %xmm1 |
||||
- vmovq -8(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
- VPCMP $4, %xmm1, %xmm2, %k1 |
||||
- addl $(CHAR_PER_VEC - (8 / CHAR_SIZE)), %edx |
||||
- kmovd %k1, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_0_end) |
||||
- ret |
||||
- |
||||
- .p2align 4,, 8 |
||||
-L(between_16_31): |
||||
- /* From 16 to 31 bytes. No branch when size == 16. */ |
||||
- |
||||
- /* Use movups to save code size. */ |
||||
- vmovdqu (%rsi), %xmm2 |
||||
- VPCMP $4, (%rdi), %xmm2, %k1 |
||||
- kmovd %k1, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_0_lv) |
||||
- /* Use overlapping loads to avoid branches. */ |
||||
- vmovdqu -16(%rsi, %rdx, CHAR_SIZE), %xmm2 |
||||
- VPCMP $4, -16(%rdi, %rdx, CHAR_SIZE), %xmm2, %k1 |
||||
- addl $(CHAR_PER_VEC - (16 / CHAR_SIZE)), %edx |
||||
- kmovd %k1, %eax |
||||
- testl %eax, %eax |
||||
- jnz L(return_vec_0_end) |
||||
- ret |
||||
- |
||||
-# ifndef USE_AS_WMEMCMP |
||||
-L(between_2_3): |
||||
- /* Load as big endian to avoid branches. */ |
||||
- movzwl (%rdi), %eax |
||||
- movzwl (%rsi), %ecx |
||||
- shll $8, %eax |
||||
- shll $8, %ecx |
||||
- bswap %eax |
||||
- bswap %ecx |
||||
- movzbl -1(%rdi, %rdx), %edi |
||||
- movzbl -1(%rsi, %rdx), %esi |
||||
- orl %edi, %eax |
||||
- orl %esi, %ecx |
||||
- /* Subtraction is okay because the upper 8 bits are zero. */ |
||||
- subl %ecx, %eax |
||||
- ret |
||||
-# endif |
||||
END (MEMCMP) |
||||
#endif |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
commit 9681691402052b727e01ae3375c73e0f76566593 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Apr 27 13:59:26 2022 -0300 |
||||
|
||||
linux: Fix missing internal 64 bit time_t stat usage |
||||
|
||||
These are two missing spots initially done by 52a5fe70a2c77935. |
||||
|
||||
Checked on i686-linux-gnu. |
||||
|
||||
(cherry picked from commit 834ddd0432f68d6dc85b6aac95065721af0d86e9) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/faccessat.c b/sysdeps/unix/sysv/linux/faccessat.c |
||||
index 13160d32499c4e58..00e4ce7f80ee2dfe 100644 |
||||
--- a/sysdeps/unix/sysv/linux/faccessat.c |
||||
+++ b/sysdeps/unix/sysv/linux/faccessat.c |
||||
@@ -39,8 +39,8 @@ __faccessat (int fd, const char *file, int mode, int flag) |
||||
if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure))) |
||||
return INLINE_SYSCALL (faccessat, 3, fd, file, mode); |
||||
|
||||
- struct stat64 stats; |
||||
- if (__fstatat64 (fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW)) |
||||
+ struct __stat64_t64 stats; |
||||
+ if (__fstatat64_time64 (fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW)) |
||||
return -1; |
||||
|
||||
mode &= (X_OK | W_OK | R_OK); /* Clear any bogus bits. */ |
||||
diff --git a/sysdeps/unix/sysv/linux/pathconf.c b/sysdeps/unix/sysv/linux/pathconf.c |
||||
index b599a66c930cad4d..f79930303118ebcd 100644 |
||||
--- a/sysdeps/unix/sysv/linux/pathconf.c |
||||
+++ b/sysdeps/unix/sysv/linux/pathconf.c |
||||
@@ -110,8 +110,8 @@ distinguish_extX (const struct statfs *fsbuf, const char *file, int fd) |
||||
&& strcmp (mntbuf.mnt_type, "ext4") != 0) |
||||
continue; |
||||
|
||||
- struct stat64 fsst; |
||||
- if (__stat64 (mntbuf.mnt_dir, &fsst) >= 0 |
||||
+ struct __stat64_t64 fsst; |
||||
+ if (__stat64_time64 (mntbuf.mnt_dir, &fsst) >= 0 |
||||
&& st.st_dev == fsst.st_dev) |
||||
{ |
||||
if (strcmp (mntbuf.mnt_type, "ext4") == 0) |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
commit 55640ed3fde48360a8e8083be4843bd2dc7cecfe |
||||
Author: Carlos O'Donell <carlos@redhat.com> |
||||
Date: Tue Apr 26 10:52:41 2022 -0400 |
||||
|
||||
i386: Regenerate ulps |
||||
|
||||
These failures were caught while building glibc master for Fedora |
||||
Rawhide which is built with '-mtune=generic -msse2 -mfpmath=sse' |
||||
using gcc 11.3 (gcc-11.3.1-2.fc35) on a Cascadelake Intel Xeon |
||||
processor. |
||||
|
||||
(cherry picked from commit e465d97653311c3687aee49de782177353acfe86) |
||||
|
||||
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps |
||||
index 7601049110789201..84e6686eba5fe79a 100644 |
||||
--- a/sysdeps/i386/fpu/libm-test-ulps |
||||
+++ b/sysdeps/i386/fpu/libm-test-ulps |
||||
@@ -668,7 +668,7 @@ ldouble: 4 |
||||
|
||||
Function: Imaginary part of "clog10": |
||||
double: 2 |
||||
-float: 1 |
||||
+float: 2 |
||||
float128: 2 |
||||
ldouble: 2 |
||||
|
||||
diff --git a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps |
||||
index a39c89cec1141935..cc21e6907fe8b6a3 100644 |
||||
--- a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps |
||||
+++ b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps |
||||
@@ -668,7 +668,7 @@ ldouble: 4 |
||||
|
||||
Function: Imaginary part of "clog10": |
||||
double: 2 |
||||
-float: 1 |
||||
+float: 2 |
||||
float128: 2 |
||||
ldouble: 2 |
||||
|
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
commit 88a8637cb4658cd91a002659db05867716b88b36 |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Wed Apr 27 13:40:30 2022 -0300 |
||||
|
||||
linux: Fix fchmodat with AT_SYMLINK_NOFOLLOW for 64 bit time_t (BZ#29097) |
||||
|
||||
The AT_SYMLINK_NOFOLLOW emulation ues the default 32 bit stat internal |
||||
calls, which fails with EOVERFLOW if the file constains timestamps |
||||
beyond 2038. |
||||
|
||||
Checked on i686-linux-gnu. |
||||
|
||||
(cherry picked from commit 118a2aee07f64d605b6668cbe195c1f44eac6be6) |
||||
|
||||
diff --git a/io/Makefile b/io/Makefile |
||||
index 9871ecbc74020a6d..01968b81042e01e4 100644 |
||||
--- a/io/Makefile |
||||
+++ b/io/Makefile |
||||
@@ -81,16 +81,17 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ |
||||
tst-closefrom \ |
||||
|
||||
tests-time64 := \ |
||||
+ tst-fcntl-time64 \ |
||||
+ tst-fts-time64 \ |
||||
tst-futimens-time64 \ |
||||
tst-futimes-time64\ |
||||
- tst-fts-time64 \ |
||||
+ tst-futimesat-time64 \ |
||||
+ tst-lchmod-time64 \ |
||||
tst-lutimes-time64 \ |
||||
tst-stat-time64 \ |
||||
- tst-futimesat-time64 \ |
||||
tst-utime-time64 \ |
||||
tst-utimensat-time64 \ |
||||
tst-utimes-time64 \ |
||||
- tst-fcntl-time64 \ |
||||
# tests-time64 |
||||
|
||||
# Likewise for statx, but we do not need static linking here. |
||||
@@ -134,6 +135,7 @@ CFLAGS-close.c += -fexceptions -fasynchronous-unwind-tables |
||||
|
||||
CFLAGS-test-stat.c += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE |
||||
CFLAGS-test-lfs.c += -D_LARGEFILE64_SOURCE |
||||
+CFLAGS-tst-lchmod.c += -D_FILE_OFFSET_BITS=64 |
||||
|
||||
test-stat2-ARGS = Makefile . $(objpfx)test-stat2 |
||||
|
||||
diff --git a/io/tst-lchmod-time64.c b/io/tst-lchmod-time64.c |
||||
new file mode 100644 |
||||
index 0000000000000000..f2b7cc9d358f2a77 |
||||
--- /dev/null |
||||
+++ b/io/tst-lchmod-time64.c |
||||
@@ -0,0 +1,2 @@ |
||||
+#define CHECK_TIME64 |
||||
+#include "tst-lchmod.c" |
||||
diff --git a/io/tst-lchmod.c b/io/tst-lchmod.c |
||||
index 0fe98e01b74b713d..472766b186975922 100644 |
||||
--- a/io/tst-lchmod.c |
||||
+++ b/io/tst-lchmod.c |
||||
@@ -66,10 +66,27 @@ select_path (bool do_relative_path, const char *full_path, const char *relative_ |
||||
return full_path; |
||||
} |
||||
|
||||
+static void |
||||
+update_file_time_to_y2038 (const char *fname, int flags) |
||||
+{ |
||||
+#ifdef CHECK_TIME64 |
||||
+ /* Y2038 threshold plus 1 second. */ |
||||
+ const struct timespec ts[] = { { 0x80000001LL, 0}, { 0x80000001LL } }; |
||||
+ TEST_VERIFY_EXIT (utimensat (AT_FDCWD, fname, ts, flags) == 0); |
||||
+#endif |
||||
+} |
||||
+ |
||||
static void |
||||
test_1 (bool do_relative_path, int (*chmod_func) (int fd, const char *, mode_t, int)) |
||||
{ |
||||
char *tempdir = support_create_temp_directory ("tst-lchmod-"); |
||||
+#ifdef CHECK_TIME64 |
||||
+ if (!support_path_support_time64 (tempdir)) |
||||
+ { |
||||
+ puts ("info: test skipped, filesystem does not support 64 bit time_t"); |
||||
+ return; |
||||
+ } |
||||
+#endif |
||||
|
||||
char *path_dangling = xasprintf ("%s/dangling", tempdir); |
||||
char *path_file = xasprintf ("%s/file", tempdir); |
||||
@@ -93,9 +110,12 @@ test_1 (bool do_relative_path, int (*chmod_func) (int fd, const char *, mode_t, |
||||
xsymlink ("loop", path_loop); |
||||
xsymlink ("target-does-not-exist", path_dangling); |
||||
|
||||
+ update_file_time_to_y2038 (path_file, 0); |
||||
+ update_file_time_to_y2038 (path_to_file, AT_SYMLINK_NOFOLLOW); |
||||
+ |
||||
/* Check that the modes do not collide with what we will use in the |
||||
test. */ |
||||
- struct stat64 st; |
||||
+ struct stat st; |
||||
xstat (path_file, &st); |
||||
TEST_VERIFY ((st.st_mode & 0777) != 1); |
||||
xlstat (path_to_file, &st); |
||||
diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c |
||||
index 5bd1eb96a5d78130..b0cf61949a9302d9 100644 |
||||
--- a/sysdeps/unix/sysv/linux/fchmodat.c |
||||
+++ b/sysdeps/unix/sysv/linux/fchmodat.c |
||||
@@ -48,8 +48,8 @@ fchmodat (int fd, const char *file, mode_t mode, int flag) |
||||
|
||||
/* Use fstatat because fstat does not work on O_PATH descriptors |
||||
before Linux 3.6. */ |
||||
- struct stat64 st; |
||||
- if (__fstatat64 (pathfd, "", &st, AT_EMPTY_PATH) != 0) |
||||
+ struct __stat64_t64 st; |
||||
+ if (__fstatat64_time64 (pathfd, "", &st, AT_EMPTY_PATH) != 0) |
||||
{ |
||||
__close_nocancel (pathfd); |
||||
return -1; |
@ -0,0 +1,189 @@
@@ -0,0 +1,189 @@
|
||||
commit c66c92181ddbd82306537a608e8c0282587131de |
||||
Author: DJ Delorie <dj@redhat.com> |
||||
Date: Wed Mar 30 17:44:02 2022 -0400 |
||||
|
||||
posix/glob.c: update from gnulib |
||||
|
||||
Copied from gnulib/lib/glob.c in order to fix rhbz 1982608 |
||||
Also fixes swbz 25659 |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
Tested-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 7c477b57a31487eda516db02b9e04f22d1a6e6af) |
||||
|
||||
diff --git a/posix/glob.c b/posix/glob.c |
||||
index 593a4c358f3d42e5..6af310a1aa31401a 100644 |
||||
--- a/posix/glob.c |
||||
+++ b/posix/glob.c |
||||
@@ -21,13 +21,14 @@ |
||||
optimizes away the pattern == NULL test below. */ |
||||
# define _GL_ARG_NONNULL(params) |
||||
|
||||
-# include <config.h> |
||||
+# include <libc-config.h> |
||||
|
||||
#endif |
||||
|
||||
#include <glob.h> |
||||
|
||||
#include <errno.h> |
||||
+#include <fcntl.h> |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <stdbool.h> |
||||
@@ -56,6 +57,8 @@ |
||||
# define sysconf(id) __sysconf (id) |
||||
# define closedir(dir) __closedir (dir) |
||||
# define opendir(name) __opendir (name) |
||||
+# undef dirfd |
||||
+# define dirfd(str) __dirfd (str) |
||||
# define readdir(str) __readdir64 (str) |
||||
# define getpwnam_r(name, bufp, buf, len, res) \ |
||||
__getpwnam_r (name, bufp, buf, len, res) |
||||
@@ -69,11 +72,8 @@ |
||||
# ifndef GLOB_LSTAT |
||||
# define GLOB_LSTAT gl_lstat |
||||
# endif |
||||
-# ifndef GLOB_STAT64 |
||||
-# define GLOB_STAT64 __stat64 |
||||
-# endif |
||||
-# ifndef GLOB_LSTAT64 |
||||
-# define GLOB_LSTAT64 __lstat64 |
||||
+# ifndef GLOB_FSTATAT64 |
||||
+# define GLOB_FSTATAT64 __fstatat64 |
||||
# endif |
||||
# include <shlib-compat.h> |
||||
#else /* !_LIBC */ |
||||
@@ -88,8 +88,7 @@ |
||||
# define struct_stat struct stat |
||||
# define struct_stat64 struct stat |
||||
# define GLOB_LSTAT gl_lstat |
||||
-# define GLOB_STAT64 stat |
||||
-# define GLOB_LSTAT64 lstat |
||||
+# define GLOB_FSTATAT64 fstatat |
||||
#endif /* _LIBC */ |
||||
|
||||
#include <fnmatch.h> |
||||
@@ -215,7 +214,8 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname) |
||||
} ust; |
||||
return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC) |
||||
? pglob->GLOB_LSTAT (fullname, &ust.st) |
||||
- : GLOB_LSTAT64 (fullname, &ust.st64)); |
||||
+ : GLOB_FSTATAT64 (AT_FDCWD, fullname, &ust.st64, |
||||
+ AT_SYMLINK_NOFOLLOW)); |
||||
} |
||||
|
||||
/* Set *R = A + B. Return true if the answer is mathematically |
||||
@@ -257,7 +257,8 @@ is_dir (char const *filename, int flags, glob_t const *pglob) |
||||
struct_stat64 st64; |
||||
return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC) |
||||
? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode) |
||||
- : GLOB_STAT64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode)); |
||||
+ : (GLOB_FSTATAT64 (AT_FDCWD, filename, &st64, 0) == 0 |
||||
+ && S_ISDIR (st64.st_mode))); |
||||
} |
||||
|
||||
/* Find the end of the sub-pattern in a brace expression. */ |
||||
@@ -747,6 +748,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), |
||||
else |
||||
{ |
||||
#ifndef WINDOWS32 |
||||
+ /* Recognize ~user as a shorthand for the specified user's home |
||||
+ directory. */ |
||||
char *end_name = strchr (dirname, '/'); |
||||
char *user_name; |
||||
int malloc_user_name = 0; |
||||
@@ -885,7 +888,22 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), |
||||
} |
||||
scratch_buffer_free (&pwtmpbuf); |
||||
} |
||||
-#endif /* !WINDOWS32 */ |
||||
+#else /* WINDOWS32 */ |
||||
+ /* On native Windows, access to a user's home directory |
||||
+ (via GetUserProfileDirectory) or to a user's environment |
||||
+ variables (via ExpandEnvironmentStringsForUser) requires |
||||
+ the credentials of the user. Therefore we cannot support |
||||
+ the ~user syntax on this platform. |
||||
+ Handling ~user specially (and treat it like plain ~) if |
||||
+ user is getenv ("USERNAME") would not be a good idea, |
||||
+ since it would make people think that ~user is supported |
||||
+ in general. */ |
||||
+ if (flags & GLOB_TILDE_CHECK) |
||||
+ { |
||||
+ retval = GLOB_NOMATCH; |
||||
+ goto out; |
||||
+ } |
||||
+#endif /* WINDOWS32 */ |
||||
} |
||||
} |
||||
|
||||
@@ -1266,6 +1284,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags, |
||||
{ |
||||
size_t dirlen = strlen (directory); |
||||
void *stream = NULL; |
||||
+ struct scratch_buffer s; |
||||
+ scratch_buffer_init (&s); |
||||
# define GLOBNAMES_MEMBERS(nnames) \ |
||||
struct globnames *next; size_t count; char *name[nnames]; |
||||
struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) }; |
||||
@@ -1337,6 +1357,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, |
||||
} |
||||
else |
||||
{ |
||||
+ int dfd = dirfd (stream); |
||||
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
||||
| ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); |
||||
flags |= GLOB_MAGCHAR; |
||||
@@ -1364,8 +1385,32 @@ glob_in_dir (const char *pattern, const char *directory, int flags, |
||||
if (flags & GLOB_ONLYDIR) |
||||
switch (readdir_result_type (d)) |
||||
{ |
||||
- case DT_DIR: case DT_LNK: case DT_UNKNOWN: break; |
||||
default: continue; |
||||
+ case DT_DIR: break; |
||||
+ case DT_LNK: case DT_UNKNOWN: |
||||
+ /* The filesystem was too lazy to give us a hint, |
||||
+ so we have to do it the hard way. */ |
||||
+ if (__glibc_unlikely (dfd < 0 || flags & GLOB_ALTDIRFUNC)) |
||||
+ { |
||||
+ size_t namelen = strlen (d.name); |
||||
+ size_t need = dirlen + 1 + namelen + 1; |
||||
+ if (s.length < need |
||||
+ && !scratch_buffer_set_array_size (&s, need, 1)) |
||||
+ goto memory_error; |
||||
+ char *p = mempcpy (s.data, directory, dirlen); |
||||
+ *p = '/'; |
||||
+ p += p[-1] != '/'; |
||||
+ memcpy (p, d.name, namelen + 1); |
||||
+ if (! is_dir (s.data, flags, pglob)) |
||||
+ continue; |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ struct_stat64 st64; |
||||
+ if (! (GLOB_FSTATAT64 (dfd, d.name, &st64, 0) == 0 |
||||
+ && S_ISDIR (st64.st_mode))) |
||||
+ continue; |
||||
+ } |
||||
} |
||||
|
||||
if (fnmatch (pattern, d.name, fnm_flags) == 0) |
||||
@@ -1497,5 +1542,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags, |
||||
__set_errno (save); |
||||
} |
||||
|
||||
+ scratch_buffer_free (&s); |
||||
return result; |
||||
} |
||||
diff --git a/sysdeps/unix/sysv/linux/glob64-time64.c b/sysdeps/unix/sysv/linux/glob64-time64.c |
||||
index a465f70905e5a8a3..95efe4c4f4624967 100644 |
||||
--- a/sysdeps/unix/sysv/linux/glob64-time64.c |
||||
+++ b/sysdeps/unix/sysv/linux/glob64-time64.c |
||||
@@ -37,6 +37,7 @@ |
||||
# define GLOB_LSTAT gl_lstat |
||||
# define GLOB_STAT64 __stat64_time64 |
||||
# define GLOB_LSTAT64 __lstat64_time64 |
||||
+# define GLOB_FSTATAT64 __fstatat64_time64 |
||||
|
||||
# define COMPILE_GLOB64 1 |
||||
|
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
commit bc6fba3c8048b11c9f73db03339c97a2fec3f0cf |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Wed Nov 17 14:25:16 2021 +0000 |
||||
|
||||
Add PF_MCTP, AF_MCTP from Linux 5.15 to bits/socket.h |
||||
|
||||
Linux 5.15 adds a new address / protocol family PF_MCTP / AF_MCTP; add |
||||
these constants to bits/socket.h. |
||||
|
||||
Tested for x86_64. |
||||
|
||||
(cherry picked from commit bdeb7a8fa9989d18dab6310753d04d908125dc1d) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h |
||||
index a011a8c0959b9970..7bb9e863d7329da9 100644 |
||||
--- a/sysdeps/unix/sysv/linux/bits/socket.h |
||||
+++ b/sysdeps/unix/sysv/linux/bits/socket.h |
||||
@@ -86,7 +86,8 @@ typedef __socklen_t socklen_t; |
||||
#define PF_QIPCRTR 42 /* Qualcomm IPC Router. */ |
||||
#define PF_SMC 43 /* SMC sockets. */ |
||||
#define PF_XDP 44 /* XDP sockets. */ |
||||
-#define PF_MAX 45 /* For now.. */ |
||||
+#define PF_MCTP 45 /* Management component transport protocol. */ |
||||
+#define PF_MAX 46 /* For now.. */ |
||||
|
||||
/* Address families. */ |
||||
#define AF_UNSPEC PF_UNSPEC |
||||
@@ -137,6 +138,7 @@ typedef __socklen_t socklen_t; |
||||
#define AF_QIPCRTR PF_QIPCRTR |
||||
#define AF_SMC PF_SMC |
||||
#define AF_XDP PF_XDP |
||||
+#define AF_MCTP PF_MCTP |
||||
#define AF_MAX PF_MAX |
||||
|
||||
/* Socket level values. Others are defined in the appropriate headers. |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit fd5dbfd1cd98cb2f12f9e9f7004a4d25ab0c977f |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Mon Nov 22 15:30:12 2021 +0000 |
||||
|
||||
Update kernel version to 5.15 in tst-mman-consts.py |
||||
|
||||
This patch updates the kernel version in the test tst-mman-consts.py |
||||
to 5.15. (There are no new MAP_* constants covered by this test in |
||||
5.15 that need any other header changes.) |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
(cherry picked from commit 5c3ece451d46a7d8721311609bfcb6faafacb39e) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-mman-consts.py b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
index 810433c238f31c25..eeccdfd04dae57ab 100644 |
||||
--- a/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
+++ b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
@@ -33,7 +33,7 @@ def main(): |
||||
help='C compiler (including options) to use') |
||||
args = parser.parse_args() |
||||
linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) |
||||
- linux_version_glibc = (5, 14) |
||||
+ linux_version_glibc = (5, 15) |
||||
sys.exit(glibcextract.compare_macro_consts( |
||||
'#define _GNU_SOURCE 1\n' |
||||
'#include <sys/mman.h>\n', |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
commit 5146b73d72ced9bab125e986aa99ef5fe2f88475 |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Mon Dec 20 15:38:32 2021 +0000 |
||||
|
||||
Add ARPHRD_CAN, ARPHRD_MCTP to net/if_arp.h |
||||
|
||||
Add the constant ARPHRD_MCTP, from Linux 5.15, to net/if_arp.h, along |
||||
with ARPHRD_CAN which was added to Linux in version 2.6.25 (commit |
||||
cd05acfe65ed2cf2db683fa9a6adb8d35635263b, "[CAN]: Allocate protocol |
||||
numbers for PF_CAN") but apparently missed for glibc at the time. |
||||
|
||||
Tested for x86_64. |
||||
|
||||
(cherry picked from commit a94d9659cd69dbc70d3494b1cbbbb5a1551675c5) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/net/if_arp.h b/sysdeps/unix/sysv/linux/net/if_arp.h |
||||
index 2a8933cde7cf236d..42910b776660def1 100644 |
||||
--- a/sysdeps/unix/sysv/linux/net/if_arp.h |
||||
+++ b/sysdeps/unix/sysv/linux/net/if_arp.h |
||||
@@ -95,6 +95,8 @@ struct arphdr |
||||
#define ARPHRD_ROSE 270 |
||||
#define ARPHRD_X25 271 /* CCITT X.25. */ |
||||
#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware. */ |
||||
+#define ARPHRD_CAN 280 /* Controller Area Network. */ |
||||
+#define ARPHRD_MCTP 290 |
||||
#define ARPHRD_PPP 512 |
||||
#define ARPHRD_CISCO 513 /* Cisco HDLC. */ |
||||
#define ARPHRD_HDLC ARPHRD_CISCO |
@ -0,0 +1,337 @@
@@ -0,0 +1,337 @@
|
||||
commit 6af165658d0999ac2c4e9ce88bee020fbc2ee49f |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Wed Mar 23 17:11:56 2022 +0000 |
||||
|
||||
Update syscall lists for Linux 5.17 |
||||
|
||||
Linux 5.17 has one new syscall, set_mempolicy_home_node. Update |
||||
syscall-names.list and regenerate the arch-syscall.h headers with |
||||
build-many-glibcs.py update-syscalls. |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
(cherry picked from commit 8ef9196b26793830515402ea95aca2629f7721ec) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
index 9905ebedf298954c..4fcb6da80af37e9e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
@@ -236,6 +236,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_tid_address 96 |
||||
#define __NR_setdomainname 162 |
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
index ee8085be69958b25..0cf74c1a96bb1235 100644 |
||||
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
@@ -391,6 +391,7 @@ |
||||
#define __NR_sendmsg 114 |
||||
#define __NR_sendto 133 |
||||
#define __NR_set_mempolicy 431 |
||||
+#define __NR_set_mempolicy_home_node 560 |
||||
#define __NR_set_robust_list 466 |
||||
#define __NR_set_tid_address 411 |
||||
#define __NR_setdomainname 166 |
||||
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
index 1b626d97705d545a..c1207aaa12be6a51 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
@@ -238,6 +238,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_tid_address 96 |
||||
#define __NR_setdomainname 162 |
||||
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
index 96ef8db9368e7de4..e7ba04c106d8af7d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
@@ -302,6 +302,7 @@ |
||||
#define __NR_sendmsg 296 |
||||
#define __NR_sendto 290 |
||||
#define __NR_set_mempolicy 321 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 338 |
||||
#define __NR_set_tid_address 256 |
||||
#define __NR_set_tls 983045 |
||||
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
index 96910154ed6a5c1b..dc9383758ebc641b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
@@ -250,6 +250,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_thread_area 244 |
||||
#define __NR_set_tid_address 96 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
index 36675fd48e6f50c5..767f1287a30b473e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
@@ -289,6 +289,7 @@ |
||||
#define __NR_sendmsg 183 |
||||
#define __NR_sendto 82 |
||||
#define __NR_set_mempolicy 262 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 289 |
||||
#define __NR_set_tid_address 237 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
index c86ccbda4681066c..1998f0d76a444cac 100644 |
||||
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
@@ -323,6 +323,7 @@ |
||||
#define __NR_sendmsg 370 |
||||
#define __NR_sendto 369 |
||||
#define __NR_set_mempolicy 276 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 311 |
||||
#define __NR_set_thread_area 243 |
||||
#define __NR_set_tid_address 258 |
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h |
||||
index d898bce404955ef0..b2eab1b93d70b9de 100644 |
||||
--- a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h |
||||
@@ -272,6 +272,7 @@ |
||||
#define __NR_sendmsg 1205 |
||||
#define __NR_sendto 1199 |
||||
#define __NR_set_mempolicy 1261 |
||||
+#define __NR_set_mempolicy_home_node 1474 |
||||
#define __NR_set_robust_list 1298 |
||||
#define __NR_set_tid_address 1233 |
||||
#define __NR_setdomainname 1129 |
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
index fe721b809076abeb..5fc3723772f92516 100644 |
||||
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
@@ -310,6 +310,7 @@ |
||||
#define __NR_sendmsg 367 |
||||
#define __NR_sendto 366 |
||||
#define __NR_set_mempolicy 270 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 304 |
||||
#define __NR_set_thread_area 334 |
||||
#define __NR_set_tid_address 253 |
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
index 6e10c3661db96a1e..b6e9b007e496cd80 100644 |
||||
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
@@ -326,6 +326,7 @@ |
||||
#define __NR_sendmsg 360 |
||||
#define __NR_sendto 353 |
||||
#define __NR_set_mempolicy 276 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 311 |
||||
#define __NR_set_thread_area 243 |
||||
#define __NR_set_tid_address 258 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
index 26a6d594a2222f15..b3a3871f8ab8a23e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
@@ -308,6 +308,7 @@ |
||||
#define __NR_sendmsg 4179 |
||||
#define __NR_sendto 4180 |
||||
#define __NR_set_mempolicy 4270 |
||||
+#define __NR_set_mempolicy_home_node 4450 |
||||
#define __NR_set_robust_list 4309 |
||||
#define __NR_set_thread_area 4283 |
||||
#define __NR_set_tid_address 4252 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
index 83e0d49c5e3ca1bc..b462182723aff286 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
@@ -288,6 +288,7 @@ |
||||
#define __NR_sendmsg 6045 |
||||
#define __NR_sendto 6043 |
||||
#define __NR_set_mempolicy 6233 |
||||
+#define __NR_set_mempolicy_home_node 6450 |
||||
#define __NR_set_robust_list 6272 |
||||
#define __NR_set_thread_area 6246 |
||||
#define __NR_set_tid_address 6213 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
index d6747c542f63202b..a9d6b94572e93001 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
@@ -270,6 +270,7 @@ |
||||
#define __NR_sendmsg 5045 |
||||
#define __NR_sendto 5043 |
||||
#define __NR_set_mempolicy 5229 |
||||
+#define __NR_set_mempolicy_home_node 5450 |
||||
#define __NR_set_robust_list 5268 |
||||
#define __NR_set_thread_area 5242 |
||||
#define __NR_set_tid_address 5212 |
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
index 4ee209bc4475ea7d..809a219ef32a45ef 100644 |
||||
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
@@ -250,6 +250,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_tid_address 96 |
||||
#define __NR_setdomainname 162 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
index 497299fbc47a708c..627831ebae1b9e90 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
@@ -319,6 +319,7 @@ |
||||
#define __NR_sendmsg 341 |
||||
#define __NR_sendto 335 |
||||
#define __NR_set_mempolicy 261 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 300 |
||||
#define __NR_set_tid_address 232 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
index e840279f171b10b9..bae597199d79eaad 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
@@ -298,6 +298,7 @@ |
||||
#define __NR_sendmsg 341 |
||||
#define __NR_sendto 335 |
||||
#define __NR_set_mempolicy 261 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 300 |
||||
#define __NR_set_tid_address 232 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
index 73ef74c005e5a2bb..bf4be80f8d380963 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
@@ -228,6 +228,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_tid_address 96 |
||||
#define __NR_setdomainname 162 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
index 919a79ee91177459..d656aedcc2be6009 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
@@ -235,6 +235,7 @@ |
||||
#define __NR_sendmsg 211 |
||||
#define __NR_sendto 206 |
||||
#define __NR_set_mempolicy 237 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 99 |
||||
#define __NR_set_tid_address 96 |
||||
#define __NR_setdomainname 162 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
index 005c0ada7aab85a1..57025107e82c9439 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
@@ -311,6 +311,7 @@ |
||||
#define __NR_sendmsg 370 |
||||
#define __NR_sendto 369 |
||||
#define __NR_set_mempolicy 270 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 304 |
||||
#define __NR_set_tid_address 252 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
index 9131fddcc16116e4..72e19c6d569fbf9b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
@@ -278,6 +278,7 @@ |
||||
#define __NR_sendmsg 370 |
||||
#define __NR_sendto 369 |
||||
#define __NR_set_mempolicy 270 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 304 |
||||
#define __NR_set_tid_address 252 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
index d8fb041568ecb4da..d52b522d9cac87ef 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
@@ -303,6 +303,7 @@ |
||||
#define __NR_sendmsg 355 |
||||
#define __NR_sendto 349 |
||||
#define __NR_set_mempolicy 276 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 311 |
||||
#define __NR_set_tid_address 258 |
||||
#define __NR_setdomainname 121 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
index 2bc014fe6a1a1f4a..d3f4d8aa3edb4795 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
@@ -310,6 +310,7 @@ |
||||
#define __NR_sendmsg 114 |
||||
#define __NR_sendto 133 |
||||
#define __NR_set_mempolicy 305 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 300 |
||||
#define __NR_set_tid_address 166 |
||||
#define __NR_setdomainname 163 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
index 76dbbe595ffe868f..2cc03d7a24453335 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
@@ -286,6 +286,7 @@ |
||||
#define __NR_sendmsg 114 |
||||
#define __NR_sendto 133 |
||||
#define __NR_set_mempolicy 305 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 300 |
||||
#define __NR_set_tid_address 166 |
||||
#define __NR_setdomainname 163 |
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
index 0bc2af37dfa1eeb5..e2743c649586d97a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list |
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
@@ -21,8 +21,8 @@ |
||||
# This file can list all potential system calls. The names are only |
||||
# used if the installed kernel headers also provide them. |
||||
|
||||
-# The list of system calls is current as of Linux 5.16. |
||||
-kernel 5.16 |
||||
+# The list of system calls is current as of Linux 5.17. |
||||
+kernel 5.17 |
||||
|
||||
FAST_atomic_update |
||||
FAST_cmpxchg |
||||
@@ -523,6 +523,7 @@ sendmmsg |
||||
sendmsg |
||||
sendto |
||||
set_mempolicy |
||||
+set_mempolicy_home_node |
||||
set_robust_list |
||||
set_thread_area |
||||
set_tid_address |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
index 28558279b48a1ef4..b4ab892ec183e32d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
@@ -278,6 +278,7 @@ |
||||
#define __NR_sendmsg 46 |
||||
#define __NR_sendto 44 |
||||
#define __NR_set_mempolicy 238 |
||||
+#define __NR_set_mempolicy_home_node 450 |
||||
#define __NR_set_robust_list 273 |
||||
#define __NR_set_thread_area 205 |
||||
#define __NR_set_tid_address 218 |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
index c1ab8ec45e8b8fd3..772559c87b3625b8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
@@ -270,6 +270,7 @@ |
||||
#define __NR_sendmsg 1073742342 |
||||
#define __NR_sendto 1073741868 |
||||
#define __NR_set_mempolicy 1073742062 |
||||
+#define __NR_set_mempolicy_home_node 1073742274 |
||||
#define __NR_set_robust_list 1073742354 |
||||
#define __NR_set_thread_area 1073742029 |
||||
#define __NR_set_tid_address 1073742042 |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit 81181ba5d916fc49bd737f603e28a3c2dc8430b4 |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Wed Feb 16 14:19:24 2022 +0000 |
||||
|
||||
Update kernel version to 5.16 in tst-mman-consts.py |
||||
|
||||
This patch updates the kernel version in the test tst-mman-consts.py |
||||
to 5.16. (There are no new MAP_* constants covered by this test in |
||||
5.16 that need any other header changes.) |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
(cherry picked from commit 790a607e234aa10d4b977a1b80aebe8a2acac970) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-mman-consts.py b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
index eeccdfd04dae57ab..8102d80b6660e523 100644 |
||||
--- a/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
+++ b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
@@ -33,7 +33,7 @@ def main(): |
||||
help='C compiler (including options) to use') |
||||
args = parser.parse_args() |
||||
linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) |
||||
- linux_version_glibc = (5, 15) |
||||
+ linux_version_glibc = (5, 16) |
||||
sys.exit(glibcextract.compare_macro_consts( |
||||
'#define _GNU_SOURCE 1\n' |
||||
'#include <sys/mman.h>\n', |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit 0499c3a95fb864284fef36d3e9c5a54f6646b2db |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Thu Mar 24 15:35:27 2022 +0000 |
||||
|
||||
Update kernel version to 5.17 in tst-mman-consts.py |
||||
|
||||
This patch updates the kernel version in the test tst-mman-consts.py |
||||
to 5.17. (There are no new MAP_* constants covered by this test in |
||||
5.17 that need any other header changes.) |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
(cherry picked from commit 23808a422e6036accaba7236fd3b9a0d7ab7e8ee) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-mman-consts.py b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
index 8102d80b6660e523..724c7375c3a1623b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
+++ b/sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
@@ -33,7 +33,7 @@ def main(): |
||||
help='C compiler (including options) to use') |
||||
args = parser.parse_args() |
||||
linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) |
||||
- linux_version_glibc = (5, 16) |
||||
+ linux_version_glibc = (5, 17) |
||||
sys.exit(glibcextract.compare_macro_consts( |
||||
'#define _GNU_SOURCE 1\n' |
||||
'#include <sys/mman.h>\n', |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
commit f858bc309315a03ff6b1a048f59405c159d23430 |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Mon Feb 21 22:49:36 2022 +0000 |
||||
|
||||
Add SOL_MPTCP, SOL_MCTP from Linux 5.16 to bits/socket.h |
||||
|
||||
Linux 5.16 adds constants SOL_MPTCP and SOL_MCTP to the getsockopt / |
||||
setsockopt levels; add these constants to bits/socket.h. |
||||
|
||||
Tested for x86_64. |
||||
|
||||
(cherry picked from commit fdc1ae67fef27eea1445bab4bdfe2f0fb3bc7aa1) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h |
||||
index 7bb9e863d7329da9..c81fab840918924e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/bits/socket.h |
||||
+++ b/sysdeps/unix/sysv/linux/bits/socket.h |
||||
@@ -169,6 +169,8 @@ typedef __socklen_t socklen_t; |
||||
#define SOL_KCM 281 |
||||
#define SOL_TLS 282 |
||||
#define SOL_XDP 283 |
||||
+#define SOL_MPTCP 284 |
||||
+#define SOL_MCTP 285 |
||||
|
||||
/* Maximum queue length specifiable by listen. */ |
||||
#define SOMAXCONN 4096 |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
commit c108e87026d61d6744e3e55704e0bea937243f5a |
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
Date: Tue Dec 14 11:15:07 2021 +0000 |
||||
|
||||
aarch64: Add HWCAP2_ECV from Linux 5.16 |
||||
|
||||
Indicates the availability of enhanced counter virtualization extension |
||||
of armv8.6-a with self-synchronized virtual counter CNTVCTSS_EL0 usable |
||||
in userspace. |
||||
|
||||
(cherry picked from commit 5a1be8ebdf6f02d4efec6e5f12ad06db17511f90) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
index 30fda0a4a347695e..04cc762015a7230a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
@@ -74,3 +74,4 @@ |
||||
#define HWCAP2_RNG (1 << 16) |
||||
#define HWCAP2_BTI (1 << 17) |
||||
#define HWCAP2_MTE (1 << 18) |
||||
+#define HWCAP2_ECV (1 << 19) |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
commit 97cb8227b864b8ea0d99a4a50e4163baad3e1c72 |
||||
Author: Joseph Myers <joseph@codesourcery.com> |
||||
Date: Mon Mar 28 13:16:48 2022 +0000 |
||||
|
||||
Add HWCAP2_AFP, HWCAP2_RPRES from Linux 5.17 to AArch64 bits/hwcap.h |
||||
|
||||
Add the new HWCAP2_AFP and HWCAP2_RPRES constants from Linux 5.17. |
||||
Tested with build-many-glibcs.py for aarch64-linux-gnu. |
||||
|
||||
(cherry picked from commit 866c599182e87f116440b5d854f9e99533c48eb3) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
index 04cc762015a7230a..9a5c4116b3fe9903 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h |
||||
@@ -75,3 +75,5 @@ |
||||
#define HWCAP2_BTI (1 << 17) |
||||
#define HWCAP2_MTE (1 << 18) |
||||
#define HWCAP2_ECV (1 << 19) |
||||
+#define HWCAP2_AFP (1 << 20) |
||||
+#define HWCAP2_RPRES (1 << 21) |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
commit 31af92b9c8cf753992d45c801a855a02060afc08 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed May 4 15:56:47 2022 +0530 |
||||
|
||||
manual: Clarify that abbreviations of long options are allowed |
||||
|
||||
The man page and code comments clearly state that abbreviations of long |
||||
option names are recognized correctly as long as they are unique. |
||||
Document this fact in the glibc manual as well. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
Reviewed-by: Andreas Schwab <schwab@linux-m68k.org> |
||||
(cherry picked from commit db1efe02c9f15affc3908d6ae73875b82898a489) |
||||
|
||||
diff --git a/manual/getopt.texi b/manual/getopt.texi |
||||
index 5485fc46946631f7..b4c0b15ac2060560 100644 |
||||
--- a/manual/getopt.texi |
||||
+++ b/manual/getopt.texi |
||||
@@ -250,7 +250,8 @@ option, and stores the option's argument (if it has one) in @code{optarg}. |
||||
|
||||
When @code{getopt_long} encounters a long option, it takes actions based |
||||
on the @code{flag} and @code{val} fields of the definition of that |
||||
-option. |
||||
+option. The option name may be abbreviated as long as the abbreviation is |
||||
+unique. |
||||
|
||||
If @code{flag} is a null pointer, then @code{getopt_long} returns the |
||||
contents of @code{val} to indicate which option it found. You should |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
commit d299032743e05571ef326c838a5ecf6ef5b3e9c3 |
||||
Author: H.J. Lu <hjl.tools@gmail.com> |
||||
Date: Fri Feb 4 11:09:10 2022 -0800 |
||||
|
||||
x86-64: Fix strcmp-avx2.S |
||||
|
||||
Change "movl %edx, %rdx" to "movl %edx, %edx" in: |
||||
|
||||
commit b77b06e0e296f1a2276c27a67e1d44f2cfa38d45 |
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
Date: Mon Jan 10 15:35:38 2022 -0600 |
||||
|
||||
x86: Optimize strcmp-avx2.S |
||||
|
||||
(cherry picked from commit c15efd011cea3d8f0494269eb539583215a1feed) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
index a0d1c65db11028bc..cdded412a70bad10 100644 |
||||
--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S |
||||
@@ -106,7 +106,7 @@ ENTRY(STRCMP) |
||||
# ifdef USE_AS_STRNCMP |
||||
# ifdef __ILP32__ |
||||
/* Clear the upper 32 bits. */ |
||||
- movl %edx, %rdx |
||||
+ movl %edx, %edx |
||||
# endif |
||||
cmp $1, %RDX_LP |
||||
/* Signed comparison intentional. We use this branch to also |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue