elf: Add _dl_audit_pltexit

It consolidates the code required to call la_pltexit audit
callback.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
This commit is contained in:
Adhemerval Zanella 2021-07-22 18:02:42 -03:00
parent eff687e846
commit 8c0664e2b8
27 changed files with 158 additions and 122 deletions

View File

@ -20,6 +20,8 @@
#include <link.h>
#include <ldsodefs.h>
#include <dl-machine.h>
#include <dl-runtime.h>
#include <dl-fixup-attribute.h>
void
_dl_audit_activity_map (struct link_map *l, int action)
@ -320,3 +322,48 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
*value = DL_FIXUP_ADDR_VALUE (sym.st_value);
}
void
DL_ARCH_FIXUP_ATTRIBUTE
_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
const void *inregs, void *outregs)
{
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
/* This is the address in the array where we store the result of previous
relocations. */
// XXX Maybe the bound information must be stored on the stack since
// XXX with bind_not a new value could have been stored in the meantime.
struct reloc_result *reloc_result =
&l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB])
+ reloc_result->boundndx);
/* Set up the sym parameter. */
ElfW(Sym) sym = *defsym;
sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
/* Get the symbol name. */
const char *strtab = (const void *) D_PTR (reloc_result->bound,
l_info[DT_STRTAB]);
const char *symname = strtab + sym.st_name;
struct audit_ifaces *afct = GLRO(dl_audit);
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
{
if (afct->ARCH_LA_PLTEXIT != NULL
&& (reloc_result->enterexit
& (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
{
struct auditstate *l_state = link_map_audit_state (l, cnt);
struct auditstate *bound_state
= link_map_audit_state (reloc_result->bound, cnt);
afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
&l_state->cookie, &bound_state->cookie,
inregs, outregs, symname);
}
afct = afct->next;
}
}

View File

@ -16,8 +16,6 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */
#include <alloca.h>
#include <assert.h>
#include <stdlib.h>
@ -31,19 +29,6 @@
#include <dl-runtime.h>
#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|| ELF_MACHINE_NO_REL
# define PLTREL ElfW(Rela)
#else
# define PLTREL ElfW(Rel)
#endif
/* The fixup functions might have need special attributes. If none
are provided define the macro as empty. */
#ifndef ARCH_FIXUP_ATTRIBUTE
# define ARCH_FIXUP_ATTRIBUTE
#endif
/* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation
specified in the PLT of the given shared object, and return the resolved
@ -52,7 +37,7 @@
function. */
DL_FIXUP_VALUE_TYPE
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE
_dl_fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@ -148,7 +133,8 @@ _dl_fixup (
#ifndef PROF
DL_FIXUP_VALUE_TYPE
__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
__attribute ((noinline))
DL_ARCH_FIXUP_ATTRIBUTE
_dl_profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@ -332,52 +318,3 @@ _dl_profile_fixup (
}
#endif /* PROF */
#include <stdio.h>
void
ARCH_FIXUP_ATTRIBUTE
_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
const void *inregs, void *outregs)
{
#ifdef SHARED
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
/* This is the address in the array where we store the result of previous
relocations. */
// XXX Maybe the bound information must be stored on the stack since
// XXX with bind_not a new value could have been stored in the meantime.
struct reloc_result *reloc_result =
&l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB])
+ reloc_result->boundndx);
/* Set up the sym parameter. */
ElfW(Sym) sym = *defsym;
sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
/* Get the symbol name. */
const char *strtab = (const void *) D_PTR (reloc_result->bound,
l_info[DT_STRTAB]);
const char *symname = strtab + sym.st_name;
struct audit_ifaces *afct = GLRO(dl_audit);
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
{
if (afct->ARCH_LA_PLTEXIT != NULL
&& (reloc_result->enterexit
& (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
{
struct auditstate *l_state = link_map_audit_state (l, cnt);
struct auditstate *bound_state
= link_map_audit_state (reloc_result->bound, cnt);
afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
&l_state->cookie, &bound_state->cookie,
inregs, outregs, symname);
}
afct = afct->next;
}
#endif
}

View File

@ -436,3 +436,11 @@ _dl_get_dl_main_map (void)
return &_dl_main_map;
}
#endif
/* This is used by _dl_runtime_profile, not used on static code. */
void
DL_ARCH_FIXUP_ATTRIBUTE
_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
const void *inregs, void *outregs)
{
}

View File

@ -293,7 +293,7 @@ _dl_runtime_profile:
ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
add x2, x29, #OFFSET_RG
add x3, x29, #OFFSET_RV
bl _dl_call_pltexit
bl _dl_audit_pltexit
ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]

