aboutsummaryrefslogtreecommitdiff
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.zip
glibc-6b32696116e0097f5dd578ec087bcbef483f2a07.tar.gz
glibc-6b32696116e0097f5dd578ec087bcbef483f2a07.tar.bz2
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 c0c9bd9..48aee81 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;
}