Hello. GMP is popular library with its own --enable-assembly use. Unfortunately default configuration options allows GMP to provide PIC-incompatible static library. This issue is deadly important for musl. See link https://www.openwall.com/lists/musl/2020/01/29/12. Musl returns segfault for applications trying to do static link against PIC-incompatible static library. Glibc somehow ignores it, but it is broken in the same way. Workarounds like "-fno-pie" and "-static" doesn't looks very good. BTW these workarounds are not compatible with some sanitizers. This issue is very popular. You can find tons of information in google by searching about '--disable-assembly static "gmp"'. GMP authors provided a right solution for this issue silently. We need just to pass "--with-pic" configuration option. Both v6.1 and 6.2 support this option. So please add the following line '$(usex static-libs "--with-pic" "")' into ebuilds: ECONF_SOURCE="${S}" econf \ --localstatedir="${EPREFIX}"/var/state/gmp \ --enable-shared \ $(use_enable asm assembly) \ $(use_enable cxx) \ $(use_enable static-libs static) \ $(usex static-libs "--with-pic" "") Thank you. Reproducible: Always
Please provide an example of a tool/test that breaks in gentoo.
We can use the following test: echo -e \ "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); mpz_clear(a); }" > main.c && \ gcc main.c /usr/lib64/libgmp.a -o main && ./main /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: /usr/lib64/libgmp.a(bdiv_q_1.o): warning: relocation against `__gmp_binvert_limb_table' in read-only section `.text' /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: warning: creating a DT_TEXTREL in object This warning is deadly for musl system, segfault. Glibc somehow is working, but binary is broken too. Please see here https://www.openwall.com/lists/musl/2020/01/29/19. Developers said that it will better to add some link flag that throws error instead of warning. But I can't find this flag: "-Wl,-z,relro,-z,now" doesn't make error from warning.
(In reply to Andrew Aladjev from comment #2) > We can use the following test: > > echo -e \ > "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); > mpz_clear(a); }" > main.c && \ > gcc main.c /usr/lib64/libgmp.a -o main && ./main > > /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ > ld: /usr/lib64/libgmp.a(bdiv_q_1.o): warning: relocation against > `__gmp_binvert_limb_table' in read-only section `.text' > /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ > ld: warning: creating a DT_TEXTREL in object > > This warning is deadly for musl system, segfault. please provide emerge '--info gcc gmp' from systems where you see the crash. It means musl does not support TEXTRELs. It's not a gmp-specific but a wider problem. Instead of SIGSEGVing if feasible musl should report a nice error to build binaries without TEXTRELs. We can add USE=pic to dev-libs/gmp to workaround the musl deficiency. > Glibc somehow is working glibc just performs TEXTREl relocation. > but binary is broken too. What does it mean? > Please see here > https://www.openwall.com/lists/musl/2020/01/29/19. Developers said that it > will better to add some link flag that throws error instead of warning. But > I can't find this flag: "-Wl,-z,relro,-z,now" doesn't make error from > warning. I think you are looking for -Wl,-z,text option (see 'man ld').
> please provide emerge '--info gcc gmp' from systems where you see the crash. Yes, I've uploaded docker images: "puchuu/test_x86_64-pc-linux-gnu" and "puchuu/test_x86_64-gentoo-linux-musl", everybody can reproduce this bug. GMP version is 6.1.2-r1. I will attach emerge info. > It means musl does not support TEXTRELs. It's not a gmp-specific but a wider problem. Instead of SIGSEGVing if feasible musl should report a nice error to build binaries without TEXTRELs. Yes, and not only TEXTREL. Please see this link https://github.com/ifduyue/musl/blob/master/ldso/dynlink.c#L391-L433. Every relocaton type that tryies to write into "reloc_addr" may be broken, because address may be readonly. I will try later to create a patch for musl that returns some reasonable error message like "not supported relocation in readonly mode" before crash. > We can add USE=pic to dev-libs/gmp to workaround the musl deficiency. This will be a good solution, thank you. > glibc just performs TEXTREl relocation. This relocation is a part a readonly segment, glibc may remap this segment as writable, maybe just ignores it. I will investigate glibc source later about this question. > I think you are looking for -Wl,-z,text option (see 'man ld'). Yes, that's it. I've receved "read-only segment has dynamic relocations" error. It may be good to include this flag into any musl profile.
Created attachment 608594 [details] emerge glibc info
Created attachment 608596 [details] emerge musl info
(In reply to Andrew Aladjev from comment #2) > We can use the following test: > > echo -e \ > "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); > mpz_clear(a); }" > main.c && \ > gcc main.c /usr/lib64/libgmp.a -o main && ./main > > /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ > ld: /usr/lib64/libgmp.a(bdiv_q_1.o): warning: relocation against > `__gmp_binvert_limb_table' in read-only section `.text' > /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../x86_64-pc-linux-gnu/bin/ > ld: warning: creating a DT_TEXTREL in object This warning does not happen for me. Your toolchain must be different enough from mine. (In reply to Andrew Aladjev from comment #5) > Created attachment 608594 [details] > emerge glibc info 1. Please provide 'emerge --info sys-devel/gcc dev-libs/gmp'. I'd like to see USE-flags gcc was built with and gcc/gmp versions. gcc somehow generates code it's not supposed to. 2. Please post 'gcc -v' output to make sure. (In reply to Andrew Aladjev from comment #6) > Created attachment 608596 [details] > emerge musl info Same here. Please attach the same [1.] and [2.] above. (In reply to Andrew Aladjev from comment #4) > > I think you are looking for -Wl,-z,text option (see 'man ld'). > > Yes, that's it. I've receved "read-only segment has dynamic relocations" > error. It may be good to include this flag into any musl profile. I suggest filing a separate bug against musl@ to consider it.
Created attachment 609398 [details] emerge gmp gcc info glibc
Created attachment 609400 [details] emerge gmp gcc info musl
Attached emerge -v --info gmp gcc for each container. My containers are super basic, it was compiled with default uses from profiles.
(In reply to Andrew Aladjev from comment #8) > Created attachment 609398 [details] > emerge gmp gcc info glibc I don't see how you can get /usr/lib64/libgmp.a with your gmp USE="-static-libs": > dev-libs/gmp-6.1.2-r1::gentoo was built with the following: > USE="asm cxx -doc -static-libs" Are you sure /usr/lib64/libgmp.a is up to date and not some ancient leftover? (In reply to Andrew Aladjev from comment #10) > Attached emerge -v --info gmp gcc for each container. My containers are > super basic, it was compiled with default uses from profiles. Same here: > dev-libs/gmp-6.1.2-r1::gentoo was built with the following: > USE="asm cxx -doc -static-libs"
> I don't see how you can get /usr/lib64/libgmp.a with your gmp USE="-static-libs" I've just recreated new container from image. It is ok. You can 100% reproduce this error by using the following commands: docker run -it puchuu/test_x86_64-gentoo-linux-musl bash env-update && source /etc/profile echo "dev-libs/gmp static-libs" > /etc/portage/package.use/gmp MAKEOPTS='-j16' emerge -v dev-libs/gmp echo -e \ "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); mpz_clear(a); }" > main.c && \ gcc main.c /usr/lib64/libgmp.a -o main && ./main It will segfault.
(In reply to Andrew Aladjev from comment #12) > > I don't see how you can get /usr/lib64/libgmp.a with your gmp USE="-static-libs" > > I've just recreated new container from image. It is ok. You can 100% > reproduce this error by using the following commands: > > docker run -it puchuu/test_x86_64-gentoo-linux-musl bash > env-update && source /etc/profile > echo "dev-libs/gmp static-libs" > /etc/portage/package.use/gmp > MAKEOPTS='-j16' emerge -v dev-libs/gmp > echo -e \ > "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); > mpz_clear(a); }" > main.c && \ > gcc main.c /usr/lib64/libgmp.a -o main && ./main > > It will segfault. Are you sure? """ # echo -e "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); mpz_clear(a); }" > main.c && gcc main.c /usr/lib64/libgmp.a -o main && ./main gcc: error: /usr/lib64/libgmp.a: No such file or directory """ Which makes sense. musl does not use /usr/lib64/ diretory.
Sorry, please replace lib64 with lib in the sample above. lib64 reproduced warning in glibc container, lib warning and segfault in musl one.
Aha. Finally got the crash and the warning. It looks like the affected version is only gmp-6.1.2, but not gmp-6.2.0 (That's why I kept failing to reproduce it). At a superficial glance TEXTREL comes from a single file: gcd_1.o. The rest of default assembly is TEXTREL-clean. On gmp-6.1.2 it was provided from: gmp-6.1.2-r1/work/gmp-6.1.2/mpn/x86_64/gcd_1.asm That code is probably not TEXTREL-clean. On gmp-6.2.0 the same function is provided by: gmp-6.2.0-r1/work/gmp-6.2.0/mpn/generic/gcd_1.c That code handles TEXTREL as good as gcc can do for you. https://gmplib.org/repo/gmp/rev/f5fc3e7389b4 removed assembly implementations: changeset: 17981:f5fc3e7389b4 user: Torbjorn Granlund <tg@gmplib.org> date: Fri Nov 29 00:53:11 2019 +0100 summary: Remove all gcd_1.asm files. The change does not say why. Probably due to presence of TEXTRELs? Note: ideally --with-pic should not influence TEXTREL cleanliness. All code should be TEXTREL-free. Practically it might not be, but it should be fixed on assembly level if reasonably possible. Specifically --with-pic=pic-only does not fix gmp: # EXTRA_ECONF=--with-pic=pic-only emerge -av1 dev-libs/gmp /usr/lib/gcc/x86_64-gentoo-linux-musl/9.2.0/../../../../x86_64-gentoo-linux-musl/bin/ld: warning: creating a DT_TEXTREL in object TEXTREL does not go away. Thus I suggest using gmp-6.2.0 or USE=-asm.
Fun fact on i686 code still has a few TEXTRELs in addition: # ar x /usr/lib/libgmp.a # LANG=C gcc *.o -o ../main -Wl,--defsym=main=42 /usr/lib/gcc/i686-pc-linux-gnu/9.2.0/../../../../i686-pc-linux-gnu/bin/ld: add_n.o: warning: relocation in read-only section `.text' /usr/lib/gcc/i686-pc-linux-gnu/9.2.0/../../../../i686-pc-linux-gnu/bin/ld: warning: creating a DT_TEXTREL in object sf /tmp/z # scanelf -t ../main TYPE TEXTREL FILE ET_DYN TEXTREL ../main sf /tmp/z # scanelf -T ../main TYPE TEXTRELS FILE main: (memory/data?) [0x1E7E] in (optimized out: previous __gmpn_add_n) [0x1E50] main: (memory/data?) [0x25FF] in (optimized out: previous __gmpn_addmul_1) [0x25A7] main: (memory/data?) [0x41FD] in (optimized out: previous __gmpn_bdiv_q_1) [0x41D0] main: (memory/data?) [0xDB5E] in (optimized out: previous __gmpn_divexact_1) [0xDB30] main: (memory/data?) [0x2D55C] in (optimized out: previous __gmpn_modexact_1_odd) [0x2D540] main: (memory/data?) [0x30931] in (optimized out: previous __gmpn_mul_basecase) [0x30780] main: (memory/data?) [0x403A0] in (optimized out: previous __gmpn_sqr_basecase) [0x40240] main: (memory/data?) [0x4301E] in (optimized out: previous __gmpn_sub_n) [0x42FF0] main: (memory/data?) [0x4319F] in (optimized out: previous __gmpn_submul_1) [0x43147] ET_DYN ../main
--with-pic helps to make both x86_64 and i686 working. The following image "puchuu/test-ruby-lzws_i686-gentoo-linux-musl" was created to test software depends on gmp v6.1.2. We can use the following example: docker run -it --entrypoint bash puchuu/test-ruby-lzws_i686-gentoo-linux-musl env-update && source /etc/profile echo -e \ "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); mpz_clear(a); }" > main.c && \ gcc main.c /usr/lib/libgmp.a -o main && ./main Work good. So please add "pic" use, it can help sometimes.
(In reply to Sergei Trofimovich from comment #15) > Specifically --with-pic=pic-only does not fix gmp: > # EXTRA_ECONF=--with-pic=pic-only emerge -av1 dev-libs/gmp Oh, --with-pic=pic-only is an invalid syntax. --with-pic works, yes.
The bug has been closed via the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=10a57644d5a354baac5d1018fe2dbb34342a14fd commit 10a57644d5a354baac5d1018fe2dbb34342a14fd Author: Sergei Trofimovich <slyfox@gentoo.org> AuthorDate: 2020-01-31 07:56:56 +0000 Commit: Sergei Trofimovich <slyfox@gentoo.org> CommitDate: 2020-01-31 07:57:17 +0000 dev-libs/gmp: add USE=pic for static libraries, bug #707332 gmp makes a decision to use PIC or non-PIC assemply at ./configure time instead of (typical) build time. On top of that non-PIC assembly also has TEXTRELs in it which musl can't handle and crashes binaries at relocation setup time. For gmp is it relevant only for static linking. The change adds USE=pic to force static libraries to generate assembly code without TEXTRELs. Reported-by: Andrew Aladjev Closes: https://bugs.gentoo.org/707332 Package-Manager: Portage-2.3.86, Repoman-2.3.20 Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> dev-libs/gmp/gmp-6.1.2-r1.ebuild | 7 +++++-- dev-libs/gmp/gmp-6.1.2.ebuild | 7 +++++-- dev-libs/gmp/gmp-6.2.0-r1.ebuild | 5 ++++- dev-libs/gmp/gmp-6.2.0.ebuild | 5 ++++- dev-libs/gmp/metadata.xml | 1 + 5 files changed, 19 insertions(+), 6 deletions(-)
(In reply to Andrew Aladjev from comment #17) > --with-pic helps to make both x86_64 and i686 working. The following image > "puchuu/test-ruby-lzws_i686-gentoo-linux-musl" was created to test software > depends on gmp v6.1.2. We can use the following example: > > docker run -it --entrypoint bash puchuu/test-ruby-lzws_i686-gentoo-linux-musl > env-update && source /etc/profile > echo -e \ > "#include <gmp.h>\n void main () { mpz_t a; mpz_init(a); mpz_mul(a, a, a); > mpz_clear(a); }" > main.c && \ > gcc main.c /usr/lib/libgmp.a -o main && ./main > > Work good. So please add "pic" use, it can help sometimes. In future please void posting docker scenarios and actually attach patches to the ebuilds/envidonment you do.