Message ID | BBB983E5-87CC-4BED-967E-2C6A90DE120F@bell.net |
---|---|
State | New |
Headers | show |
On 2015-10-25, at 3:32 PM, John David Anglin wrote: > The attached change fixes libc/19170. It is identical to the approach used on ia64 aside from > the hppa assembler code. I committed the attached change which has been used on Debian for some time. Dave -- John David Anglin dave.anglin@bell.net 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. diff --git a/sysdeps/hppa/crti.S b/sysdeps/hppa/crti.S index 7c1470ddf8..0f9bb7b013 100644 --- a/sysdeps/hppa/crti.S +++ b/sysdeps/hppa/crti.S @@ -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 diff --git a/sysdeps/hppa/crtn.S b/sysdeps/hppa/crtn.S index 42f310d217..49666b81f9 100644 --- a/sysdeps/hppa/crtn.S +++ b/sysdeps/hppa/crtn.S @@ -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 diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h index 0b0ae85b5d..0b8f031823 100644 --- a/sysdeps/hppa/dl-lookupcfg.h +++ b/sysdeps/hppa/dl-lookupcfg.h @@ -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)
diff -up ./crti.S.org ./crti.S --- ./crti.S.org 2015-10-23 17:46:33.115387971 +0200 +++ ./crti.S 2015-10-23 21:46:25.277880769 +0200 @@ -49,6 +49,72 @@ # 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__)(); +} +*/ + .section .data.rel.ro,"aw",@progbits + .align 4 +.LC0: + .word P%__gmon_start__ + .text + .align 4 + .type gmon_initializer, @function +gmon_initializer: + .PROC + .CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=3 + .ENTRY + stw %r2,-20(%r30) + addil LT'.LC0,%r19 + ldw RT'.LC0(%r1),%r28 + stwm %r4,64(%r30) + ldw 0(%r28),%r28 + comib,= 0,%r28,.L1 + stw %r19,-32(%r30) + bl __gmon_start__,%r2 + nop +.L1: + ldw -84(%r30),%r2 + 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 +124,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 diff -up ./crtn.S.org ./crtn.S --- ./crtn.S.org 2015-10-23 17:46:28.283390160 +0200 +++ ./crtn.S 2015-10-23 17:47:15.691368693 +0200 @@ -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