Since the __{div,rem}{l,q}{,u} special libc entry points use a specific
authormiod <miod@openbsd.org>
Mon, 1 Jun 2015 19:02:11 +0000 (19:02 +0000)
committermiod <miod@openbsd.org>
Mon, 1 Jun 2015 19:02:11 +0000 (19:02 +0000)
calling convention which conflicts over t11 usage with the secureplt
calling convention, force these symbols to be `notype' rather `function', so
that the linker will not attempt to use plt relocations for them in the
absence of explicit relocation information.

Note that these symbols are still public and still callable with the old plt
convention, so existing binaries will still work with an updated libc, and
no libc version change is necessary.

lib/libc/arch/alpha/gen/divrem.m4

index 94ec920..cb35010 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: divrem.m4,v 1.4 2003/03/01 00:19:08 miod Exp $        */
+/*     $OpenBSD: divrem.m4,v 1.5 2015/06/01 19:02:11 miod Exp $        */
 /*     $NetBSD: divrem.m4,v 1.7 1996/10/17 03:08:04 cgd Exp $  */
 
 /*
@@ -57,16 +57,41 @@ ifelse(S, `true', `define(NEG, `t4')')
 
 #include <machine/asm.h>
 
-LEAF(NAME, 0)                                  /* XXX */
+/*
+ * These functions use t11 as an input, which makes them incompatible with
+ * the secureplt calling sequence. The compiler knows about this, and will
+ * ask for a call through a got relocation. But this can only work if the
+ * linker omits creating a plt entry for the symbol. In order to achieve
+ * this, we need to declare it as `notype' instead of `function', which
+ * means that LEAF(NAME, 0) can't be used as it uses .ent which forces the
+ * `function' type.
+ */
+       .globl  NAME
+       .type   NAME, @notype
+       .usepv  NAME, no
+
+       .cfi_startproc
+       .cfi_return_column ra
+NAME:
+       MCOUNT
        lda     sp, -64(sp)
+       .cfi_def_cfa_offset 64
        stq     BIT, 0(sp)
+       .cfi_rel_offset BIT, 0
        stq     I, 8(sp)
+       .cfi_rel_offset I, 8
        stq     CC, 16(sp)
+       .cfi_rel_offset CC, 16
        stq     T_0, 24(sp)
-ifelse(S, `true',
-`      stq     NEG, 32(sp)')
+       .cfi_rel_offset T_0, 24
+ifelse(S, `true',`dnl
+       stq     NEG, 32(sp)
+       .cfi_rel_offset NEG, 32
+')dnl
        stq     A, 40(sp)
+       .cfi_rel_offset A, 40
        stq     B, 48(sp)
+       .cfi_rel_offset B, 48
        mov     zero, RESULT                    /* Initialize result to zero */
 
 ifelse(S, `true',
@@ -177,14 +202,23 @@ ifelse(S, `true',
 ')
 
        ldq     BIT, 0(sp)
+       .cfi_restore BIT
        ldq     I, 8(sp)
+       .cfi_restore I
        ldq     CC, 16(sp)
+       .cfi_restore CC
        ldq     T_0, 24(sp)
-ifelse(S, `true',
-`      ldq     NEG, 32(sp)')
+       .cfi_restore T_0
+ifelse(S, `true',`dnl
+       ldq     NEG, 32(sp)
+       .cfi_restore NEG
+')dnl
        ldq     A, 40(sp)
+       .cfi_restore A
        ldq     B, 48(sp)
+       .cfi_restore B
        lda     sp, 64(sp)
+       .cfi_def_cfa_offset 0
        ret     zero, (t9), 1
 
 Ldotrap:
@@ -195,4 +229,9 @@ ifelse(OP, `div',
 ')
        br      zero, Lret_result
 
-END(NAME)
+/*
+ * For the reasons stated above, we can not use END(NAME) either, as it
+ * expands to .end which requires a matching .ent.
+ */
+       .cfi_endproc
+       .size   NAME, . - NAME