Handle __gmon_start__ as undefined weak on hppa.
authorJohn David Anglin <danglin@gcc.gnu.org>
Sat, 2 Dec 2017 19:43:28 +0000 (14:43 -0500)
committerJohn David Anglin <danglin@gcc.gnu.org>
Sat, 2 Dec 2017 19:43:28 +0000 (14:43 -0500)
[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.

ChangeLog
sysdeps/hppa/crti.S
sysdeps/hppa/crtn.S
sysdeps/hppa/dl-lookupcfg.h

index d85007e..e24ae78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
index 7c1470d..0f9bb7b 100644 (file)
 # 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
index 42f310d..49666b8 100644 (file)
 /* 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
index 0b0ae85..0b8f031 100644 (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)