Bug 1713891 - Impossible to link large object files due to glibc/gcc relocation truncation
Summary: Impossible to link large object files due to glibc/gcc relocation truncation
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: 30
Hardware: x86_64
OS: Linux
unspecified
low
Target Milestone: ---
Assignee: Carlos O'Donell
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2019-05-25 13:10 UTC by Yann Droneaud
Modified: 2019-08-22 16:38 UTC (History)
9 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2019-08-22 16:38:08 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Yann Droneaud 2019-05-25 13:10:16 UTC
On x86_64, I'm not able to link a ~2GiBytes object file into an executable or a shared library.

Using:
- binutils-2.31.1-29.fc30.x86_64
- gcc-9.1.1-1.fc30.x86_64
- glibc-devel-2.29-12.fc30.x86_64

Start by assembling the following code:

  $ cat large.S
          .section .rodata
          .globl large
          .p2align 0
          .type  large, @object
          .size  large, SIZE
  large:
          .zero  SIZE

  $ gcc -DSIZE=$((2**31)) -c -o large.o large.S

Then linking the large object as a shared object fails:

  $ gcc -shared -o liblarge.so large.o
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crti.o: in function `_init':
  (.init+0xb): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `__gmon_start__'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `deregister_tm_clones':
  crtstuff.c:(.text+0x3): relocation truncated to fit: R_X86_64_PC32 against `.tm_clone_table'
  /usr/bin/ld: crtstuff.c:(.text+0xa): relocation truncated to fit: R_X86_64_PC32 against symbol `__TMC_END__' defined in .got.plt section in liblarge.so
  /usr/bin/ld: crtstuff.c:(.text+0x16): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `_ITM_deregisterTMCloneTable'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `register_tm_clones':
  crtstuff.c:(.text+0x33): relocation truncated to fit: R_X86_64_PC32 against `.tm_clone_table'
  /usr/bin/ld: crtstuff.c:(.text+0x3a): relocation truncated to fit: R_X86_64_PC32 against symbol `__TMC_END__' defined in .got.plt section in liblarge.so
  /usr/bin/ld: crtstuff.c:(.text+0x57): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `_ITM_registerTMCloneTable'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `__do_global_dtors_aux':
  crtstuff.c:(.text+0x76): relocation truncated to fit: R_X86_64_PC32 against `.bss'
  /usr/bin/ld: crtstuff.c:(.text+0x81): relocation truncated to fit: R_X86_64_GOTPCREL against symbol `__cxa_finalize@@GLIBC_2.2.5' defined in .text section in //lib64/libc.so.6
  /usr/bin/ld: crtstuff.c:(.text+0x8e): relocation truncated to fit: R_X86_64_PC32 against symbol `__dso_handle' defined in .data.rel.ro.local section in /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o
  /usr/bin/ld: crtstuff.c:(.text+0x9e): additional relocation overflows omitted from the output
  liblarge.so: PC-relative offset overflow in PLT entry for `__cxa_finalize@@GLIBC_2.2.5'
  collect2: error: ld returned 1 exit status

