[ELF] Don't relax R_X86_64_GOTPCRELX if addend != -4
clang may produce `movl x@GOTPCREL+4(%rip), %eax` when loading the high 32 bits
of the address of a global variable in -fpic/-fpie mode.
If assembled by GNU as, the fixup emits an R_X86_64_GOTPCRELX with an
addend != -4. The instruction loads from the GOT entry with an offset
and thus it is incorrect to relax the instruction.
If assembled by the integrated assembler, we emit R_X86_64_GOTPCREL for
relocations that definitely cannot be relaxed (D92114), so this patch is not
needed.
This patch disables the relaxation, which is compatible with the implementation in GNU ld
("Add R_X86_64_[REX_]GOTPCRELX support to gas and ld").
Reviewed By: grimar, jhenderson
Differential Revision: https://reviews.llvm.org/D91993
			
			
This commit is contained in:
		
							parent
							
								
									25c8fbb3d9
								
							
						
					
					
						commit
						589e10f858
					
				| 
						 | 
					@ -730,7 +730,12 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
 | 
					RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
 | 
				
			||||||
                                const uint8_t *loc) const {
 | 
					                                const uint8_t *loc) const {
 | 
				
			||||||
  if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX)
 | 
					  // 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.
 | 
				
			||||||
 | 
					  if ((type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) ||
 | 
				
			||||||
 | 
					      addend != -4)
 | 
				
			||||||
    return R_GOT_PC;
 | 
					    return R_GOT_PC;
 | 
				
			||||||
  const uint8_t op = loc[-2];
 | 
					  const uint8_t op = loc[-2];
 | 
				
			||||||
  const uint8_t modRm = loc[-1];
 | 
					  const uint8_t modRm = loc[-1];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					# REQUIRES: x86
 | 
				
			||||||
 | 
					# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
 | 
				
			||||||
 | 
					# RUN: ld.lld %t.o -o %t
 | 
				
			||||||
 | 
					# RUN: llvm-objdump -s -d %t | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK:      Contents of section .got:
 | 
				
			||||||
 | 
					# CHECK-NEXT: {{^}} [[#%x,ADDR:]] {{.*}} 00000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK:      leal {{.*}}(%rip), %eax  # {{.*}} <foo>
 | 
				
			||||||
 | 
					# CHECK-NEXT: movl {{.*}}(%rip), %eax  # [[#ADDR+4]]
 | 
				
			||||||
 | 
					# CHECK-NEXT: movq {{.*}}(%rip), %rax  # [[#ADDR+1]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## movl foo@GOTPCREL(%rip), %eax
 | 
				
			||||||
 | 
					  movl 0(%rip), %eax
 | 
				
			||||||
 | 
					  .reloc .-4, R_X86_64_GOTPCRELX, foo-4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The instruction has an offset (addend!=-4). It is incorrect to relax movl to leal.
 | 
				
			||||||
 | 
					## movl foo@GOTPCREL+4(%rip), %eax
 | 
				
			||||||
 | 
					  movl 0(%rip), %eax
 | 
				
			||||||
 | 
					  .reloc .-4, R_X86_64_GOTPCRELX, foo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## This does not make sense because it loads one byte past the GOT entry.
 | 
				
			||||||
 | 
					## It is just to demonstrate the behavior.
 | 
				
			||||||
 | 
					## movq foo@GOTPCREL+1(%rip), %rax
 | 
				
			||||||
 | 
					  movq 0(%rip), %rax
 | 
				
			||||||
 | 
					  .reloc .-4, R_X86_64_REX_GOTPCRELX, foo-3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.globl foo
 | 
				
			||||||
 | 
					foo:
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
		Loading…
	
		Reference in New Issue