View File

@ -187,7 +187,7 @@ _dl_runtime_profile_new:
jsr $26, ($27), 0
ldgp $29, 0($26)
/* Set up for call to _dl_call_pltexit. */
/* Set up for call to _dl_audit_pltexit. */
ldq $16, 16*8($15)
ldq $17, 17*8($15)
stq $0, 16*8($15)
@ -196,7 +196,7 @@ _dl_runtime_profile_new:
lda $19, 16*8($15)
stt $f0, 18*8($15)
stt $f1, 19*8($15)
bsr $26, _dl_call_pltexit !samegp
bsr $26, _dl_audit_pltexit !samegp
mov $15, $30
cfi_def_cfa_register (30)
@ -518,7 +518,7 @@ _dl_runtime_profile_old:
jsr $26, ($27), 0
ldgp $29, 0($26)
/* Set up for call to _dl_call_pltexit. */
/* Set up for call to _dl_audit_pltexit. */
ldq $16, 48*8($15)
ldq $17, 49*8($15)
stq $0, 46*8($15)
@ -527,7 +527,7 @@ _dl_runtime_profile_old:
lda $19, 46*8($15)
stt $f0, 48*8($15)
stt $f1, 49*8($15)
bsr $26, _dl_call_pltexit !samegp
bsr $26, _dl_audit_pltexit !samegp
mov $15, $30
cfi_def_cfa_register (30)

View File

@ -28,4 +28,6 @@
Prelinked libraries may use Elf32_Rela though. */
#define ELF_MACHINE_PLT_REL 1
#define PLTREL ElfW(Rel)
#endif

View File

@ -194,7 +194,7 @@ _dl_runtime_profile:
ldmia ip, {r0,r1}
add r2, r7, #72
add r3, r7, #0
bl _dl_call_pltexit
bl _dl_audit_pltexit
@ Return to caller.
ldmia r7, {r0-r3}

View File

@ -0,0 +1,24 @@
/* ABI specifics for lazy resolution functions.
Copyright (C) 2021 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_FIXUP_ATTRIBUTE_H
#define _DL_FIXUP_ATTRIBUTE_H
#define DL_ARCH_FIXUP_ATTRIBUTE
#endif

View File

@ -23,5 +23,7 @@
#define ELF_MACHINE_NO_REL 1
/* Defined if the architecture supports Elf{32,64}_Rela relocations. */
#define ELF_MACHINE_NO_RELA 0
/* Used to calculate the index of link_map l_reloc_result. */
#define PLTREL ElfW(Rela)
#endif

View File

@ -35,6 +35,7 @@
#include <link.h>
#include <dl-lookupcfg.h>
#include <dl-sysdep.h>
#include <dl-fixup-attribute.h>
#include <libc-lock.h>
#include <hp-timing.h>
#include <tls.h>
@ -1438,6 +1439,11 @@ void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
DL_FIXUP_VALUE_TYPE *value, void *regs,
long int *framesize)
attribute_hidden;
void DL_ARCH_FIXUP_ATTRIBUTE _dl_audit_pltexit (struct link_map *l,
ElfW(Word) reloc_arg,
const void *inregs,
void *outregs)
attribute_hidden;
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED

View File

@ -26,7 +26,7 @@
_dl_fixup with the relocation offset. */
ElfW(Word)
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE
_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l)
{
Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type;

View File

@ -300,7 +300,7 @@ L(cont):
ldw -4(%sp),%r1
copy %r1, %sp
/* Arguments to _dl_call_pltexit */
/* Arguments to _dl_audit_pltexit */
ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */
ldw -120(%sp), %r25 /* (2) reloc offsets */
ldo -56(%sp), %r24 /* (3) *La_hppa_regs */
@ -312,8 +312,8 @@ L(cont):
ldo -128(%sp), %r1
fstd %fr4,0(%r1)
/* Call _dl_call_pltexit */
bl _dl_call_pltexit,%rp
/* Call _dl_audit_pltexit */
bl _dl_audit_pltexit,%rp
nop
/* Restore *La_hppa_retval */

View File

@ -0,0 +1,30 @@
/* ABI specifics for lazy resolution functions. i386 version.
Copyright (C) 2021 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_FIXUP_ATTRIBUTE_H
#define _DL_FIXUP_ATTRIBUTE_H
/* We cannot use this scheme for profiling because the _mcount call destroys
the passed register information. */
#ifndef PROF
# define DL_ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
#else
# define DL_ARCH_FIXUP_ATTRIBUTE
#endif
#endif

View File

@ -28,4 +28,6 @@
Prelinked libraries may use Elf32_Rela though. */
#define ELF_MACHINE_PLT_REL 1
#define PLTREL ElfW(Rel)
#endif

View File

@ -115,29 +115,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
return lazy;
}
#ifdef IN_DL_RUNTIME
# ifndef PROF
/* We add a declaration of this function here so that in dl-runtime.c
the ELF_MACHINE_RUNTIME_TRAMPOLINE macro really can pass the parameters
in registers.
We cannot use this scheme for profiling because the _mcount call
destroys the passed register information. */
#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
extern ElfW(Addr) _dl_fixup (struct link_map *l,
ElfW(Word) reloc_offset)
ARCH_FIXUP_ATTRIBUTE;
extern ElfW(Addr) _dl_profile_fixup (struct link_map *l,
ElfW(Word) reloc_offset,
ElfW(Addr) retaddr, void *regs,
long int *framesizep)
ARCH_FIXUP_ATTRIBUTE;
# endif
#endif
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0xf0000000UL

