Hello naddy, about devel/gmp,

After OpenBSD/macppc switched to lld, a text relocation in libgmp.a
began to cause linker errors.  I want to patch devel/gmp's powerpc32
asm to remove this text relocation.  The diff is at the end of this
mail, is this ok?

Charlene pointed me at a build failure in devel/xtensa-lx106-elf/gdb
when it tried to link gdb 8.x with libgmp.a.  I reproduced the
problem with a -static link of this C example:

$ cat divide.c
#include <err.h>
#include <gmp.h>
#include <stdio.h>
int
main(int argc, char **argv) {
        mpz_t x, y;
        if (argc != 3) errx(1, "usage: ./divide x y");
        mpz_init_set_str(x, argv[1], 10);
        mpz_init_set_str(y, argv[2], 10);
        mpz_fdiv_q(x, x, y);
        printf("%s\n", mpz_get_str(NULL, 10, x));
}
$ cc -o divide divide.c $(pkg-config --cflags --libs gmp) -static
ld: error: can't create dynamic relocation R_PPC_ADDR16_HA against local symbol 
in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' 
to allow text relocations in the output
>>> defined in /usr/local/lib/libgmp.a(invert_limb.o)
>>> referenced by tmp-invert_limb.s
>>>               invert_limb.o:(__gmpn_invert_limb) in archive 
>>> /usr/local/lib/libgmp.a

ld: error: can't create dynamic relocation R_PPC_ADDR16_LO against local symbol 
in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' 
to allow text relocations in the output
>>> defined in /usr/local/lib/libgmp.a(invert_limb.o)
>>> referenced by tmp-invert_limb.s
>>>               invert_limb.o:(__gmpn_invert_limb) in archive 
>>> /usr/local/lib/libgmp.a
cc: error: linker command failed with exit code 1 (use -v to see invocation)

The text relocation comes from the m4 macro call LEA(r9, approx_tab)
at WRKSRC/mpn/powerpc32/invert_limb.asm:48.  It tries to embed the
absolute address of approx_tab in the program text, but OpenBSD uses
PIE position-independent executables, so the absolute address isn't
known until runtime.  libgmp.so.* avoids the text relocation by using
the pc-relative address; my patch causes libgmp.a to do the same.

gmp's configure detects that our clang emits position-independent code
by default, and sets the m4 macro PIC_ALWAYS to "yes".  I would want
the asm to check for PIC_ALWAYS and use the pc-relative address, but
in fact, the asm ignores PIC_ALWAYS, because of this faulty check at
WRKSRC/mpn/asm-defs.m4:1054,

ifelse(`PIC_ALWAYS',`yes',`define(`PIC')')

Notice that `PIC_ALWAYS' is in quotes, so the macro PIC_ALWAYS is not
expanded.  This faulty check compares the literal string "PIC_ALWAYS"
with the literal string "yes"; these strings never match, so this
faulty check never defines PIC.  I don't fix this faulty check,
because it might affect other archs.  Instead, I edit the powerpc32
asm to behave as if PIC is always defined.

--George

Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/gmp/Makefile,v
retrieving revision 1.43
diff -u -p -r1.43 Makefile
--- Makefile    17 Nov 2020 21:54:42 -0000      1.43
+++ Makefile    8 Sep 2021 21:21:38 -0000
@@ -4,6 +4,7 @@ COMMENT-main=   library for arbitrary prec
 COMMENT-cxx=   C++ library for arbitrary precision arithmetic
 
 VERSION=       6.2.1
+REVISION-main= 0
 DISTNAME=      gmp-${VERSION}
 MULTI_PACKAGES=        -main -cxx
 PKGNAME-main=  gmp-${VERSION}
Index: patches/patch-mpn_powerpc32_elf_m4
===================================================================
RCS file: patches/patch-mpn_powerpc32_elf_m4
diff -N patches/patch-mpn_powerpc32_elf_m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-mpn_powerpc32_elf_m4  8 Sep 2021 21:21:38 -0000
@@ -0,0 +1,45 @@
+$OpenBSD$
+
+Fix libgmp.a, which doesn't define PIC, but needs the PIC asm, because
+OpenBSD uses PIE position-independent executables.  This prevents text
+relocation errors when ld.lld links gdb >= 8 with libgmp.a.
+
+ld: error: can't create dynamic relocation R_PPC_ADDR16_HA against local 
symbol in readonly segment; recompile object files with -fPIC or pass 
'-Wl,-z,notext' to allow text relocations in the output
+>>> defined in /usr/local/lib/libgmp.a(invert_limb.o)
+>>> referenced by tmp-invert_limb.s
+>>>               invert_limb.o:(__gmpn_invert_limb) in archive 
/usr/local/lib/libgmp.a
+
+Index: mpn/powerpc32/elf.m4
+--- mpn/powerpc32/elf.m4.orig
++++ mpn/powerpc32/elf.m4
+@@ -51,18 +51,14 @@ m4_assert_numargs(1)
+ 
+ define(`LEA',
+ m4_assert_numargs(2)
+-`ifdef(`PIC',`
+-      mflr    r0
++`     mflr    r0
+       bcl     20, 31, 1f
+ 1:    mflr    $1
+       addis   $1, $1, (_GLOBAL_OFFSET_TABLE_-1b)@ha
+       addi    $1, $1, (_GLOBAL_OFFSET_TABLE_-1b)@l
+       mtlr    r0
+       lwz     $1, $2@got($1)
+-',`
+-      lis     $1, $2@ha
+-      la      $1, $2@l($1)
+-')')
++')
+ 
+ 
+ define(`LEAL',
+@@ -89,8 +85,7 @@ m4_assert_numargs(1)
+ 
+ define(`ASM_END', `dnl')
+ 
+-ifdef(`PIC',`
+-define(`PIC_SLOW')')
++define(`PIC_SLOW')
+ 
+ dnl  64-bit "long long" parameters are put in an even-odd pair, skipping an
+ dnl  even register if that was in turn.  I wish somebody could explain why 
that

Reply via email to