mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 17:53:37 +08:00
78308ce77a
The new __riscv_hwprobe() function is designed to be used by ifunc selector functions. This presents a challenge for applications and libraries, as ifunc selectors are invoked before all relocations have been performed, so an external call to __riscv_hwprobe() from an ifunc selector won't work. To address this, pass a pointer to the __riscv_hwprobe() function into ifunc selectors as the second argument (alongside dl_hwcap, which was already being passed). Include a typedef as well for convenience, so that ifunc users don't have to go through contortions to call this routine. Users will need to remember to check the second argument for NULL, to account for older glibcs that don't pass the function. Signed-off-by: Evan Green <evan@rivosinc.com> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
58 lines
1.7 KiB
C
58 lines
1.7 KiB
C
/* Machine-dependent ELF indirect relocation inline functions.
|
|
RISC-V version.
|
|
Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _DL_IREL_H
|
|
#define _DL_IREL_H
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <ldsodefs.h>
|
|
#include <sysdep.h>
|
|
#include <sys/hwprobe.h>
|
|
|
|
#define ELF_MACHINE_IRELA 1
|
|
|
|
static inline ElfW(Addr)
|
|
__attribute ((always_inline))
|
|
elf_ifunc_invoke (ElfW(Addr) addr)
|
|
{
|
|
/* The third argument is a void pointer to preserve the extension
|
|
flexibility. */
|
|
return ((ElfW(Addr) (*) (uint64_t, void *, void *)) (addr))
|
|
(GLRO(dl_hwcap), __riscv_hwprobe, NULL);
|
|
}
|
|
|
|
static inline void
|
|
__attribute ((always_inline))
|
|
elf_irela (const ElfW(Rela) *reloc)
|
|
{
|
|
ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset;
|
|
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
|
|
|
|
if (__glibc_likely (r_type == R_RISCV_IRELATIVE))
|
|
{
|
|
ElfW(Addr) value = elf_ifunc_invoke (reloc->r_addend);
|
|
*reloc_addr = value;
|
|
}
|
|
else
|
|
__libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
}
|
|
|
|
#endif
|