View File

@ -252,7 +252,7 @@ _dl_runtime_profile:
movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax
# PLT1
movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx
call _dl_call_pltexit
call _dl_audit_pltexit
movl LRV_EAX_OFFSET(%esp), %eax
movl LRV_EDX_OFFSET(%esp), %edx
fldt LRV_ST1_OFFSET(%esp)

View File

@ -133,7 +133,7 @@ END(_dl_runtime_resolve)
/* The fourth argument to _dl_profile_fixup and the third one to
_dl_call_pltexit are a pointer to La_ia64_regs:
_dl_audit_pltexit are a pointer to La_ia64_regs:
8byte r8
8byte r9
@ -159,7 +159,7 @@ END(_dl_runtime_resolve)
8byte sp
The fifth argument to _dl_profile_fixup is a pointer to long int.
The fourth argument to _dl_call_pltexit is a pointer to
The fourth argument to _dl_audit_pltexit is a pointer to
La_ia64_retval:
8byte r8
@ -261,7 +261,7 @@ ENTRY(_dl_runtime_profile)
}
{ .mii
mov r18 = ar.unat /* save it in La_ia64_regs */
mov loc7 = out3 /* save it for _dl_call_pltexit */
mov loc7 = out3 /* save it for _dl_audit_pltexit */
mov loc5 = r11 /* preserve language specific register */
}
{ .mmi
@ -272,7 +272,7 @@ ENTRY(_dl_runtime_profile)
}
{ .mii
mov ar.unat = r17 /* restore it for function call */
mov loc8 = r16 /* save it for _dl_call_pltexit */
mov loc8 = r16 /* save it for _dl_audit_pltexit */
nop.i 0x0
}
{ .mmi
@ -291,7 +291,7 @@ ENTRY(_dl_runtime_profile)
{ .mmi
stf.spill [r2] = f14, 32
stf.spill [r3] = f15, 24
mov loc9 = out1 /* save it for _dl_call_pltexit */
mov loc9 = out1 /* save it for _dl_audit_pltexit */
;;
}
{ .mmb
@ -426,7 +426,7 @@ ENTRY(_dl_runtime_profile)
br.call.sptk.many b0 = b6
}
{ .mii
/* Prepare stack for _dl_call_pltexit. Loc10 has the original
/* Prepare stack for _dl_audit_pltexit. Loc10 has the original
stack pointer. */
adds r12 = -PLTEXIT_FRAME_SIZE, loc10
adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10
@ -461,14 +461,14 @@ ENTRY(_dl_runtime_profile)
{ .mmi
stf.spill [r2] = f12, 32
stf.spill [r3] = f13, 32
/* We need to restore gp for _dl_call_pltexit. */
/* We need to restore gp for _dl_audit_pltexit. */
mov gp = loc11
;;
}
{ .mmb
stf.spill [r2] = f14
stf.spill [r3] = f15
br.call.sptk.many b0 = _dl_call_pltexit
br.call.sptk.many b0 = _dl_audit_pltexit
}
{ .mmi
/* Load all the non-floating and floating return values. Skip

View File

@ -202,7 +202,7 @@ _dl_runtime_profile:
cfi_adjust_cfa_offset (4)
move.l (32+FPSPACE)(%sp), -(%sp)
cfi_adjust_cfa_offset (4)
jbsr _dl_call_pltexit
jbsr _dl_audit_pltexit
lea 16(%sp), %sp
cfi_adjust_cfa_offset (-16)
move.l (%sp)+, %d0

View File

@ -22,5 +22,6 @@
#define ELF_MACHINE_PLT_REL 1
#define ELF_MACHINE_NO_REL 0
#define ELF_MACHINE_NO_RELA 0
#define PLTREL ElfW(Rel)
#endif

View File

@ -197,7 +197,7 @@ END(_dl_runtime_resolve)
#ifndef PROF
ENTRY (_dl_profile_resolve, 4)
/* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we
need to call _dl_call_pltexit. */
need to call _dl_audit_pltexit. */
std r31,-8(r1)
std r30,-16(r1)
/* We need to save the registers used to pass parameters, ie. r3 thru
@ -452,7 +452,7 @@ L(restoreFXR2):
L(callpltexit):
addi r5,r1,INT_PARMS
addi r6,r1,INT_RTN
bl JUMPTARGET(_dl_call_pltexit)
bl JUMPTARGET(_dl_audit_pltexit)
#ifndef SHARED
nop
#endif

View File

@ -282,7 +282,7 @@ _dl_runtime_profile:
basr %r1,0
5: l %r14,7f-5b(%r1)
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_32_retval *
bas %r14,0(%r14,%r1) # call _dl_call_pltexit
bas %r14,0(%r14,%r1) # call _dl_audit_pltexit
lr %r15,%r12 # remove stack frame
# undef FRAME_SIZE
@ -301,7 +301,7 @@ _dl_runtime_profile:
br %r14
6: .long _dl_profile_fixup - 0b
7: .long _dl_call_pltexit - 5b
7: .long _dl_audit_pltexit - 5b
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile
# undef SIZEOF_STRUCT_LA_S390_32_REGS

View File

@ -284,7 +284,7 @@ _dl_runtime_profile:
lmg %r2,%r4,CFA_OFF+PLT1_OFF(%r12) # r2, r3: args saved by PLT
# r4: struct La_s390_64_regs *
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_64_retval *
brasl %r14,_dl_call_pltexit
brasl %r14,_dl_audit_pltexit
lgr %r15,%r12 # remove stack frame
# undef FRAME_SIZE

View File

@ -423,8 +423,8 @@ _dl_runtime_profile:
.align 2
#ifdef SHARED
7: .long _GLOBAL_OFFSET_TABLE_
8: .long _dl_call_pltexit@GOTOFF
8: .long _dl_audit_pltexit@GOTOFF
#else
8: .long _dl_call_pltexit
8: .long _dl_audit_pltexit
#endif
.size _dl_runtime_profile, .-_dl_runtime_profile

View File

@ -127,7 +127,7 @@ _dl_profile_invoke:
mov %l5, %o0
mov %l6, %o1
add %sp, (11 * 8), %o2
call _dl_call_pltexit
call _dl_audit_pltexit
add %sp, ( 9 * 8), %o3
ldd [%sp + ( 9 * 8)], %i0

View File

@ -196,7 +196,7 @@ _dl_profile_invoke:
mov %l5, %o0
mov %l6, %o1
add %sp, STACK_BIAS + (24 * 8), %o2
call _dl_call_pltexit
call _dl_audit_pltexit
add %sp, STACK_BIAS + (16 * 8), %o3
ldx [%sp + STACK_BIAS + (16 * 8)], %i0

View File

@ -18,7 +18,7 @@
02111-1307 USA. */
/* The ABI calls for the PLT stubs to pass the index of the relocation
and not its offset. In _dl_profile_fixup and _dl_call_pltexit we
and not its offset. In _dl_profile_fixup and _dl_audit_pltexit we
also use the index. Therefore it is wasteful to compute the offset
in the trampoline just to reverse the operation immediately
afterwards. */

View File

@ -357,7 +357,7 @@ _dl_runtime_profile:
jns 3f
/* There's nothing in the frame size, so there
will be no call to the _dl_call_pltexit. */
will be no call to the _dl_audit_pltexit. */
/* Get back registers content. */
movq LR_RCX_OFFSET(%rsp), %rcx
@ -403,7 +403,7 @@ _dl_runtime_profile:
mov 24(%rbx), %RSP_LP # Drop the copied stack content
/* Now we have to prepare the La_x86_64_retval structure for the
_dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now,
_dl_audit_pltexit. The La_x86_64_regs is being pointed by rsp now,
so we just need to allocate the sizeof(La_x86_64_retval) space on
the stack, since the alignment has already been taken care of. */
# ifdef RESTORE_AVX
@ -448,7 +448,7 @@ _dl_runtime_profile:
movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx.
movq 40(%rbx), %rsi # Copy args pushed by PLT in register.
movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index
call _dl_call_pltexit
call _dl_audit_pltexit
/* Restore return registers. */
movq LRV_RAX_OFFSET(%rsp), %rax