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