[hjl@gnu-tools-1 got-4]$ cat x.S .data .type bar, @object bar: .byte 1 .size bar, .-bar .globl foo .type foo, @object foo: .byte 1 .size foo, .-foo .text .globl _start .type _start, @function _start: movl $0, bar@GOT movl $0, foo@GOT [hjl@gnu-tools-1 got-4]$ make LD=ld gcc -B./ -m32 -fno-lto -c -o x.o x.S ld -m elf_i386 -o x x.o ./objdump -dwr x x: file format elf32-i386 Disassembly of section .text: 08048074 <_start>: 8048074: c7 05 f8 ff ff ff 00 00 00 00 movl $0x0,0xfffffff8 804807e: c7 05 fc ff ff ff 00 00 00 00 movl $0x0,0xfffffffc [hjl@gnu-tools-1 got-4]$ bar@GOT should be the memory address, not the offset from GOT base.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=74d7f0aa5b1e27da215349fb32337e1d83aca7d7 commit 74d7f0aa5b1e27da215349fb32337e1d83aca7d7 Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Jun 11 20:44:24 2016 -0700 Subtract GOT base only with a base register When relocating R_386_GOT32 in "op $0, bar@GOT", we shouldn't subtract GOT base without a base register and we should disallow it without a base register for PIC. bfd/ PR ld/20244 * elf32-i386.c (elf_i386_relocate_section): When relocating R_386_GOT32, return error without a base register for PIC and subtract the .got.plt section address only with a base register. ld/ PR ld/20244 * testsuite/ld-i386/i386.exp: Run pr20244-1a and pr20244-1b. * testsuite/ld-i386/pr20244-1.s: New file. * testsuite/ld-i386/pr20244-1a.d: Likewise. * testsuite/ld-i386/pr20244-1b.d: Likewise. * testsuite/ld-i386/pr20244-1c.d: Likewise.
Fixed for trunk so far.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=712ec27916b5604d29d928dec060fd1ba0fd9edb commit 712ec27916b5604d29d928dec060fd1ba0fd9edb Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon Jun 13 11:06:10 2016 -0700 Add the GOT base for GOT32 relocs against IFUNC Add the GOT base for R_386_GOT32/R_386_GOT32X relocations against IFUNC symbols if there is no base register and disallow them for PIC. bfd/ PR ld/20244 * elf32-i386.c (elf_i386_relocate_section): Add the .got.plt section address for R_386_GOT32/R_386_GOT32X relocations against IFUNC symbols if there is no base register and return error for PIC. ld/ PR ld/20244 * testsuite/ld-i386/i386.exp: Run pr20244-2a, pr20244-2b, pr20244-2c and pr20244-2d. * testsuite/ld-i386/no-plt.exp: Run pr20244-3a and pr20244-3b. * testsuite/ld-i386/pr20244-2.s: New file. * testsuite/ld-i386/pr20244-2a.d: Likewise. * testsuite/ld-i386/pr20244-2b.d: Likewise. * testsuite/ld-i386/pr20244-2c.d: Likewise. * testsuite/ld-i386/pr20244-2d.d: Likewise. * testsuite/ld-i386/pr20244-3a.c: Likewise. * testsuite/ld-i386/pr20244-3b.S: Likewise. * testsuite/ld-i386/pr20244-3c.S: Likewise. * testsuite/ld-i386/pr20244-3d.S: Likewise.
The binutils-2_26-branch branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9983f9d2d44dc6380671006f1d1cdea00587ccd6 commit 9983f9d2d44dc6380671006f1d1cdea00587ccd6 Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Jun 11 20:44:24 2016 -0700 Subtract GOT base only with a base register When relocating R_386_GOT32 in "op $0, bar@GOT", we shouldn't subtract GOT base without a base register and we should disallow it without a base register for PIC. bfd/ PR ld/20244 * elf32-i386.c (elf_i386_relocate_section): When relocating R_386_GOT32, return error without a base register for PIC and subtract the .got.plt section address only with a base register. ld/ PR ld/20244 * testsuite/ld-i386/i386.exp: Run pr20244-1a and pr20244-1b. * testsuite/ld-i386/pr20244-1.s: New file. * testsuite/ld-i386/pr20244-1a.d: Likewise. * testsuite/ld-i386/pr20244-1b.d: Likewise. * testsuite/ld-i386/pr20244-1c.d: Likewise.
The binutils-2_26-branch branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3cac3e2e8b3c2d70467ac14c07f78bf3088c2e42 commit 3cac3e2e8b3c2d70467ac14c07f78bf3088c2e42 Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon Jun 13 09:27:12 2016 -0700 Add the GOT base for GOT32 relocs against IFUNC Add the GOT base for R_386_GOT32/R_386_GOT32X relocations against IFUNC symbols if there is no base register and disallow them for PIC. bfd/ PR ld/20244 * elf32-i386.c (elf_i386_relocate_section): Add the .got.plt section address for R_386_GOT32/R_386_GOT32X relocations against IFUNC symbols if there is no base register and return error for PIC. * elf32-i386.c (elf_i386_relocate_section): Simplify IFUNC GOT32 adjustment for static executables. ld/ PR ld/20244 * testsuite/ld-i386/i386.exp: Run pr20244-2a, pr20244-2b, pr20244-2c and pr20244-2d. * testsuite/ld-i386/no-plt.exp: Run pr20244-3a and pr20244-3b. * testsuite/ld-i386/pr20244-2.s: New file. * testsuite/ld-i386/pr20244-2a.d: Likewise. * testsuite/ld-i386/pr20244-2b.d: Likewise. * testsuite/ld-i386/pr20244-2c.d: Likewise. * testsuite/ld-i386/pr20244-2d.d: Likewise. * testsuite/ld-i386/pr20244-3a.c: Likewise. * testsuite/ld-i386/pr20244-3b.S: Likewise. * testsuite/ld-i386/pr20244-3c.S: Likewise. * testsuite/ld-i386/pr20244-3d.S: Likewise. Add 2 i386 tests to call IFUNC functions via GOT ld/ * testsuite/ld-i386/i386.exp: Run ifunc-1a and ifunc-1b. * testsuite/ld-i386/ifunc-1a.c: New file. * testsuite/ld-i386/ifunc-1b.S: Likewise. * testsuite/ld-i386/ifunc-1c.S: Likewise. * testsuite/ld-i386/ifunc-1d.S: Likewise.
Fixed for 2.26 and 2.27.
Hi. It looks like this change breaks the Oracle 12.1 client installation. While trying to install the 32-bit Oracle client on a 64-bit SUSE SLES 12 SP2 machine, we got [...]/ld: [...]/product/121/lib/libnls12.a(lxecg2e.o): direct GOT relocation R_386_GOT32 against `lxecerr' without base register can not be used when making a shared object After replacing GNU ld version "GNU ld (GNU Binutils; SUSE Linux Enterprise 12) 2.26.1" with the "GNU ld (GNU Binutils; SUSE Linux Enterprise 11) 2.21.1" version from an older SLES machine, the Oracle client installation worked fine. Any idea what the heck Oracle is doing wrong in creating the object files for archives like libnls12.a? (These archives have file modification dates from 2014, so they’re not build during installation.) Kind Regards, Dopıng
(In reply to Dopıng from comment #7) > Hi. > > It looks like this change breaks the Oracle 12.1 client installation. While > trying to install the 32-bit Oracle client on a 64-bit SUSE SLES 12 SP2 > machine, we got > > [...]/ld: [...]/product/121/lib/libnls12.a(lxecg2e.o): direct GOT relocation > R_386_GOT32 against `lxecerr' without base register can not be used when > making a shared object > > After replacing GNU ld version "GNU ld (GNU Binutils; SUSE Linux Enterprise > 12) 2.26.1" with the "GNU ld (GNU Binutils; SUSE Linux Enterprise 11) > 2.21.1" version from an older SLES machine, the Oracle client installation > worked fine. > > Any idea what the heck Oracle is doing wrong in creating the object files > for archives like libnls12.a? (These archives have file modification dates > from 2014, so they’re not build during installation.) lxecg2e.o contains something like [hjl@gnu-17 tmp]$ cat x.s .globl bar .type bar, @function bar: movl foo@GOT, %ecx movl (%ecx), %eax ret [hjl@gnu-17 tmp]$ /usr/bin/as --32 -o x.o x.s [hjl@gnu-17 tmp]$ ld -shared -m elf_i386 x.o ld: x.o: direct GOT relocation R_386_GOT32 against `foo' without base register can not be used when making a shared object ld: final link failed: Bad value [hjl@gnu-17 tmp]$ The problem is that since linker doesn't know where the GOT base is at run-time, it can't properly resolve R_386_GOT32.
(In reply to H.J. Lu from comment #8) > [...] > The problem is that since linker doesn't know where the GOT base is at run-time, > it can't properly resolve R_386_GOT32. Unfortunately, my knowledge of binary file internals like the global offset table is rather limited. I know that stuff like compiling without -fpic and then trying to build a shared library is not the best of ideas, but I’ve never had any GOT-related problems before. Do you have any idea what compiler option Oracle might have used incorrectly that caused this code? What I don’t get is why the older GNU ld seems to link these objects files into a shared library just fine. If that’s the case, the older ld must have a way to properly deal with these assembly instructions, right?
(In reply to Dopıng from comment #9) > (In reply to H.J. Lu from comment #8) > > [...] > > The problem is that since linker doesn't know where the GOT base is at run-time, > > it can't properly resolve R_386_GOT32. > > Unfortunately, my knowledge of binary file internals like the global offset > table is rather limited. I know that stuff like compiling without -fpic and > then trying to build a shared library is not the best of ideas, but I’ve > never had any GOT-related problems before. Without -fpic is OK. The problem is GOT reference without the base register. You can use "objdump -dwr" to see what the code is doing. > Do you have any idea what compiler option Oracle might have used incorrectly > that caused this code? I have no idea. > What I don’t get is why the older GNU ld seems to link these objects files > into a shared library just fine. If that’s the case, the older ld must have > a way to properly deal with these assembly instructions, right? The old linker will silently generate broken output.
(In reply to H.J. Lu from comment #10) > > What I don’t get is why the older GNU ld seems to link these objects files > > into a shared library just fine. If that’s the case, the older ld must have > > a way to properly deal with these assembly instructions, right? > > The old linker will silently generate broken output. Hmm. Broken as in ”will probably cause a SIGSEGV or SIGBUS“, or less broken? 😉 I’m wondering why nobody noticed this problem before. Is it possible that the problematic instructions belong to dead code, e.g. are part of a function that’s (almost) never called, part of a (faulty) generated exception handler, ...? Or did you find these instructions all over the place in the Oracle object files?
(In reply to Dopıng from comment #11) > (In reply to H.J. Lu from comment #10) > > > What I don’t get is why the older GNU ld seems to link these objects files > > > into a shared library just fine. If that’s the case, the older ld must have > > > a way to properly deal with these assembly instructions, right? > > > > The old linker will silently generate broken output. > Hmm. Broken as in ”will probably cause a SIGSEGV or SIGBUS“, or less broken? > 😉 > I’m wondering why nobody noticed this problem before. Is it possible that > the problematic instructions belong to dead code, e.g. are part of a > function that’s (almost) never called, part of a (faulty) generated > exception handler, ...? Or did you find these instructions all over the > place in the Oracle object files? I don't think that piece of code is executed.
My assembler knowledge is rusty, that much is certain... Excerpts from the output of “objdump -dwr lxecg2e.o”: 00000010 <lxecg2e>: 10: 66 90 xchg %ax,%ax 12: 53 push %ebx 13: 8b dc mov %esp,%ebx 15: 83 e4 f0 and $0xfffffff0,%esp 18: 55 push %ebp 19: 55 push %ebp 1a: 8b 6b 04 mov 0x4(%ebx),%ebp 1d: 89 6c 24 04 mov %ebp,0x4(%esp) 21: 8b ec mov %esp,%ebp 23: 81 ec 08 04 00 00 sub $0x408,%esp 29: 89 9d f8 fb ff ff mov %ebx,-0x408(%ebp) 2f: 89 7d f8 mov %edi,-0x8(%ebp) 32: e8 00 00 00 00 call 37 <lxecg2e+0x27> 37: 5f pop %edi 38: 8d bf 03 00 00 00 lea 0x3(%edi),%edi 3a: R_386_GOTPC _GLOBAL_OFFSET_TABLE_ 3e: 8b 53 08 mov 0x8(%ebx),%edx 41: 89 75 fc mov %esi,-0x4(%ebp) 44: 8d 75 e0 lea -0x20(%ebp),%esi 47: 89 75 f4 mov %esi,-0xc(%ebp) 4a: 0f b7 42 30 movzwl 0x30(%edx),%eax 4e: 85 c0 test %eax,%eax 50: 8b 8f 00 00 00 00 mov 0x0(%edi),%ecx 52: R_386_GOT32 lxetbn 56: 8b 0c 81 mov (%ecx,%eax,4),%ecx 59: 89 4d f0 mov %ecx,-0x10(%ebp) 5c: 75 19 jne 77 <lxecg2e+0x67> [...] 76: c3 ret 77: 8b 43 18 mov 0x18(%ebx),%eax 7a: 8d b5 08 fc ff ff lea -0x3f8(%ebp),%esi 80: 68 1c 02 00 00 push $0x21c 85: 52 push %edx 86: 56 push %esi 87: c7 00 ff ff ff ff movl $0xffffffff,(%eax) 8d: 8b df mov %edi,%ebx 8f: e8 fc ff ff ff call 90 <lxecg2e+0x80> 90: R_386_PLT32 _intel_fast_memcpy 94: 8b 9d f8 fb ff ff mov -0x408(%ebp),%ebx 9a: 8b 53 1c mov 0x1c(%ebx),%edx 9d: 33 c0 xor %eax,%eax 9f: 52 push %edx a0: 66 89 85 38 fc ff ff mov %ax,-0x3c8(%ebp) a7: 8d 85 2c ff ff ff lea -0xd4(%ebp),%eax ad: 8b 0a mov (%edx),%ecx af: 8d 15 00 00 00 00 lea 0x0,%edx b1: R_386_GOT32 lxecerr [...] That last line is the only reference to ‘lxecerr’. If the JNE at 5c only jumps in case of an error condition, the remaining code may never get executed. But that’s quite a lot of code up to 8b4 (including six setjmp() calls, but no longjmp() call, so this code doesn’t smell like an error handler IMHO). “ar x libnls12.a ; objdump -dwr *.o | egrep 'lea.*R_386_GOT32' | wc -l” prints 439. Does that grep make sense or would I need to grep for something else? How would the correct lea instruction look like?
(In reply to Dopıng from comment #13) > My assembler knowledge is rusty, that much is certain... > a0: 66 89 85 38 fc ff ff mov %ax,-0x3c8(%ebp) > a7: 8d 85 2c ff ff ff lea -0xd4(%ebp),%eax > ad: 8b 0a mov (%edx),%ecx > af: 8d 15 00 00 00 00 lea 0x0,%edx b1: R_386_GOT32 lxecerr > [...] > What are insns after "lea"?
(In reply to H.J. Lu from comment #14) > What are insns after "lea"? af: 8d 15 00 00 00 00 lea 0x0,%edx b1: R_386_GOT32 lxecerr b5: ff 31 pushl (%ecx) b7: 50 push %eax b8: ff 34 17 pushl (%edi,%edx,1) bb: 56 push %esi bc: 8d b5 58 fe ff ff lea -0x1a8(%ebp),%esi c2: 56 push %esi c3: 8b df mov %edi,%ebx c5: e8 fc ff ff ff call c6 <lxecg2e+0xb6> c6: R_386_PLT32 ldxnbeg ca: 8b 9d f8 fb ff ff mov -0x408(%ebp),%ebx d0: 83 c4 24 add $0x24,%esp d3: 8b 43 14 mov 0x14(%ebx),%eax d6: 83 f8 01 cmp $0x1,%eax d9: 0f 85 e9 02 00 00 jne 3c8 <lxecg2e+0x3b8> df: 8d 85 2c ff ff ff lea -0xd4(%ebp),%eax e5: 50 push %eax e6: 8b df mov %edi,%ebx e8: e8 fc ff ff ff call e9 <lxecg2e+0xd9> e9: R_386_PLT32 _setjmp ed: 8b 9d f8 fb ff ff mov -0x408(%ebp),%ebx f3: 83 c4 04 add $0x4,%esp f6: 85 c0 test %eax,%eax f8: 0f 85 d4 00 00 00 jne 1d2 <lxecg2e+0x1c2> fe: e8 00 00 00 00 call 103 <lxecg2e+0xf3> 103: 5e pop %esi 104: 8d 45 d4 lea -0x2c(%ebp),%eax 107: 50 push %eax 108: ff 73 10 pushl 0x10(%ebx) [...]
Created attachment 9831 [details] Disassembly + relocation section of lxecg2e.o I’ve attached the complete disassembly and relocation section of lxecg2e.o.
(In reply to Dopıng from comment #16) > Created attachment 9831 [details] > Disassembly + relocation section of lxecg2e.o > > I’ve attached the complete disassembly and relocation section of lxecg2e.o. I opened: https://sourceware.org/bugzilla/show_bug.cgi?id=21168
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a5def14f1ca70e14d9433cb229c9369fa3051598 commit a5def14f1ca70e14d9433cb229c9369fa3051598 Author: H.J. Lu <hjl.tools@gmail.com> Date: Wed Feb 15 10:55:51 2017 -0800 Add a test for R_386_GOT32/R_386_GOT32X IFUNC reloc error bfd/ PR ld/20244 * elf32-i386.c (elf_i386_relocate_section): Properly get IFUNC symbol name when reporting R_386_GOT32/R_386_GOT32X relocation error against local IFUNC symbol without a base register for PIC. ld/ PR ld/20244 * testsuite/ld-i386/i386.exp: Run pr20244-4a, pr20244-4b and pr20244-4c. * testsuite/ld-i386/pr20244-4.s: New file. * testsuite/ld-i386/pr20244-4a.d: Likewise. * testsuite/ld-i386/pr20244-4b.d: Likewise. * testsuite/ld-i386/pr20244-4c.d: Likewise.