diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index 48f17718365e2..b778b9aa9d28f 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -388,6 +388,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s, case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_REX2_GOTPCRELX: case R_X86_64_GOTTPOFF: return R_GOT_PC; case R_X86_64_GOTOFF64: @@ -725,6 +726,7 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const { case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_REX2_GOTPCRELX: case R_X86_64_PC32: case R_X86_64_GOTTPOFF: case R_X86_64_PLT32: @@ -808,6 +810,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { break; case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_REX2_GOTPCRELX: if (rel.expr != R_GOT_PC) { relaxGot(loc, rel, val); } else { @@ -859,12 +862,13 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend, const uint8_t *loc) const { - // Only R_X86_64_[REX_]GOTPCRELX can be relaxed. GNU as may emit GOTPCRELX - // with addend != -4. Such an instruction does not load the full GOT entry, so - // we cannot relax the relocation. E.g. movl x@GOTPCREL+4(%rip), %rax - // (addend=0) loads the high 32 bits of the GOT entry. + // Only R_X86_64_[REX_]|[REX2_]GOTPCRELX can be relaxed. GNU as may emit + // GOTPCRELX with addend != -4. Such an instruction does not load the full GOT + // entry, so we cannot relax the relocation. E.g. movl x@GOTPCREL+4(%rip), + // %rax (addend=0) loads the high 32 bits of the GOT entry. if (!ctx.arg.relax || addend != -4 || - (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX)) + (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX && + type != R_X86_64_REX2_GOTPCRELX)) return R_GOT_PC; const uint8_t op = loc[-2]; const uint8_t modRm = loc[-1]; @@ -880,7 +884,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend, if (op == 0xff && (modRm == 0x15 || modRm == 0x25)) return R_RELAX_GOT_PC; - // We don't support test/binop instructions without a REX prefix. + // We don't support test/binop instructions without a REX/REX2 prefix. if (type == R_X86_64_GOTPCRELX) return R_GOT_PC; @@ -894,8 +898,8 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend, // "Intel 64 and IA-32 Architectures Software Developer's Manual V2" // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) -static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, - uint8_t modRm) { +static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, uint8_t modRm, + bool isRex2) { const uint8_t rex = loc[-3]; // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg". if (op == 0x85) { @@ -921,7 +925,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, // See "TEST-Logical Compare" (4-428 Vol. 2B). loc[-2] = 0xf7; - // Move R bit to the B bit in REX byte. + // Move R bit to the B bit in REX/REX2 byte. // REX byte is encoded as 0100WRXB, where // 0100 is 4bit fixed pattern. // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the @@ -932,7 +936,17 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, // REX.B This 1-bit value is an extension to the MODRM.rm field or the // SIB.base field. // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A). - loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; + // + // REX2 prefix is encoded as 0xd5|M|R2|X2|B2|WRXB, where + // 0xd5 is 1byte fixed pattern. + // REX2's [W,R,X,B] have the same meanings as REX's. + // REX2.M encodes the map id. + // R2/X2/B2 provides the fifth and most siginicant bits of the R/X/B + // register identifiers, each of which can now address all 32 GPRs. + if (isRex2) + loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2; + else + loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; write32le(loc, val); return; } @@ -953,7 +967,10 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for // descriptions about each operation. loc[-2] = 0x81; - loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; + if (isRex2) + loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2; + else + loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; write32le(loc, val); } @@ -974,7 +991,7 @@ static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) { // We are relaxing a rip relative to an absolute, so compensate // for the old -4 addend. assert(!ctx.arg.isPic); - relaxGotNoPic(loc, val + 4, op, modRm); + relaxGotNoPic(loc, val + 4, op, modRm, rel.type == R_X86_64_REX2_GOTPCRELX); return; } diff --git a/lld/test/ELF/x86-64-gotpc-no-relax-err.s b/lld/test/ELF/x86-64-gotpc-no-relax-err.s index 618dca47755f4..4280c8fd1dc97 100644 --- a/lld/test/ELF/x86-64-gotpc-no-relax-err.s +++ b/lld/test/ELF/x86-64-gotpc-no-relax-err.s @@ -7,15 +7,19 @@ ## `>>> defined in` for linker synthesized __stop_* symbols (there is no ## associated file or linker script line number). -# CHECK: error: {{.*}}:(.text+0x2): relocation R_X86_64_GOTPCRELX out of range: 2147483658 is not in [-2147483648, 2147483647]; references '__stop_data' +# CHECK: error: {{.*}}:(.text+0x2): relocation R_X86_64_GOTPCRELX out of range: 2147483666 is not in [-2147483648, 2147483647]; references '__stop_data' # CHECK-NEXT: >>> defined in # CHECK-EMPTY: -# CHECK-NEXT: error: {{.*}}:(.text+0x9): relocation R_X86_64_REX_GOTPCRELX out of range: 2147483651 is not in [-2147483648, 2147483647]; references '__stop_data' +# CHECK-NEXT: error: {{.*}}:(.text+0x9): relocation R_X86_64_REX_GOTPCRELX out of range: 2147483659 is not in [-2147483648, 2147483647]; references '__stop_data' +# CHECK-NEXT: >>> defined in +# CHECK-EMPTY: +# CHECK-NEXT: error: {{.*}}:(.text+0x11): relocation R_X86_64_REX2_GOTPCRELX out of range: 2147483651 is not in [-2147483648, 2147483647]; references '__stop_data' # CHECK-NEXT: >>> defined in #--- a.s movl __stop_data@GOTPCREL(%rip), %eax # out of range movq __stop_data@GOTPCREL(%rip), %rax # out of range + movq __stop_data@GOTPCREL(%rip), %r16 # out of range movq __stop_data@GOTPCREL(%rip), %rax # in range .section data,"aw",@progbits @@ -23,5 +27,5 @@ #--- lds SECTIONS { .text 0x200000 : { *(.text) } - .got 0x80200010 : { *(.got) } + .got 0x80200016 : { *(.got) } } diff --git a/lld/test/ELF/x86-64-gotpc-relax-nopic.s b/lld/test/ELF/x86-64-gotpc-relax-nopic.s index 7481904d16f1b..e3cd93d1d5796 100644 --- a/lld/test/ELF/x86-64-gotpc-relax-nopic.s +++ b/lld/test/ELF/x86-64-gotpc-relax-nopic.s @@ -10,30 +10,39 @@ # SYMRELOC: Symbols [ # SYMRELOC: Symbol { # SYMRELOC: Name: bar -# SYMRELOC-NEXT: Value: 0x203248 +# SYMRELOC-NEXT: Value: 0x203290 ## 2105751 = 0x202197 (bar) # DISASM: Disassembly of section .text: # DISASM-EMPTY: # DISASM-NEXT: <_start>: -# DISASM-NEXT: 2011c8: adcl {{.*}}(%rip), %eax # 0x202240 -# DISASM-NEXT: addl {{.*}}(%rip), %ebx # 0x202240 -# DISASM-NEXT: andl {{.*}}(%rip), %ecx # 0x202240 -# DISASM-NEXT: cmpl {{.*}}(%rip), %edx # 0x202240 -# DISASM-NEXT: orl {{.*}}(%rip), %edi # 0x202240 -# DISASM-NEXT: sbbl {{.*}}(%rip), %esi # 0x202240 -# DISASM-NEXT: subl {{.*}}(%rip), %ebp # 0x202240 -# DISASM-NEXT: xorl $0x203248, %r8d -# DISASM-NEXT: testl $0x203248, %r15d -# DISASM-NEXT: 201200: adcq $0x203248, %rax -# DISASM-NEXT: addq $0x203248, %rbx -# DISASM-NEXT: andq $0x203248, %rcx -# DISASM-NEXT: cmpq $0x203248, %rdx -# DISASM-NEXT: orq $0x203248, %rdi -# DISASM-NEXT: sbbq $0x203248, %rsi -# DISASM-NEXT: subq $0x203248, %rbp -# DISASM-NEXT: xorq $0x203248, %r8 -# DISASM-NEXT: testq $0x203248, %r15 +# DISASM-NEXT: 2011c8: adcl {{.*}}(%rip), %eax # 0x202288 +# DISASM-NEXT: addl {{.*}}(%rip), %ebx # 0x202288 +# DISASM-NEXT: andl {{.*}}(%rip), %ecx # 0x202288 +# DISASM-NEXT: cmpl {{.*}}(%rip), %edx # 0x202288 +# DISASM-NEXT: orl {{.*}}(%rip), %edi # 0x202288 +# DISASM-NEXT: sbbl {{.*}}(%rip), %esi # 0x202288 +# DISASM-NEXT: subl {{.*}}(%rip), %ebp # 0x202288 +# DISASM-NEXT: xorl $0x203290, %r8d +# DISASM-NEXT: testl $0x203290, %r15d +# DISASM-NEXT: 201200: adcq $0x203290, %rax +# DISASM-NEXT: addq $0x203290, %rbx +# DISASM-NEXT: andq $0x203290, %rcx +# DISASM-NEXT: cmpq $0x203290, %rdx +# DISASM-NEXT: orq $0x203290, %rdi +# DISASM-NEXT: sbbq $0x203290, %rsi +# DISASM-NEXT: subq $0x203290, %rbp +# DISASM-NEXT: xorq $0x203290, %r8 +# DISASM-NEXT: testq $0x203290, %r15 +# DISASM-NEXT: 20123f: adcq $0x203290, %r16 +# DISASM-NEXT: addq $0x203290, %r17 +# DISASM-NEXT: andq $0x203290, %r18 +# DISASM-NEXT: cmpq $0x203290, %r19 +# DISASM-NEXT: orq $0x203290, %r20 +# DISASM-NEXT: sbbq $0x203290, %r21 +# DISASM-NEXT: subq $0x203290, %r22 +# DISASM-NEXT: xorq $0x203290, %r23 +# DISASM-NEXT: testq $0x203290, %r24 # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t2 # RUN: llvm-readobj -S -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s @@ -46,8 +55,8 @@ # SEC-PIC-NEXT: SHF_ALLOC # SEC-PIC-NEXT: SHF_WRITE # SEC-PIC-NEXT: ] -# SEC-PIC-NEXT: Address: 0x2380 -# SEC-PIC-NEXT: Offset: 0x380 +# SEC-PIC-NEXT: Address: 0x23C8 +# SEC-PIC-NEXT: Offset: 0x3C8 # SEC-PIC-NEXT: Size: 8 # SEC-PIC-NEXT: Link: # SEC-PIC-NEXT: Info: @@ -57,7 +66,7 @@ # SEC-PIC: 0x000000006FFFFFF9 RELACOUNT 1 # SEC-PIC: Relocations [ # SEC-PIC-NEXT: Section ({{.*}}) .rela.dyn { -# SEC-PIC-NEXT: 0x2380 R_X86_64_RELATIVE - 0x3388 +# SEC-PIC-NEXT: 0x23C8 R_X86_64_RELATIVE - 0x33D0 # SEC-PIC-NEXT: } # SEC-PIC-NEXT: ] @@ -65,24 +74,33 @@ # DISASM-PIC: Disassembly of section .text: # DISASM-PIC-EMPTY: # DISASM-PIC-NEXT: <_start>: -# DISASM-PIC-NEXT: 1268: adcl {{.*}}(%rip), %eax # 0x2380 -# DISASM-PIC-NEXT: addl {{.*}}(%rip), %ebx # 0x2380 -# DISASM-PIC-NEXT: andl {{.*}}(%rip), %ecx # 0x2380 -# DISASM-PIC-NEXT: cmpl {{.*}}(%rip), %edx # 0x2380 -# DISASM-PIC-NEXT: orl {{.*}}(%rip), %edi # 0x2380 -# DISASM-PIC-NEXT: sbbl {{.*}}(%rip), %esi # 0x2380 -# DISASM-PIC-NEXT: subl {{.*}}(%rip), %ebp # 0x2380 -# DISASM-PIC-NEXT: xorl {{.*}}(%rip), %r8d # 0x2380 -# DISASM-PIC-NEXT: testl %r15d, {{.*}}(%rip) # 0x2380 -# DISASM-PIC-NEXT: 12a0: adcq {{.*}}(%rip), %rax # 0x2380 -# DISASM-PIC-NEXT: addq {{.*}}(%rip), %rbx # 0x2380 -# DISASM-PIC-NEXT: andq {{.*}}(%rip), %rcx # 0x2380 -# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %rdx # 0x2380 -# DISASM-PIC-NEXT: orq {{.*}}(%rip), %rdi # 0x2380 -# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %rsi # 0x2380 -# DISASM-PIC-NEXT: subq {{.*}}(%rip), %rbp # 0x2380 -# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r8 # 0x2380 -# DISASM-PIC-NEXT: testq %r15, {{.*}}(%rip) # 0x2380 +# DISASM-PIC-NEXT: 1268: adcl {{.*}}(%rip), %eax # 0x23c8 +# DISASM-PIC-NEXT: addl {{.*}}(%rip), %ebx # 0x23c8 +# DISASM-PIC-NEXT: andl {{.*}}(%rip), %ecx # 0x23c8 +# DISASM-PIC-NEXT: cmpl {{.*}}(%rip), %edx # 0x23c8 +# DISASM-PIC-NEXT: orl {{.*}}(%rip), %edi # 0x23c8 +# DISASM-PIC-NEXT: sbbl {{.*}}(%rip), %esi # 0x23c8 +# DISASM-PIC-NEXT: subl {{.*}}(%rip), %ebp # 0x23c8 +# DISASM-PIC-NEXT: xorl {{.*}}(%rip), %r8d # 0x23c8 +# DISASM-PIC-NEXT: testl %r15d, {{.*}}(%rip) # 0x23c8 +# DISASM-PIC-NEXT: 12a0: adcq {{.*}}(%rip), %rax # 0x23c8 +# DISASM-PIC-NEXT: addq {{.*}}(%rip), %rbx # 0x23c8 +# DISASM-PIC-NEXT: andq {{.*}}(%rip), %rcx # 0x23c8 +# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %rdx # 0x23c8 +# DISASM-PIC-NEXT: orq {{.*}}(%rip), %rdi # 0x23c8 +# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %rsi # 0x23c8 +# DISASM-PIC-NEXT: subq {{.*}}(%rip), %rbp # 0x23c8 +# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r8 # 0x23c8 +# DISASM-PIC-NEXT: testq %r15, {{.*}}(%rip) # 0x23c8 +# DISASM-PIC-NEXT: 12df: adcq {{.*}}(%rip), %r16 # 0x23c8 +# DISASM-PIC-NEXT: addq {{.*}}(%rip), %r17 # 0x23c8 +# DISASM-PIC-NEXT: andq {{.*}}(%rip), %r18 # 0x23c8 +# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %r19 # 0x23c8 +# DISASM-PIC-NEXT: orq {{.*}}(%rip), %r20 # 0x23c8 +# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %r21 # 0x23c8 +# DISASM-PIC-NEXT: subq {{.*}}(%rip), %r22 # 0x23c8 +# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r23 # 0x23c8 +# DISASM-PIC-NEXT: testq %r24, {{.*}}(%rip) # 0x23c8 .data .type bar, @object @@ -115,3 +133,14 @@ _start: subq bar@GOTPCREL(%rip), %rbp xorq bar@GOTPCREL(%rip), %r8 testq %r15, bar@GOTPCREL(%rip) + +## R_X86_64_REX2_GOTPCRELX + adcq bar@GOTPCREL(%rip), %r16 + addq bar@GOTPCREL(%rip), %r17 + andq bar@GOTPCREL(%rip), %r18 + cmpq bar@GOTPCREL(%rip), %r19 + orq bar@GOTPCREL(%rip), %r20 + sbbq bar@GOTPCREL(%rip), %r21 + subq bar@GOTPCREL(%rip), %r22 + xorq bar@GOTPCREL(%rip), %r23 + testq %r24, bar@GOTPCREL(%rip) diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s index 5945bfc04a022..b1ff995b3fc21 100644 --- a/lld/test/ELF/x86-64-gotpc-relax.s +++ b/lld/test/ELF/x86-64-gotpc-relax.s @@ -1,5 +1,5 @@ # REQUIRES: x86 -## Test R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization. +## Test R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX/R_X86_64_REX2_GOTPCRELX GOT optimization. # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t1 --no-apply-dynamic-relocs @@ -15,16 +15,16 @@ ## In our implementation, .got is retained even if all GOT-generating relocations are optimized. # CHECK: Name Type Address Off Size ES Flg Lk Inf Al -# CHECK: .iplt PROGBITS 0000000000201280 000280 000010 00 AX 0 0 16 -# CHECK-NEXT: .got PROGBITS 0000000000202290 000290 000000 00 WA 0 0 8 +# CHECK: .iplt PROGBITS 00000000002012e0 0002e0 000010 00 AX 0 0 16 +# CHECK-NEXT: .got PROGBITS 00000000002022f0 0002f0 000000 00 WA 0 0 8 ## There is one R_X86_64_IRELATIVE relocations. # RELOC-LABEL: Relocation section '.rela.dyn' at offset {{.*}} contains 1 entry: # CHECK: Offset Info Type Symbol's Value Symbol's Name + Addend -# CHECK: 0000000000203290 0000000000000025 R_X86_64_IRELATIVE 2011e2 +# CHECK: 00000000002032f0 0000000000000025 R_X86_64_IRELATIVE 2011e2 # CHECK-LABEL: Hex dump of section '.got.plt': -# NOAPPLY-NEXT: 0x00203290 00000000 00000000 -# APPLY-NEXT: 0x00203290 e2112000 00000000 +# NOAPPLY-NEXT: 0x002032f0 00000000 00000000 +# APPLY-NEXT: 0x002032f0 e2112000 00000000 # 0x201173 + 7 - 10 = 0x201170 # 0x20117a + 7 - 17 = 0x201170 @@ -43,20 +43,20 @@ # DISASM-NEXT: leaq -17(%rip), %rax # DISASM-NEXT: leaq -23(%rip), %rax # DISASM-NEXT: leaq -30(%rip), %rax -# DISASM-NEXT: movq 8330(%rip), %rax -# DISASM-NEXT: movq 8323(%rip), %rax +# DISASM-NEXT: movq 8426(%rip), %rax +# DISASM-NEXT: movq 8419(%rip), %rax # DISASM-NEXT: leaq -52(%rip), %rax # DISASM-NEXT: leaq -59(%rip), %rax # DISASM-NEXT: leaq -65(%rip), %rax # DISASM-NEXT: leaq -72(%rip), %rax -# DISASM-NEXT: movq 8288(%rip), %rax -# DISASM-NEXT: movq 8281(%rip), %rax +# DISASM-NEXT: movq 8384(%rip), %rax +# DISASM-NEXT: movq 8377(%rip), %rax # DISASM-NEXT: callq 0x2011e0 # DISASM-NEXT: callq 0x2011e0 # DISASM-NEXT: callq 0x2011e1 # DISASM-NEXT: callq 0x2011e1 -# DISASM-NEXT: callq *8251(%rip) -# DISASM-NEXT: callq *8245(%rip) +# DISASM-NEXT: callq *8347(%rip) +# DISASM-NEXT: callq *8341(%rip) # DISASM-NEXT: jmp 0x2011e0 # DISASM-NEXT: nop # DISASM-NEXT: jmp 0x2011e0 @@ -65,13 +65,26 @@ # DISASM-NEXT: nop # DISASM-NEXT: jmp 0x2011e1 # DISASM-NEXT: nop -# DISASM-NEXT: jmpq *8215(%rip) -# DISASM-NEXT: jmpq *8209(%rip) +# DISASM-NEXT: jmpq *8311(%rip) +# DISASM-NEXT: jmpq *8305(%rip) +# DISASM-NEXT: leaq -167(%rip), %r16 +# DISASM-NEXT: leaq -175(%rip), %r16 +# DISASM-NEXT: leaq -182(%rip), %r16 +# DISASM-NEXT: leaq -190(%rip), %r16 +# DISASM-NEXT: movq 8265(%rip), %r16 +# DISASM-NEXT: movq 8257(%rip), %r16 +# DISASM-NEXT: leaq -215(%rip), %r16 +# DISASM-NEXT: leaq -223(%rip), %r16 +# DISASM-NEXT: leaq -230(%rip), %r16 +# DISASM-NEXT: leaq -238(%rip), %r16 +# DISASM-NEXT: movq 8217(%rip), %r16 +# DISASM-NEXT: movq 8209(%rip), %r16 # NORELAX-LABEL: <_start>: # NORELAX-COUNT-12: movq # NORELAX-COUNT-6: callq * # NORELAX-COUNT-6: jmpq * +# NORELAX-COUNT-12: movq .text .globl foo @@ -120,3 +133,16 @@ _start: jmp *hid@GOTPCREL(%rip) jmp *ifunc@GOTPCREL(%rip) jmp *ifunc@GOTPCREL(%rip) + + movq foo@GOTPCREL(%rip), %r16 + movq foo@GOTPCREL(%rip), %r16 + movq hid@GOTPCREL(%rip), %r16 + movq hid@GOTPCREL(%rip), %r16 + movq ifunc@GOTPCREL(%rip), %r16 + movq ifunc@GOTPCREL(%rip), %r16 + movq foo@GOTPCREL(%rip), %r16 + movq foo@GOTPCREL(%rip), %r16 + movq hid@GOTPCREL(%rip), %r16 + movq hid@GOTPCREL(%rip), %r16 + movq ifunc@GOTPCREL(%rip), %r16 + movq ifunc@GOTPCREL(%rip), %r16