+ return 0;
+ }
+diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c
+index 95b46dcbeb..3a323547f9 100644
+--- a/stdio-common/vfscanf-internal.c
++++ b/stdio-common/vfscanf-internal.c
+@@ -277,7 +277,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+ #endif
+ {
+ va_list arg;
+- const CHAR_T *f = format;
++ const UCHAR_T *f = (const UCHAR_T *) format;
+ UCHAR_T fc; /* Current character of the format. */
+ WINT_T done = 0; /* Assignments done. */
+ size_t read_in = 0; /* Chars read in. */
+@@ -415,10 +415,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+ #endif
+
+ #ifndef COMPILE_WSCANF
+- if (!isascii ((unsigned char) *f))
++ if (!isascii (*f))
+ {
+ /* Non-ASCII, may be a multibyte. */
+- int len = __mbrlen (f, strlen (f), &state);
++ int len = __mbrlen ((const char *) f, strlen ((const char *) f),
++ &state);
+ if (len > 0)
+ {
+ do
+@@ -426,7 +427,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+ c = inchar ();
+ if (__glibc_unlikely (c == EOF))
+ input_error ();
+- else if (c != (unsigned char) *f++)
++ else if (c != *f++)
+ {
+ ungetc_not_eof (c, s);
+ conv_error ();
+@@ -484,9 +485,9 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+ char_buffer_rewind (&charbuf);
+
+ /* Check for a positional parameter specification. */
+- if (ISDIGIT ((UCHAR_T) *f))
++ if (ISDIGIT (*f))
+ {
+- argpos = read_int ((const UCHAR_T **) &f);
++ argpos = read_int (&f);
+ if (*f == L_('$'))
+ ++f;
+ else
+@@ -521,8 +522,8 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+
+ /* Find the maximum field width. */
+ width = 0;
+- if (ISDIGIT ((UCHAR_T) *f))
+- width = read_int ((const UCHAR_T **) &f);
++ if (ISDIGIT (*f))
++ width = read_int (&f);
+ got_width:
+ if (width == 0)
+ width = -1;
+@@ -2522,12 +2523,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
+ }
+
+ while ((fc = *f++) != '\0' && fc != ']')
+- if (fc == '-' && *f != '\0' && *f != ']'
+- && (unsigned char) f[-2] <= (unsigned char) *f)
++ if (fc == '-' && *f != '\0' && *f != ']' && f[-2] <= *f)
+ {
+ /* Add all characters from the one before the '-'
+ up to (but not including) the next format char. */
+- for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
++ for (fc = f[-2]; fc < *f; ++fc)
+ ((char *)charbuf.scratch.data)[fc] = 1;
+ }
+ else
+diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
+index 309d0f39b2..c8d3051af8 100644
+--- a/string/bits/string_fortified.h
++++ b/string/bits/string_fortified.h
+@@ -22,11 +22,6 @@
+ # error "Never use <bits/string_fortified.h> directly; include <string.h> instead."
+ #endif
+
+-#if !__GNUC_PREREQ (5,0)
+-__warndecl (__warn_memset_zero_len,
+- "memset used with constant zero length parameter; this could be due to transposed parameters");
+-#endif
+-
+ __fortify_function void *
+ __NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
+ size_t __len))
+@@ -58,16 +53,6 @@ __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
+ __fortify_function void *
+ __NTH (memset (void *__dest, int __ch, size_t __len))
+ {
+- /* GCC-5.0 and newer implements these checks in the compiler, so we don't
+- need them here. */
+-#if !__GNUC_PREREQ (5,0)
+- if (__builtin_constant_p (__len) && __len == 0
+- && (!__builtin_constant_p (__ch) || __ch != 0))
+- {
+- __warn_memset_zero_len ();
+- return __dest;
+- }
+-#endif
+ return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
+ }
+
+diff --git a/support/Makefile b/support/Makefile
+index 93faafddf9..4154863511 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -35,6 +35,8 @@ libsupport-routines = \
+ ignore_stderr \
+ next_to_fault \
+ oom_error \
++ resolv_response_context_duplicate \
++ resolv_response_context_free \
+ resolv_test \
+ set_fortify_handler \
+ support-xfstat \
+diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c
+new file mode 100644
+index 0000000000..f9c5c3462a
+--- /dev/null
++++ b/support/resolv_response_context_duplicate.c
+@@ -0,0 +1,37 @@
++/* Duplicate a response context used in DNS resolver tests.
++ Copyright (C) 2020 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 <string.h>
++#include <support/resolv_test.h>
++#include <support/support.h>
++
++struct resolv_response_context *
++resolv_response_context_duplicate (const struct resolv_response_context *ctx)
++{
++ struct resolv_response_context *result = xmalloc (sizeof (*result));
++ memcpy (result, ctx, sizeof (*result));
++ if (result->client_address != NULL)
++ {
++ result->client_address = xmalloc (result->client_address_length);
++ memcpy (result->client_address, ctx->client_address,
++ result->client_address_length);
++ }
++ result->query_buffer = xmalloc (result->query_length);
++ memcpy (result->query_buffer, ctx->query_buffer, result->query_length);
++ return result;
++}
+diff --git a/support/resolv_response_context_free.c b/support/resolv_response_context_free.c
+new file mode 100644
+index 0000000000..b88c05ffd4
+--- /dev/null
++++ b/support/resolv_response_context_free.c
+@@ -0,0 +1,28 @@
++/* Free a response context used in DNS resolver tests.
++ Copyright (C) 2020 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 <stdlib.h>
++#include <support/resolv_test.h>
++
++void
++resolv_response_context_free (struct resolv_response_context *ctx)
++{
++ free (ctx->query_buffer);
++ free (ctx->client_address);
++ free (ctx);
++}
+diff --git a/support/resolv_test.c b/support/resolv_test.c
+index 53b7fc41ab..9878a040a3 100644
+--- a/support/resolv_test.c
++++ b/support/resolv_test.c
+@@ -181,7 +181,9 @@ resolv_response_init (struct resolv_response_builder *b,
+ b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */
+ if (flags.tc)
+ b->buffer[2] |= 0x02;
+- b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */
++ b->buffer[3] = flags.rcode;
++ if (!flags.clear_ra)
++ b->buffer[3] |= 0x80;
+ if (flags.ad)
+ b->buffer[3] |= 0x20;
+
+@@ -434,9 +436,9 @@ resolv_response_buffer (const struct resolv_response_builder *b)
+ return result;
+ }
+
+-static struct resolv_response_builder *
+-response_builder_allocate
+- (const unsigned char *query_buffer, size_t query_length)
++struct resolv_response_builder *
++resolv_response_builder_allocate (const unsigned char *query_buffer,
++ size_t query_length)
+ {
+ struct resolv_response_builder *b = xmalloc (sizeof (*b));
+ memset (b, 0, offsetof (struct resolv_response_builder, buffer));
+@@ -445,8 +447,8 @@ response_builder_allocate
+ return b;
+ }
+
+-static void
+-response_builder_free (struct resolv_response_builder *b)
++void
++resolv_response_builder_free (struct resolv_response_builder *b)
+ {
+ tdestroy (b->compression_offsets, free);
+ free (b);
+@@ -661,13 +663,17 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
+
+ struct resolv_response_context ctx =
+ {
++ .test = obj,
++ .client_address = &peer,
++ .client_address_length = peerlen,
+ .query_buffer = query,
+ .query_length = length,
+ .server_index = server_index,
+ .tcp = false,
+ .edns = qinfo.edns,
+ };
+- struct resolv_response_builder *b = response_builder_allocate (query, length);
++ struct resolv_response_builder *b
++ = resolv_response_builder_allocate (query, length);
+ obj->config.response_callback
+ (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
+
+@@ -684,7 +690,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
+ if (b->offset >= 12)
+ printf ("info: UDP server %d: sending response:"
+ " %zu bytes, RCODE %d (for %s/%u/%u)\n",
+- server_index, b->offset, b->buffer[3] & 0x0f,
++ ctx.server_index, b->offset, b->buffer[3] & 0x0f,
+ qinfo.qname, qinfo.qclass, qinfo.qtype);
+ else
+ printf ("info: UDP server %d: sending response: %zu bytes"
+@@ -694,23 +700,31 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
+ if (b->truncate_bytes > 0)
+ printf ("info: truncated by %u bytes\n", b->truncate_bytes);
+ }
+- size_t to_send = b->offset;
+- if (to_send < b->truncate_bytes)
+- to_send = 0;
+- else
+- to_send -= b->truncate_bytes;
+-
+- /* Ignore most errors here because the other end may have closed
+- the socket. */
+- if (sendto (obj->servers[server_index].socket_udp,
+- b->buffer, to_send, 0,
+- (struct sockaddr *) &peer, peerlen) < 0)
+- TEST_VERIFY_EXIT (errno != EBADF);
++ resolv_response_send_udp (&ctx, b);
+ }
+- response_builder_free (b);
++ resolv_response_builder_free (b);
+ return true;
+ }
+
++void
++resolv_response_send_udp (const struct resolv_response_context *ctx,
++ struct resolv_response_builder *b)
++{
++ TEST_VERIFY_EXIT (!ctx->tcp);
++ size_t to_send = b->offset;
++ if (to_send < b->truncate_bytes)
++ to_send = 0;
++ else
++ to_send -= b->truncate_bytes;
++
++ /* Ignore most errors here because the other end may have closed
++ the socket. */
++ if (sendto (ctx->test->servers[ctx->server_index].socket_udp,
++ b->buffer, to_send, 0,
++ ctx->client_address, ctx->client_address_length) < 0)
++ TEST_VERIFY_EXIT (errno != EBADF);
++}
++
+ /* UDP thread_callback function. Variant for one thread per
+ server. */
+ static void
+@@ -897,14 +911,15 @@ server_thread_tcp_client (void *arg)
+
+ struct resolv_response_context ctx =
+ {
++ .test = closure->obj,
+ .query_buffer = query_buffer,
+ .query_length = query_length,
+ .server_index = closure->server_index,
+ .tcp = true,
+ .edns = qinfo.edns,
+ };
+- struct resolv_response_builder *b = response_builder_allocate
+- (query_buffer, query_length);
++ struct resolv_response_builder *b
++ = resolv_response_builder_allocate (query_buffer, query_length);
+ closure->obj->config.response_callback
+ (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
+
+@@ -936,7 +951,7 @@ server_thread_tcp_client (void *arg)
+ writev_fully (closure->client_socket, buffers, 2);
+ }
+ bool close_flag = b->close;
+- response_builder_free (b);
++ resolv_response_builder_free (b);
+ free (query_buffer);
+ if (close_flag)
+ break;
+diff --git a/support/resolv_test.h b/support/resolv_test.h
+index 67819469a0..31a5c1c3e7 100644
+--- a/support/resolv_test.h
++++ b/support/resolv_test.h
+@@ -35,25 +35,36 @@ struct resolv_edns_info
+ uint16_t payload_size;
+ };
+
++/* This opaque struct collects information about the resolver testing
++ currently in progress. */
++struct resolv_test;
++
+ /* This struct provides context information when the response callback
+ specified in struct resolv_redirect_config is invoked. */
+ struct resolv_response_context
+ {
+- const unsigned char *query_buffer;
++ struct resolv_test *test;
++ void *client_address;
++ size_t client_address_length;
++ unsigned char *query_buffer;
+ size_t query_length;
+ int server_index;
+ bool tcp;
+ struct resolv_edns_info edns;
+ };
+
++/* Produces a deep copy of the context. */
++struct resolv_response_context *
++ resolv_response_context_duplicate (const struct resolv_response_context *);
++
++/* Frees the copy. For the context passed to the response function,
++ this happens implicitly. */
++void resolv_response_context_free (struct resolv_response_context *);
++
+ /* This opaque struct is used to construct responses from within the
+ response callback function. */
+ struct resolv_response_builder;
+
+-/* This opaque struct collects information about the resolver testing
+- currently in progress. */
+-struct resolv_test;
+-
+ enum
+ {
+ /* Maximum number of test servers supported by the framework. */
+@@ -137,6 +148,10 @@ struct resolv_response_flags
+ /* If true, the AD (authenticated data) flag will be set. */
+ bool ad;
+
++ /* If true, do not set the RA (recursion available) flag in the
++ response. */
++ bool clear_ra;
++
+ /* Initial section count values. Can be used to artificially
+ increase the counts, for malformed packet testing.*/
+ unsigned short qdcount;
+@@ -188,6 +203,22 @@ void resolv_response_close (struct resolv_response_builder *);
+ /* The size of the response packet built so far. */
+ size_t resolv_response_length (const struct resolv_response_builder *);
+
++/* Allocates a response builder tied to a specific query packet,
++ starting at QUERY_BUFFER, containing QUERY_LENGTH bytes. */
++struct resolv_response_builder *
++ resolv_response_builder_allocate (const unsigned char *query_buffer,
++ size_t query_length);
++
++/* Deallocates a response buffer. */
++void resolv_response_builder_free (struct resolv_response_builder *);
++
++/* Sends a UDP response using a specific context. This can be used to
++ reorder or duplicate responses, along with
++ resolv_response_context_duplicate and
++ response_builder_allocate. */
++void resolv_response_send_udp (const struct resolv_response_context *,
++ struct resolv_response_builder *);
++
+ __END_DECLS
+
+ #endif /* SUPPORT_RESOLV_TEST_H */
+diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c
+index 196e462520..cf7624aaa2 100644
+--- a/sysdeps/aarch64/dl-bti.c
++++ b/sysdeps/aarch64/dl-bti.c
+@@ -19,43 +19,76 @@
+ #include <errno.h>
+ #include <libintl.h>
+ #include <ldsodefs.h>
++#include <sys/mman.h>
+
+-static int
+-enable_bti (struct link_map *map, const char *program)
++/* See elf/dl-load.h. */
++#ifndef MAP_COPY
++# define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE)
++#endif
++
++/* Enable BTI protection for MAP. */
++
++void
++_dl_bti_protect (struct link_map *map, int fd)
+ {
++ const size_t pagesz = GLRO(dl_pagesize);
+ const ElfW(Phdr) *phdr;
+- unsigned prot;
+
+ for (phdr = map->l_phdr; phdr < &map->l_phdr[map->l_phnum]; ++phdr)
+ if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
+ {
+- void *start = (void *) (phdr->p_vaddr + map->l_addr);
+- size_t len = phdr->p_memsz;
++ size_t vstart = ALIGN_DOWN (phdr->p_vaddr, pagesz);
++ size_t vend = ALIGN_UP (phdr->p_vaddr + phdr->p_filesz, pagesz);
++ off_t off = ALIGN_DOWN (phdr->p_offset, pagesz);
++ void *start = (void *) (vstart + map->l_addr);
++ size_t len = vend - vstart;
+
+- prot = PROT_EXEC | PROT_BTI;
++ unsigned prot = PROT_EXEC | PROT_BTI;
+ if (phdr->p_flags & PF_R)
+ prot |= PROT_READ;
+ if (phdr->p_flags & PF_W)
+ prot |= PROT_WRITE;
+
+- if (__mprotect (start, len, prot) < 0)
+- {
+- if (program)
+- _dl_fatal_printf ("%s: mprotect failed to turn on BTI\n",
+- map->l_name);
+- else
+- _dl_signal_error (errno, map->l_name, "dlopen",
+- N_("mprotect failed to turn on BTI"));
+- }
++ if (fd == -1)
++ /* Ignore failures for kernel mapped binaries. */
++ __mprotect (start, len, prot);
++ else
++ map->l_mach.bti_fail = __mmap (start, len, prot,
++ MAP_FIXED|MAP_COPY|MAP_FILE,
++ fd, off) == MAP_FAILED;
+ }
+- return 0;
+ }
+
+-/* Enable BTI for L if required. */
++
++static void
++bti_failed (struct link_map *l, const char *program)
++{
++ if (program)
++ _dl_fatal_printf ("%s: %s: failed to turn on BTI protection\n",
++ program, l->l_name);
++ else
++ /* Note: the errno value is not available any more. */
++ _dl_signal_error (0, l->l_name, "dlopen",
++ N_("failed to turn on BTI protection"));
++}
++
++
++/* Enable BTI for L and its dependencies. */
+
+ void
+ _dl_bti_check (struct link_map *l, const char *program)
+ {
+- if (GLRO(dl_aarch64_cpu_features).bti && l->l_mach.bti)
+- enable_bti (l, program);
++ if (!GLRO(dl_aarch64_cpu_features).bti)
++ return;
++
++ if (l->l_mach.bti_fail)
++ bti_failed (l, program);
++
++ unsigned int i = l->l_searchlist.r_nlist;
++ while (i-- > 0)
++ {
++ struct link_map *dep = l->l_initfini[i];
++ if (dep->l_mach.bti_fail)
++ bti_failed (dep, program);
++ }
+ }
+diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
+index 70b9ed3925..fde7cfd9e2 100644
+--- a/sysdeps/aarch64/dl-machine.h
++++ b/sysdeps/aarch64/dl-machine.h
+@@ -395,13 +395,6 @@ elf_machine_lazy_rel (struct link_map *map,
+ /* Check for unexpected PLT reloc type. */
+ if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
+ {
+- if (map->l_mach.plt == 0)
+- {
+- /* Prelinking. */
+- *reloc_addr += l_addr;
+- return;
+- }
+-
+ if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
+ {
+ /* Check the symbol table for variant PCS symbols. */
+@@ -425,7 +418,10 @@ elf_machine_lazy_rel (struct link_map *map,
+ }
+ }
+
+- *reloc_addr = map->l_mach.plt;
++ if (map->l_mach.plt == 0)
++ *reloc_addr += l_addr;
++ else
++ *reloc_addr = map->l_mach.plt;
+ }
+ else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1))
+ {
+diff --git a/sysdeps/aarch64/dl-prop.h b/sysdeps/aarch64/dl-prop.h
+index b0785bda83..e926e54984 100644
+--- a/sysdeps/aarch64/dl-prop.h
++++ b/sysdeps/aarch64/dl-prop.h
+@@ -19,6 +19,8 @@
+ #ifndef _DL_PROP_H
+ #define _DL_PROP_H
+
++extern void _dl_bti_protect (struct link_map *, int) attribute_hidden;
++
+ extern void _dl_bti_check (struct link_map *, const char *)
+ attribute_hidden;
+
+@@ -35,14 +37,18 @@ _dl_open_check (struct link_map *m)
+ }
+
+ static inline void __attribute__ ((always_inline))
+-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
++_dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph)
+ {