d5474c
commit 558251bd8785760ad40fcbfeaaee5d27fa5b0fe4
d5474c
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
d5474c
Date:   Thu Oct 22 17:55:01 2020 +0100
d5474c
d5474c
    aarch64: Fix DT_AARCH64_VARIANT_PCS handling [BZ #26798]
d5474c
    
d5474c
    The variant PCS support was ineffective because in the common case
d5474c
    linkmap->l_mach.plt == 0 but then the symbol table flags were ignored
d5474c
    and normal lazy binding was used instead of resolving the relocs early.
d5474c
    (This was a misunderstanding about how GOT[1] is setup by the linker.)
d5474c
    
d5474c
    In practice this mainly affects SVE calls when the vector length is
d5474c
    more than 128 bits, then the top bits of the argument registers get
d5474c
    clobbered during lazy binding.
d5474c
    
d5474c
    Fixes bug 26798.
d5474c
d5474c
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
d5474c
index b39eae4acf4086ee..3fd3c8a265d012b1 100644
d5474c
--- a/sysdeps/aarch64/dl-machine.h
d5474c
+++ b/sysdeps/aarch64/dl-machine.h
d5474c
@@ -391,13 +391,6 @@ elf_machine_lazy_rel (struct link_map *map,
d5474c
   /* Check for unexpected PLT reloc type.  */
d5474c
   if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
d5474c
     {
d5474c
-      if (map->l_mach.plt == 0)
d5474c
-	{
d5474c
-	  /* Prelinking.  */
d5474c
-	  *reloc_addr += l_addr;
d5474c
-	  return;
d5474c
-	}
d5474c
-
d5474c
       if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
d5474c
 	{
d5474c
 	  /* Check the symbol table for variant PCS symbols.  */
d5474c
@@ -421,7 +414,10 @@ elf_machine_lazy_rel (struct link_map *map,
d5474c
 	    }
d5474c
 	}
d5474c
 
d5474c
-      *reloc_addr = map->l_mach.plt;
d5474c
+      if (map->l_mach.plt == 0)
d5474c
+	*reloc_addr += l_addr;
d5474c
+      else
d5474c
+	*reloc_addr = map->l_mach.plt;
d5474c
     }
d5474c
   else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1))
d5474c
     {