Handle __gmon_start__ as undefined weak on hppa.

[BZ libc/19170]
	* sysdeps/hppa/crti.S: Declare PREINIT_FUNCTION weak_extern when
	PREINIT_FUNCTION_WEAK is nonzero.
	(gmon_initializer): New function.  Put procedure label for it in
	.init_array section.
	(_init): Don't call PREINIT_FUNCTION.
	* sysdeps/hppa/crtn.S (__gmon_start__): Remove.
	* sysdeps/hppa/dl-lookupcfg.h (DL_FIXUP_MAKE_VALUE): Create null fixup
	value when map argument is null.
This commit is contained in:
John David Anglin 2017-12-02 14:43:28 -05:00
parent 800a496acb
commit b3f7fb12f5
4 changed files with 101 additions and 30 deletions

View File

@ -1,5 +1,15 @@
2017-12-02 John David Anglin <danglin@gcc.gnu.org>
[BZ libc/19170]
* sysdeps/hppa/crti.S: Declare PREINIT_FUNCTION weak_extern when
PREINIT_FUNCTION_WEAK is nonzero.
(gmon_initializer): New function. Put procedure label for it in
.init_array section.
(_init): Don't call PREINIT_FUNCTION.
* sysdeps/hppa/crtn.S (__gmon_start__): Remove.
* sysdeps/hppa/dl-lookupcfg.h (DL_FIXUP_MAKE_VALUE): Create null fixup
value when map argument is null.
* sysdeps/hppa/dl-fptr.c (elf_machine_resolve): Remove unnecessary
depi instruction from PIC pc-relative sequence.
* sysdeps/hppa/dl-fptr.h (ELF_MACHINE_LOAD_ADDRESS): Likewise.

View File

@ -49,6 +49,95 @@
# define PREINIT_FUNCTION_WEAK 1
#endif
#if PREINIT_FUNCTION_WEAK
weak_extern (PREINIT_FUNCTION)
#else
.hidden PREINIT_FUNCTION
#endif
/* If we have working .init_array support, we want to keep the .init
section empty (apart from the mandatory prologue/epilogue. This
ensures that the default unwind conventions (return-pointer in b0,
frame state in ar.pfs, etc.) will do the Right Thing. To ensure
an empty .init section, we register gmon_initializer() via the
.init_array.
--davidm 02/10/29 */
#if PREINIT_FUNCTION_WEAK
/* This blob of assembly code is one simple C function:
static void
__attribute__ ((used))
gmon_initializer (void)
{
extern void weak_function __gmon_start__ (void);
if (__gmon_start__)
(*__gmon_start__)();
}
In a final executable, PLABEL32 relocations for function pointers are
resolved at link time. Typically, binutils/ld resolves __gmon_start__
using an external shared library. __gmon_start__ is always called if
it is found at link time. If __gmon_start__ is not found at runtime
due to a library update, then the function pointer will point at a null
function descriptor and calling it will cause a segmentation fault.
So, we call __canonicalize_funcptr_for_compare to obtain the canonicalized
address of __gmon_start__ and skip calling __gmon_start__ if it is zero.
*/
.type __canonicalize_funcptr_for_compare,@function
.type $$dyncall,@function
.section .data.rel.ro,"aw",@progbits
.align 4
.LC0:
.type __gmon_start__,@function
.word P%__gmon_start__
.text
.align 4
.type gmon_initializer,@function
gmon_initializer:
.PROC
.CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=4
.ENTRY
stw %r2,-20(%r30)
stwm %r4,64(%r30)
stw %r3,-60(%r30)
addil LT'.LC0,%r19
ldw RT'.LC0(%r1),%r28
ldw 0(%r28),%r3
comib,= 0,%r3,1f
copy %r19,%r4
stw %r19,-32(%r30)
bl __canonicalize_funcptr_for_compare,%r2
copy %r3,%r26
comib,= 0,%r28,1f
copy %r4,%r19
copy %r3,%r22
.CALL ARGW0=GR
bl $$dyncall,%r31
copy %r31,%r2
1:
ldw -84(%r30),%r2
ldw -60(%r30),%r3
bv %r0(%r2)
ldwm -64(%r30),%r4
.EXIT
.PROCEND
.size gmon_initializer, .-gmon_initializer
# undef PREINIT_FUNCTION
# define PREINIT_FUNCTION gmon_initializer
#endif
.section .init_array, "aw"
.word P% PREINIT_FUNCTION
/* _init prologue. */
.section .init, "ax", %progbits
.align 4
@ -58,14 +147,6 @@ _init:
stw %rp,-20(%sp)
stwm %r4,64(%sp)
stw %r19,-32(%sp)
#if PREINIT_FUNCTION_WEAK
bl PREINIT_FUNCTION,%rp
copy %r19,%r4 /* delay slot */
#else
bl PREINIT_FUNCTION,%rp
copy %r19,%r4 /* delay slot */
#endif
copy %r4,%r19
/* _fini prologue. */
.section .fini,"ax",%progbits

View File

@ -38,27 +38,6 @@
/* crtn.S puts function epilogues in the .init and .fini sections
corresponding to the prologues in crti.S. */
/* Note that we cannot have a weak undefined __gmon_start__, because
that would require this to be PIC, and the linker is currently not
able to generate a proper procedure descriptor for _init. Sad but
true. Anyway, HPPA is one of those horrible architectures where
making the comparison and indirect call is quite expensive (see the
comment in sysdeps/generic/initfini.c). */
.text
.align 4
.weak __gmon_start__
.type __gmon_start__,@function
__gmon_start__:
.proc
.callinfo
.entry
bv,n %r0(%r2)
.exit
.procend
/* Here is the tail end of _init. We put __gmon_start before this so
that the assembler creates the .PARISC.unwind section for us, ie.
with the right attributes. */
.section .init, "ax", @progbits
ldw -84(%sp),%rp
copy %r4,%r19

View File

@ -73,7 +73,8 @@ void attribute_hidden _dl_unmap (struct link_map *map);
/* Construct a fixup value from the address and linkmap */
#define DL_FIXUP_MAKE_VALUE(map, addr) \
((struct fdesc) { (addr), (map)->l_info[DT_PLTGOT]->d_un.d_ptr })
(map) ? ((struct fdesc) { (addr), (map)->l_info[DT_PLTGOT]->d_un.d_ptr }) \
: ((struct fdesc) { 0, 0 })
/* Extract the code address from a fixup value */
#define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)