Re: older ld converts push with GOTPCRELX into call - is a local guard ok?

Sam James <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Organization Gentoo
Message-ID <[email protected]>
"Dora, Sunil Kumar via Binutils" <[email protected]> writes:

> Hi,
>
> I was debugging rustc segfaults and traced them to GOTPCRELX handling
> in older ld.
>
> Since commit 11c2852449825 (binutils 2.45), gas emits
> R_X86_64_GOTPCRELX for "push foo@GOTPCREL(%rip)". Older ld's
> elf_x86_64_convert_load_reloc() only checks modrm 0x25 (jmp) in the
> 0xff case and treats everything else as call, so a push (modrm 0x35)
> gets silently rewritten to "addr32 call foo". In our case foo is a
> read-only LLVM table statically linked into librustc_driver.so, so
> rustc calls into .rodata and crashes.
>
> Reproducer (two installs on purpose - that mismatch is the bug):
>
>     $ cat repro.s
>         .text
>         .globl  func
>     func:
>         push    tbl@GOTPCREL(%rip)
>         add     $8, %rsp
>         ret
>         .section .rodata
>         .globl  tbl
>         .hidden tbl
>     tbl:
>         .zero   576
>
>     $ as --version | head -1 
>     GNU assembler (GNU Binutils) 2.46.1
>     $ as -o repro.o repro.s
>     $ readelf -rW repro.o | grep tbl
>     0000000000000002  0000000300000029 R_X86_64_GOTPCRELX  0000000000000000 tbl - 4
>
>     $ ld --version | head -1
>     GNU ld (GNU Binutils for Ubuntu) 2.38
>     $ ld -shared -o bad.so repro.o
>     $ objdump -d bad.so | grep -A1 '<func>:'
>     0000000000001000 <func>:
>         1000:       67 e8 fa 0f 00 00       addr32 call 2000 <tbl>
>
>     ld 2.46.1 on the same repro.o keeps "ff 35" (push through GOT).
>     gas 2.38 emits plain GOTPCREL for this source, so only new-gas
>     objects with old ld are affected.
>
> Old branches are closed, I know - but some of our build hosts must
> stay on distro binutils for a while, so we plan to carry this locally
> (skip conversion for anything that isn't call/jmp, matching what newer
> ld does for push in a shared library):

Older branches are not closed. Like glibc, we keep older branches alive
for obvious trivial fixes for as long as people are willing to maintian
them (within reason).

But in fact, not only are they not closed, H.J. already backported fixes
for your exact problem a year ago.

> [...]
>
> 1. Is this guard safe, or can modrm be something other than
>    0x15/0x25/0x35 here that needs different handling?

Use H.J.'s patch?

>
> 2. Worth documenting this incompatibility (PR or release notes)?
>    Every ld before 2.45 silently produces bad code from such objects,
>    and tracing the crash back to the linker was not easy.

There's already https://sourceware.org/PR32991.

>
> Thanks,
> Sunil Dora

sam
signature.asc (application/pgp-signature, 418 B)
-----BEGIN PGP SIGNATURE-----

iQEBBAEWCgCpFiEEJaa7iN2bdkxrVUHCc4QJ9SDfkZAFAmpP90UbFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMiwyXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25z
Lm9wZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQyNUE2QkI4OEREOUI3NjRDNkI1NTQx
QzI3Mzg0MDlGNTIwREY5MTkwDxxzYW1AZ2VudG9vLm9yZwAKCRBzhAn1IN+RkEXc
AQCHAZ92vMeDUBVaTmwwgnJUEWLw1vSBEDiYEXLRYPqdTQD/diccvHFiarheaP06
oJaGISzdItjKR+T4E/qIHA2mqg8=
=oiR3
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.