Bug 16945 - [Gold] Executable with -fpie and -mcmodel=large gives segfault on start
Summary: [Gold] Executable with -fpie and -mcmodel=large gives segfault on start
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.25
: P2 normal
Target Milestone: 2.24
Assignee: Ian Lance Taylor
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-14 20:47 UTC by Alexander Ivchenko
Modified: 2014-05-27 20:18 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 Alexander Ivchenko 2014-05-14 20:47:09 UTC
> cat mcmodel_large.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  fprintf(stdout, "Hello\n");
  return 0;
}


> g++ -g -O0 -B/gold/.. mcmodel_large.c -fpic -mcmodel=large -o gold.out
> ./gold.out
Segmentation fault


The disassembler:
int main()
{
4005da:       55                      push   %rbp
4005db:       48 89 e5                mov    %rsp,%rbp
4005de:       53                      push   %rbx                                                                                                                            4005df:       48 83 ec 08             sub    $0x8,%rsp
4005e3:       48 8d 1d f9 ff ff ff    lea    -0x7(%rip),%rbx  # 4005e3<main+0x9>
4005ea:       49 bb fd 13 00 00 00    movabs $0x13fd,%r11
4005f1:       00 00 00
4005f4:       4c 01 db                add    %r11,%rbx
  fprintf(stdout, "Hello\n");                                                                                                                                             4005f7:       48 b8 f8 ff ff ff 00    movabs $0xfffffff8,%rax
4005fe:       00 00 00                                                                                                                                                  400601:       48 8b 04 03             mov    (%rbx,%rax,1),%rax <<< SEGFAULT
400605:       48 8b 00                mov    (%rax),%rax
400608:       48 89 c1                mov    %rax,%rcx
40060b:       ba 06 00 00 00          mov    $0x6,%edx                                                                                                                  400610:       be 01 00 00 00          mov    $0x1,%esi
400615:       48 b8 10 ed ff ff ff    movabs $0xffffffffffffed10,%rax                                                                                                   40061c:       ff ff ff
40061f:       48 8d 3c 03             lea    (%rbx,%rax,1),%rdi
400623:       48 b8 f0 ea ff ff ff    movabs $0xffffffffffffeaf0,%rax
40062a:       ff ff ff
40062d:       48 01 d8                add    %rbx,%rax
400630:       ff d0                   callq  *%rax
  return 0;
400632:       b8 00 00 00 00          mov    $0x0,%eax
}


Addendum in instruction at 4005f7 is wrong..
Comment 1 Alexander Ivchenko 2014-05-15 14:01:42 UTC
Here is where 32 bit $0xfffffff8 came from:

x86_64.cc:3329 for R_X86_64_GOT64:
------
  bool have_got_offset = false;
  unsigned int got_offset = 0;
  switch (r_type)
    {
    case elfcpp::R_X86_64_GOT32:
    case elfcpp::R_X86_64_GOT64:
    case elfcpp::R_X86_64_GOTPLT64:
    case elfcpp::R_X86_64_GOTPCREL:
    case elfcpp::R_X86_64_GOTPCREL64:
      if (gsym != NULL)
        {
          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
          got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
        }
------

Why is got_offset an unsigned int? Sometimes it is section_offset_type and sometimes it is unsigned int..

Although, changing it to section_offset_type didn't help.
Comment 2 H.J. Lu 2014-05-15 17:33:00 UTC
A patch is posted at

https://sourceware.org/ml/binutils/2014-05/msg00130.html
Comment 3 Sourceware Commits 2014-05-27 20:17:41 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, binutils-2_24-branch has been updated
       via  58a19a05d4e88b74e17cfae6f1c1c5c5e7be1537 (commit)
      from  c6badce4c1a34cdbd7384381ff99bffef7506044 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit 58a19a05d4e88b74e17cfae6f1c1c5c5e7be1537
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue May 27 12:19:33 2014 -0700

    Properly handle 64-bit GOT relocations
    
    This patch fixes 2 issues:
    
    1. Since the GOT offset is always negative, we need to use signed int
    to support 64-bit GOT relocations.
    2. R_X86_64_PLTOFF64 uses the address of GLOBAL_OFFSET_TABLE, which is
    the address of the .got.plt section, not the .got section.
    
    	PR gold/16945
    	* x86_64.cc (Target_x86_64::Relocate::relocate): Use signed int
    	for got_offset.  Properly get GOT address for R_X86_64_PLTOFF64.

-----------------------------------------------------------------------

Summary of changes:
 gold/ChangeLog |    6 ++++++
 gold/x86_64.cc |    7 +++++--
 2 files changed, 11 insertions(+), 2 deletions(-)
Comment 4 H.J. Lu 2014-05-27 20:18:38 UTC
Fixed.