From patchwork Sat Dec 2 19:54:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John David Anglin X-Patchwork-Id: 24692 Received: (qmail 98119 invoked by alias); 2 Dec 2017 19:54:47 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 98100 invoked by uid 89); 2 Dec 2017 19:54:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 spammy=sad, Thing, mandatory, 4995 X-HELO: torfep01.bell.net Subject: Re: [PATCH] Handle __gmon_start__ as undefined weak or hidden on hppa Mime-Version: 1.0 (Apple Message framework v1085) From: John David Anglin In-Reply-To: Date: Sat, 2 Dec 2017 14:54:40 -0500 Cc: GNU C Library , Mike Frysinger , Helge Deller Message-Id: References: To: John David Anglin 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 [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)