diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2023-12-30 11:00:10 +0100 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2023-12-30 11:00:10 +0100 |
commit | 6b32696116e0097f5dd578ec087bcbef483f2a07 (patch) | |
tree | ffff362478f2dd820ecff33d8800334aff39b9e0 /sysdeps/riscv/dl-machine.h | |
parent | a8a4c94ae9cefeeba72ca41364fcf684a64477bc (diff) | |
download | glibc-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.h | 27 |
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; } |