about summary refs log tree commit diff
path: root/sysdeps/riscv/dl-machine.h
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2023-12-30 11:00:10 +0100
committerAurelien Jarno <aurelien@aurel32.net>2023-12-30 11:00:10 +0100
commit6b32696116e0097f5dd578ec087bcbef483f2a07 (patch)
treeffff362478f2dd820ecff33d8800334aff39b9e0 /sysdeps/riscv/dl-machine.h
parenta8a4c94ae9cefeeba72ca41364fcf684a64477bc (diff)
downloadglibc-6b32696116e0097f5dd578ec087bcbef483f2a07.tar.gz
glibc-6b32696116e0097f5dd578ec087bcbef483f2a07.tar.xz
glibc-6b32696116e0097f5dd578ec087bcbef483f2a07.zip
RISC-V: Add support for dl_runtime_profile (BZ #31151)
Code is mostly inspired from the LoongArch one, which has a similar ABI,
with minor changes to support riscv32 and register differences.

This fixes elf/tst-sprof-basic. This also fixes elf/tst-audit1,
elf/tst-audit2 and elf/tst-audit8 with recent binutils snapshots when
--enable-bind-now is used.

Resolves: BZ #31151

Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'sysdeps/riscv/dl-machine.h')
-rw-r--r--sysdeps/riscv/dl-machine.h27
1 files changed, 26 insertions, 1 deletions
diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
index c0c9bd93ad..48aee81aa9 100644
--- a/sysdeps/riscv/dl-machine.h
+++ b/sysdeps/riscv/dl-machine.h
@@ -313,13 +313,38 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
   if (l->l_info[DT_JMPREL])
     {
       extern void _dl_runtime_resolve (void) __attribute__ ((visibility ("hidden")));
+      extern void _dl_runtime_profile (void) __attribute__ ((visibility ("hidden")));
       ElfW(Addr) *gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
       /* If a library is prelinked but we have to relocate anyway,
 	 we have to be able to undo the prelinking of .got.plt.
 	 The prelinker saved the address of .plt for us here.  */
       if (gotplt[1])
 	l->l_mach.plt = gotplt[1] + l->l_addr;
-      gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve;
+      /* The gotplt[0] entry contains the address of a function which gets
+	 called to get the address of a so far unresolved function and
+	 jump to it.  The profiling extension of the dynamic linker allows
+	 to intercept the calls to collect information.  In this case we
+	 don't store the address in the GOT so that all future calls also
+	 end in this function.  */
+#ifdef SHARED
+      if (profile != 0)
+	{
+	  gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile;
+
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
+	    /* Say that we really want profiling and the timers are
+	       started.  */
+	    GL(dl_profile_map) = l;
+	}
+      else
+#endif
+	{
+	  /* This function will get called to fix up the GOT entry
+	     indicated by the offset on the stack, and then jump to
+	     the resolved address.  */
+	  gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve;
+	}
       gotplt[1] = (ElfW(Addr)) l;
     }