diff options
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 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; } |