Or linking the large object as an executable fails:

  $ cat main.c
  int main(void)
  {
          return 0;
  }

  $ gcc -c -o main.o main.c

  $ gcc -o large main.o large.o 
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crt1.o: in function `_start':
  (.text+0x2a): relocation truncated to fit: R_X86_64_GOTPCRELX against symbol `__libc_start_main@@GLIBC_2.2.5' defined in .text section in //lib64/libc.so.6
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crt1.o:(.eh_frame+0x20): relocation truncated to fit: R_X86_64_PC32 against `.text'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crt1.o:(.eh_frame+0x50): relocation truncated to fit: R_X86_64_PC32 against `.text'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crti.o: in function `_init':
  (.init+0xb): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `__gmon_start__'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbegin.o: in function `deregister_tm_clones':
  crtstuff.c:(.text+0x7): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbegin.o: in function `register_tm_clones':
  crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbegin.o: in function `__do_global_dtors_aux':
  crtstuff.c:(.text+0x76): relocation truncated to fit: R_X86_64_PC32 against `.bss'
  /usr/bin/ld: crtstuff.c:(.text+0x88): relocation truncated to fit: R_X86_64_PC32 against `.bss'
  /usr/bin/ld: main.o:(.eh_frame+0x20): relocation truncated to fit: R_X86_64_PC32 against `.text'
  /usr/bin/ld: //usr/lib64/libc_nonshared.a(elf-init.oS): in function `__libc_csu_init':
  (.text+0x9): relocation truncated to fit: R_X86_64_PC32 against symbol `__init_array_start' defined in .init_array section in large
  /usr/bin/ld: (.text+0x20): additional relocation overflows omitted from the output
  collect2: error: ld returned 1 exit status

Or linking the large object as an position independent executable (PIE) fails:

  $ gcc -fPIE -c -o main.o main.c

  $ gcc -pie -fPIE -o large main.o large.o 
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/Scrt1.o: in function `_start':
  (.text+0x2a): relocation truncated to fit: R_X86_64_GOTPCRELX against symbol `__libc_start_main@@GLIBC_2.2.5' defined in .text section in //lib64/libc.so.6
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/Scrt1.o:(.eh_frame+0x20): relocation truncated to fit: R_X86_64_PC32 against `.text'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/../../../../lib64/crti.o: in function `_init':
  (.init+0xb): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `__gmon_start__'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `deregister_tm_clones':
  crtstuff.c:(.text+0x3): relocation truncated to fit: R_X86_64_PC32 against `.tm_clone_table'
  /usr/bin/ld: crtstuff.c:(.text+0xa): relocation truncated to fit: R_X86_64_PC32 against symbol `__TMC_END__' defined in .data section in large
  /usr/bin/ld: crtstuff.c:(.text+0x16): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `_ITM_deregisterTMCloneTable'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `register_tm_clones':
  crtstuff.c:(.text+0x33): relocation truncated to fit: R_X86_64_PC32 against `.tm_clone_table'
  /usr/bin/ld: crtstuff.c:(.text+0x3a): relocation truncated to fit: R_X86_64_PC32 against symbol `__TMC_END__' defined in .data section in large
  /usr/bin/ld: crtstuff.c:(.text+0x57): relocation truncated to fit: R_X86_64_REX_GOTPCRELX against undefined symbol `_ITM_registerTMCloneTable'
  /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/9/crtbeginS.o: in function `__do_global_dtors_aux':
  crtstuff.c:(.text+0x76): relocation truncated to fit: R_X86_64_PC32 against `.bss'
  /usr/bin/ld: crtstuff.c:(.text+0x81): additional relocation overflows omitted from the output
  large: PC-relative offset overflow in PLT entry for `__cxa_finalize@@GLIBC_2.2.5'
  collect2: error: ld returned 1 exit status

Perhaps Glibc and GCC runtimes should probably be generated in a way allowing large relocation

(Note: SIZE define can be smaller than 2GiBytes. In particular is has to be anything larger than 2147474944 to trigger the error when building a shared library)

Comment 1 Yann Droneaud 2019-05-25 13:25:44 UTC
(In reply to Yann Droneaud from comment #0)

> Perhaps Glibc and GCC runtimes should probably be generated in a way
> allowing large relocation

I'm thinking about

  -mcmodel=large

      Generate code for the large model. This model makes no assumptions about addresses and sizes of sections.

https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/x86-Options.html#index-mcmodel_003dlarge-3

But the option description for ARMv8 AArch64 scares me a bit:

  -mcmodel=large

      Generate code for the large code model. This makes no assumptions about addresses and sizes of sections. Programs can be statically linked only.

https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/AArch64-Options.html#index-mcmodel_003dlarge

Comment 2 Florian Weimer 2019-05-25 13:51:00 UTC
The x86-64 instruction encoding only offers 32-bit PC-relative addressing.  This is far more than your typical RISC architecture, but it is still a limit that can be reached on today's machines.  -mcmodel=large works around this, at a performance cost, which is why this option is not enabled by default.  I do not think there is a bug here; this is working as designed.

(The AArch64 architecture is very different and has different limitations.)

Comment 3 Carlos O'Donell 2019-08-22 16:38:08 UTC
I'm marking this CLOSED/NOTABUG. There are limits to the size of objects you can link. We would need a strong rationale to support such objects by default by making it possible for the entire runtime to support such large objects.


Note You need to log in before you can comment on or make changes to this bug.