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