Bug 23968 - GOTPCREL(%rip) references against .local symbols generate invalid code in -mrelax-relocations=no mode (chromium build crashes)
Summary: GOTPCREL(%rip) references against .local symbols generate invalid code in -mr...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.31
: P2 normal
Target Milestone: 2.32
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-09 10:41 UTC by Sergei Trofimovich
Modified: 2018-12-10 12:14 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sergei Trofimovich 2018-12-09 10:41:15 UTC
sultan on freenode/#gentoo-toolchain reported a chromium build failure when CFLAGS=-Wa,-mrelax-relocations=no is used. sultan uses it to have whole system compatible with old binutils without R_X86_64_REX_GOTPCRELX support.

I expored a failure a bit and am not sure if it's a chromium bug or binutils/gas bug. I'm leaning towards binutils/gas. Here is the minimal single-file example:

typedef unsigned char u8;

  /*
    extracted from chromium-71.0.3578.80/work/chromium-71.0.3578.80/out/Release/gen/v8/embedded.cc

    # --enable-x86-relax-relocations
    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=yes a-yes.o -o a-yes
    $ ./a-yes
    42 # works

    # --disable-x86-relax-relocations
    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=no  a-no.o  -o a-no
    $ ./a-no
    <SIGSEGV> # fails
  */

  namespace {

  __asm__(
    ".section .text\n"
    ".local v8_Default_embedded_blob_\n"
    //This would work:
    //".global v8_Default_embedded_blob_\n"
    //".hidden v8_Default_embedded_blob_\n"
    "v8_Default_embedded_blob_:\n"
    // some raw injected data
    ".byte 0x42\n"
  );

  extern "C" const u8 v8_Default_embedded_blob_[];
  }
  const u8* DefaultEmbeddedBlob(void) {
    // generates reference
    //    movq    v8_Default_embedded_blob_@GOTPCREL(%rip), %rax
    // is it valid for .local symbols?
    // If it's invalid should it be forbidden by gas? If it's valid
    // should it always generate a reloc here?
    return v8_Default_embedded_blob_;
  }

  // test main.c:

  #include <stdio.h>
  int main() {
    printf ("b0=%02X\n", DefaultEmbeddedBlob()[0]);
  }

The culprit here is in a mix of .local / @GOTPCREL(%rip) references.

It works for -mrelax-relocations=yes but does not for -mrelax-relocations=no.
Can binutils do the same thing in both cases? I would suggest:
- either generate relocation in both cases
- or forbid @GOTPCREL references against .local symbols and fail the assembly

Investigation notes:

  Assembly file is the same in both cases. Object file difference is the following:

    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=no  -c embedded.o.cc -o a-no.o
    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=yes -c embedded.o.cc -o a-yes.o
    $ objdump -d -r a-no.o  > a-no.od
    $ objdump -d -r a-yes.o > a-yes.od
    $ diff -u a-no.od a-yes.od
     Disassembly of section .text:
    @@ -10,7 +10,8 @@
     0000000000000001 <_Z19DefaultEmbeddedBlobv>:
        1:  55                      push   %rbp
        2:  48 89 e5                mov    %rsp,%rbp
    -   5:  48 8b 05 f4 ff ff ff    mov    -0xc(%rip),%rax        # 0 <v8_Default_embedded_blob_>
    +   5:  48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # c <_Z19DefaultEmbeddedBlobv+0xb>
    +                       8: R_X86_64_REX_GOTPCRELX       v8_Default_embedded_blob_-0x4
        c:  5d                      pop    %rbp
        d:  c3                      retq

  Here 'no' case has extra memory dereference as if '-0xc(%rip)' would be a GOT entry for v8_Default_embedded_blob_. Or 'mov' was used by accident instead of 'lea'.

  Final binary change:

    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=no  a-no.o  -o a-no
    $ x86_64-pc-linux-gnu-g++ -fPIC -O0 -Wa,-mrelax-relocations=yes a-yes.o -o a-yes
    $ objdump -d -R a-no  > a-no.od
    $ objdump -d -R a-yes > a-yes.od
    $ diff -u a-no.od a-yes.od
     Disassembly of section .init:
    @@ -115,7 +115,7 @@
     000000000000064b <_Z19DefaultEmbeddedBlobv>:
      64b:  55                      push   %rbp
      64c:  48 89 e5                mov    %rsp,%rbp
    - 64f:  48 8b 05 f4 ff ff ff    mov    -0xc(%rip),%rax        # 64a <v8_Default_embedded_blob_>
    + 64f:  48 8d 05 f4 ff ff ff    lea    -0xc(%rip),%rax        # 64a <v8_Default_embedded_blob_>
      656:  5d                      pop    %rbp
      657:  c3                      retq

Thanks!
Comment 2 cvs-commit@gcc.gnu.org 2018-12-10 12:10:57 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e771f7a770b07c676958247464962614266da755

commit e771f7a770b07c676958247464962614266da755
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Dec 10 04:08:52 2018 -0800

    Correct gas/ChangeLog entry for PR gas/23968
Comment 3 cvs-commit@gcc.gnu.org 2018-12-10 12:13:31 UTC
The binutils-2_31-branch branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0c362c8126bf3bc54430ce9e8d4b0a19da23bc0b

commit 0c362c8126bf3bc54430ce9e8d4b0a19da23bc0b
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Dec 10 04:08:52 2018 -0800

    Correct gas/ChangeLog entry for PR gas/23968
    
    (cherry picked from commit e771f7a770b07c676958247464962614266da755)
Comment 4 cvs-commit@gcc.gnu.org 2018-12-10 12:14:30 UTC
The binutils-2_30-branch branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c6af0afb3616c2ce5ba2950d17532c6744617c2a

commit c6af0afb3616c2ce5ba2950d17532c6744617c2a
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Dec 10 04:08:52 2018 -0800

    Correct gas/ChangeLog entry for PR gas/23968
    
    (cherry picked from commit e771f7a770b07c676958247464962614266da755)