00c0d4
commit 9e94f57484a2aba0fe67ea2059b5843f651887c2
00c0d4
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
00c0d4
Date:   Fri Feb 4 15:54:59 2022 -0300
00c0d4
00c0d4
    hppa: Fix bind-now audit (BZ #28857)
00c0d4
    
00c0d4
    On hppa, a function pointer returned by la_symbind is actually a function
00c0d4
    descriptor has the plabel bit set (bit 30).  This must be cleared to get
00c0d4
    the actual address of the descriptor.  If the descriptor has been bound,
00c0d4
    the first word of the descriptor is the physical address of theA function,
00c0d4
    otherwise, the first word of the descriptor points to a trampoline in the
00c0d4
    PLT.
00c0d4
    
00c0d4
    This patch also adds a workaround on tests because on hppa (and it seems
00c0d4
    to be the only ABI I have see it), some shared library adds a dynamic PLT
00c0d4
    relocation to am empty symbol name:
00c0d4
    
00c0d4
    $ readelf -r elf/tst-audit25mod1.so
00c0d4
    [...]
00c0d4
    Relocation section '.rela.plt' at offset 0x464 contains 6 entries:
00c0d4
     Offset     Info    Type            Sym.Value  Sym. Name + Addend
00c0d4
    00002008  00000081 R_PARISC_IPLT                508
00c0d4
    [...]
00c0d4
    
00c0d4
    It breaks some assumptions on the test, where a symbol with an empty
00c0d4
    name ("") is passed on la_symbind.
00c0d4
    
00c0d4
    Checked on x86_64-linux-gnu and hppa-linux-gnu.
00c0d4
00c0d4
diff --git a/elf/Makefile b/elf/Makefile
00c0d4
index 73d347339762fc9e..6d39b400060a73f3 100644
00c0d4
--- a/elf/Makefile
00c0d4
+++ b/elf/Makefile
00c0d4
@@ -2113,7 +2113,7 @@ $(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so
00c0d4
 $(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \
00c0d4
 		       $(objpfx)tst-audit24amod2.so
00c0d4
 tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so
00c0d4
-LDFLAGS-tst-audit24b = -Wl,-z,lazy
00c0d4
+LDFLAGS-tst-audit24c = -Wl,-z,lazy
00c0d4
 
00c0d4
 $(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so
00c0d4
 $(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \
00c0d4
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
00c0d4
index 72a50717ef60a357..ec9b032eae37c103 100644
00c0d4
--- a/elf/dl-audit.c
00c0d4
+++ b/elf/dl-audit.c
00c0d4
@@ -257,7 +257,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
00c0d4
       reloc_result->flags = flags;
00c0d4
     }
00c0d4
 
00c0d4
-  DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
00c0d4
+  if (flags & LA_SYMB_ALTVALUE)
00c0d4
+    DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
00c0d4
 }
00c0d4
 
00c0d4
 void
00c0d4
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c
00c0d4
index d8e88f3984af1707..3075dfae2fd3d288 100644
00c0d4
--- a/elf/tst-auditmod24a.c
00c0d4
+++ b/elf/tst-auditmod24a.c
00c0d4
@@ -110,5 +110,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
00c0d4
       return sym->st_value;
00c0d4
     }
00c0d4
 
00c0d4
-  abort ();
00c0d4
+  if (symname[0] != '\0')
00c0d4
+    abort ();
00c0d4
+  return sym->st_value;
00c0d4
 }
00c0d4
diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c
00c0d4
index 8c803ecc0a48f21b..badc6be451ee0357 100644
00c0d4
--- a/elf/tst-auditmod24d.c
00c0d4
+++ b/elf/tst-auditmod24d.c
00c0d4
@@ -116,5 +116,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
00c0d4
 	}
00c0d4
     }
00c0d4
 
00c0d4
-  abort ();
00c0d4
+  if (symname[0] != '\0')
00c0d4
+    abort ();
00c0d4
+  return sym->st_value;
00c0d4
 }
00c0d4
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c
00c0d4
index 526f5c54bc2c3b8c..20640a8daf346b5f 100644
00c0d4
--- a/elf/tst-auditmod25.c
00c0d4
+++ b/elf/tst-auditmod25.c
00c0d4
@@ -72,7 +72,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
00c0d4
 	      unsigned int *flags, const char *symname)
00c0d4
 #endif
00c0d4
 {
00c0d4
-  if (*refcook != -1 && *defcook != -1)
00c0d4
+  if (*refcook != -1 && *defcook != -1 && symname[0] != '\0')
00c0d4
     fprintf (stderr, "la_symbind: %s %u\n", symname,
00c0d4
 	     *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0);
00c0d4
   return sym->st_value;
00c0d4
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
00c0d4
index c3fea1fe5776b17a..86f6a04af46c87ba 100644
00c0d4
--- a/sysdeps/hppa/dl-lookupcfg.h
00c0d4
+++ b/sysdeps/hppa/dl-lookupcfg.h
00c0d4
@@ -79,7 +79,9 @@ void attribute_hidden _dl_unmap (struct link_map *map);
00c0d4
 /* Extract the code address from a fixup value */
00c0d4
 #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)
00c0d4
 #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
00c0d4
-#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
00c0d4
+/* Clear the plabel bit to get the actual address of the descriptor.  */
00c0d4
+#define DL_FIXUP_ADDR_VALUE(addr) \
00c0d4
+  (*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2))
00c0d4
 #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
00c0d4
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
00c0d4
-  (*value) = *(struct fdesc *) (st_value)
00c0d4
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)	\
00c0d4
+  *(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2)