[lld] r271365 - bar
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue May 31 23:13:56 PDT 2016
Author: rafael
Date: Wed Jun 1 01:13:54 2016
New Revision: 271365
URL: http://llvm.org/viewvc/llvm-project?rev=271365&view=rev
Log:
bar
Added:
lld/trunk/test/ELF/gotpc-relax-nopic.s
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=271365&r1=271364&r2=271365&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Jun 1 01:13:54 2016
@@ -257,6 +257,8 @@ getSymVA(uint32_t Type, typename ELFT::u
case R_PC:
case R_RELAX_GOT_PC:
return Body.getVA<ELFT>(A) - P;
+ case R_RELAX_GOT_PC_NOPIC:
+ return Body.getVA<ELFT>();
case R_PAGE_PC:
return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P);
}
@@ -325,6 +327,7 @@ void InputSectionBase<ELFT>::relocate(ui
switch (Expr) {
case R_RELAX_GOT_PC:
+ case R_RELAX_GOT_PC_NOPIC:
Target->relaxGot(BufLoc, SymVA);
break;
case R_RELAX_TLS_IE_TO_LE:
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=271365&r1=271364&r2=271365&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jun 1 01:13:54 2016
@@ -244,7 +244,7 @@ static bool needsPlt(RelExpr Expr) {
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr Expr) {
return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC ||
- Expr == R_RELAX_GOT_PC;
+ Expr == R_RELAX_GOT_PC || Expr == R_RELAX_GOT_PC_NOPIC;
}
template <class ELFT>
@@ -370,8 +370,8 @@ static RelExpr adjustExpr(const elf::Obj
} else if (!Preemptible) {
if (needsPlt(Expr))
Expr = fromPlt(Expr);
- if (Expr == R_GOT_PC && Target->canRelaxGot(Type, Data + Offset))
- Expr = R_RELAX_GOT_PC;
+ if (Expr == R_GOT_PC)
+ Expr = Target->adjustRelaxGotExpr(Type, Data + Offset, Expr);
}
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=271365&r1=271364&r2=271365&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Jun 1 01:13:54 2016
@@ -39,6 +39,7 @@ enum RelExpr {
R_PPC_PLT_OPD,
R_PPC_TOC,
R_RELAX_GOT_PC,
+ R_RELAX_GOT_PC_NOPIC,
R_RELAX_TLS_GD_TO_IE,
R_RELAX_TLS_GD_TO_LE,
R_RELAX_TLS_IE_TO_LE,
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=271365&r1=271364&r2=271365&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Jun 1 01:13:54 2016
@@ -113,7 +113,8 @@ public:
int32_t Index, unsigned RelOff) const override;
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
- bool canRelaxGot(uint32_t Type, const uint8_t *Data) const override;
+ RelExpr adjustRelaxGotExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const override;
void relaxGot(uint8_t *Loc, uint64_t Val) const override;
void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
@@ -234,8 +235,9 @@ bool TargetInfo::isTlsGlobalDynamicRel(u
return false;
}
-bool TargetInfo::canRelaxGot(uint32_t Type, const uint8_t *Data) const {
- return false;
+RelExpr TargetInfo::adjustRelaxGotExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const {
+ return Expr;
}
void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
@@ -734,16 +736,25 @@ void X86_64TargetInfo::relocateOne(uint8
}
}
-bool X86_64TargetInfo::canRelaxGot(uint32_t Type, const uint8_t *Data) const {
+RelExpr X86_64TargetInfo::adjustRelaxGotExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr RelExpr) const {
if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX)
- return false;
+ return RelExpr;
const uint8_t Op = Data[-2];
const uint8_t ModRm = Data[-1];
// Relax mov.
if (Op == 0x8b)
- return true;
+ return R_RELAX_GOT_PC;
// Relax call and jmp.
- return Op == 0xff && (ModRm == 0x15 || ModRm == 0x25);
+ if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25))
+ return R_RELAX_GOT_PC;
+
+ // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
+ // If PIC then no relaxation is available.
+ // We also don't relax test/binop instructions without REX byte,
+ // they are 32bit operations and not common to have.
+ return (!Config->Pic && Type == R_X86_64_REX_GOTPCRELX) ? R_RELAX_GOT_PC_NOPIC
+ : RelExpr;
}
void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
@@ -757,22 +768,86 @@ void X86_64TargetInfo::relaxGot(uint8_t
return;
}
- assert(Op == 0xff);
- if (ModRm == 0x15) {
- // ABI says we can convert call *foo at GOTPCREL(%rip) to nop call foo.
- // Instead we convert to addr32 call foo, where addr32 is instruction
- // prefix. That makes result expression to be a single instruction.
- *(Loc - 2) = 0x67; // addr32 prefix
- *(Loc - 1) = 0xe8; // call
- } else {
- assert(ModRm == 0x25);
- // Convert jmp *foo at GOTPCREL(%rip) to jmp foo nop.
- // jmp doesn't return, so it is fine to use nop here, it is just a stub.
- *(Loc - 2) = 0xe9; // jmp
- *(Loc + 3) = 0x90; // nop
- Loc -= 1;
- Val += 1;
+ // Convert call/jmp instructions.
+ if (Op == 0xff) {
+ if (ModRm == 0x15) {
+ // ABI says we can convert call *foo at GOTPCREL(%rip) to nop call foo.
+ // Instead we convert to addr32 call foo, where addr32 is instruction
+ // prefix. That makes result expression to be a single instruction.
+ *(Loc - 2) = 0x67; // addr32 prefix
+ *(Loc - 1) = 0xe8; // call
+ }
+ else {
+ assert(ModRm == 0x25);
+ // Convert jmp *foo at GOTPCREL(%rip) to jmp foo nop.
+ // jmp doesn't return, so it is fine to use nop here, it is just a stub.
+ *(Loc - 2) = 0xe9; // jmp
+ *(Loc + 3) = 0x90; // nop
+ Loc -= 1;
+ Val += 1;
+ }
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
}
+
+ // Convert "test %reg, foo at GOTPCREL(%rip)" to "test $foo, %reg".
+ // Documents used:
+ // 1) http://ref.x86asm.net/coder64.html
+ // 2) http://wiki.osdev.org/X86-64_Instruction_Encoding
+ // 3) http://www.swansontec.com/sintel.html
+ assert(!Config->Pic);
+ const uint8_t Rex = Loc[-3];
+ if (Op == 0x85) {
+ // See 0x85 description in (1). Column "o" has "r" what indicates that the
+ // instruction uses "full" ModR / M byte, (no opcode extension).
+
+ // ModR/M byte has form XX YYY ZZZ, where
+ // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
+ // XX has different meanings:
+ // 00: The operand's memory address is in reg1.
+ // 01: The operand's memory address is reg1 + a byte-sized displacement.
+ // 10: The operand's memory address is reg1 + a word-sized displacement.
+ // 11: The operand is reg1 itself.
+ // If an instruction requires only one operand, the unused reg2 field
+ // holds extra opcode bits rather than a register code
+ // 0xC0 == 11 000 000 binary.
+ // 0x38 == 00 111 000 binary.
+ // We transfer reg2 to reg1 here as operand. See (2), (3).
+ *(Loc - 1) = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.
+
+ // Change opcode from test op1 = r/m16/32/64, op2 = r16/32/64
+ // to test op1 = r/m16/32/64, op2 = imm16/32/64, see (1).
+ *(Loc - 2) = 0xf7;
+
+ // Move R bit to the B bit in REX 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
+ // default operand size is used (which is 32-bit for most but not all
+ // instructions).
+ // REX.R This 1-bit value is an extension to the MODRM.reg field.
+ // REX.X This 1-bit value is an extension to the SIB.index field.
+ // REX.B This 1-bit value is an extension to the MODRM.rm field or the
+ // SIB.base field, see (3).
+ *(Loc - 3) = (Rex & ~0x4) | (Rex & 0x4) >> 2;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
+ }
+
+ // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
+ // or xor operations.
+
+ // Convert "binop foo at GOTPCREL(%rip), %reg" to "binop $foo, %reg".
+ // Logic is close to one for test instruction above, but we also
+ // write opcode extension here, see below for info.
+ *(Loc - 1) = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.
+
+ // Primary opcode is 0x81, opcode extension is one of:
+ // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
+ // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
+ // This value was wrote to MODRM.reg in a line above, see (1).
+ *(Loc - 2) = 0x81;
+ *(Loc - 3) = (Rex & ~0x4) | (Rex & 0x4) >> 2;
relocateOne(Loc, R_X86_64_PC32, Val);
}
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=271365&r1=271364&r2=271365&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Jun 1 01:13:54 2016
@@ -88,7 +88,8 @@ public:
uint32_t ThunkSize = 0;
- virtual bool canRelaxGot(uint32_t Type, const uint8_t *Data) const;
+ virtual RelExpr adjustRelaxGotExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const;
virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;
virtual void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
virtual void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
Added: lld/trunk/test/ELF/gotpc-relax-nopic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gotpc-relax-nopic.s?rev=271365&view=auto
==============================================================================
--- lld/trunk/test/ELF/gotpc-relax-nopic.s (added)
+++ lld/trunk/test/ELF/gotpc-relax-nopic.s Wed Jun 1 01:13:54 2016
@@ -0,0 +1,109 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj -symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s
+# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+## There is no relocations.
+# SYMRELOC: Relocations [
+# SYMRELOC-NEXT: ]
+# SYMRELOC: Symbols [
+# SYMRELOC: Symbol {
+# SYMRELOC: Name: bar
+# SYMRELOC-NEXT: Value: 0x13000
+
+## 77824 = 0x13000 (bar)
+## Notice, that 32bit versions of operations are not relaxed.
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: _start:
+# DISASM-NEXT: 11000: 13 05 fa 0f 00 00 adcl 4090(%rip), %eax
+# DISASM-NEXT: 11006: 03 1d f4 0f 00 00 addl 4084(%rip), %ebx
+# DISASM-NEXT: 1100c: 23 0d ee 0f 00 00 andl 4078(%rip), %ecx
+# DISASM-NEXT: 11012: 3b 15 e8 0f 00 00 cmpl 4072(%rip), %edx
+# DISASM-NEXT: 11018: 0b 35 e2 0f 00 00 orl 4066(%rip), %esi
+# DISASM-NEXT: 1101e: 1b 3d dc 0f 00 00 sbbl 4060(%rip), %edi
+# DISASM-NEXT: 11024: 2b 2d d6 0f 00 00 subl 4054(%rip), %ebp
+# DISASM-NEXT: 1102a: 44 33 05 cf 0f 00 00 xorl 4047(%rip), %r8d
+# DISASM-NEXT: 11031: 44 85 3d c8 0f 00 00 testl 4040(%rip), %r15d
+# DISASM-NEXT: 11038: 48 81 d0 00 30 01 00 adcq $77824, %rax
+# DISASM-NEXT: 1103f: 48 81 c3 00 30 01 00 addq $77824, %rbx
+# DISASM-NEXT: 11046: 48 81 e1 00 30 01 00 andq $77824, %rcx
+# DISASM-NEXT: 1104d: 48 81 fa 00 30 01 00 cmpq $77824, %rdx
+# DISASM-NEXT: 11054: 48 81 cf 00 30 01 00 orq $77824, %rdi
+# DISASM-NEXT: 1105b: 48 81 de 00 30 01 00 sbbq $77824, %rsi
+# DISASM-NEXT: 11062: 48 81 ed 00 30 01 00 subq $77824, %rbp
+# DISASM-NEXT: 11069: 49 81 f0 00 30 01 00 xorq $77824, %r8
+# DISASM-NEXT: 11070: 49 f7 c7 00 30 01 00 testq $77824, %r15
+
+# RUN: ld.lld -shared %t.o -o %t2
+# RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=SEC-PIC %s
+# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s
+# SEC-PIC: Section {
+# SEC-PIC: Index:
+# SEC-PIC: Name: .got
+# SEC-PIC-NEXT: Type: SHT_PROGBITS
+# SEC-PIC-NEXT: Flags [
+# SEC-PIC-NEXT: SHF_ALLOC
+# SEC-PIC-NEXT: SHF_WRITE
+# SEC-PIC-NEXT: ]
+# SEC-PIC-NEXT: Address: 0x2090
+# SEC-PIC-NEXT: Offset: 0x2090
+# SEC-PIC-NEXT: Size: 8
+# SEC-PIC-NEXT: Link:
+# SEC-PIC-NEXT: Info:
+# SEC-PIC-NEXT: AddressAlignment:
+# SEC-PIC-NEXT: EntrySize:
+# SEC-PIC-NEXT: }
+
+## Check that there was no relaxation performed. All values refer to got entry.
+## Ex: 0x1000 + 4234 + 6 = 0x2090
+## 0x102a + 4191 + 7 = 0x2090
+# DISASM-PIC: Disassembly of section .text:
+# DISASM-PIC-NEXT: _start:
+# DISASM-PIC-NEXT: 1000: 13 05 8a 10 00 00 adcl 4234(%rip), %eax
+# DISASM-PIC-NEXT: 1006: 03 1d 84 10 00 00 addl 4228(%rip), %ebx
+# DISASM-PIC-NEXT: 100c: 23 0d 7e 10 00 00 andl 4222(%rip), %ecx
+# DISASM-PIC-NEXT: 1012: 3b 15 78 10 00 00 cmpl 4216(%rip), %edx
+# DISASM-PIC-NEXT: 1018: 0b 35 72 10 00 00 orl 4210(%rip), %esi
+# DISASM-PIC-NEXT: 101e: 1b 3d 6c 10 00 00 sbbl 4204(%rip), %edi
+# DISASM-PIC-NEXT: 1024: 2b 2d 66 10 00 00 subl 4198(%rip), %ebp
+# DISASM-PIC-NEXT: 102a: 44 33 05 5f 10 00 00 xorl 4191(%rip), %r8d
+# DISASM-PIC-NEXT: 1031: 44 85 3d 58 10 00 00 testl 4184(%rip), %r15d
+# DISASM-PIC-NEXT: 1038: 48 13 05 51 10 00 00 adcq 4177(%rip), %rax
+# DISASM-PIC-NEXT: 103f: 48 03 1d 4a 10 00 00 addq 4170(%rip), %rbx
+# DISASM-PIC-NEXT: 1046: 48 23 0d 43 10 00 00 andq 4163(%rip), %rcx
+# DISASM-PIC-NEXT: 104d: 48 3b 15 3c 10 00 00 cmpq 4156(%rip), %rdx
+# DISASM-PIC-NEXT: 1054: 48 0b 3d 35 10 00 00 orq 4149(%rip), %rdi
+# DISASM-PIC-NEXT: 105b: 48 1b 35 2e 10 00 00 sbbq 4142(%rip), %rsi
+# DISASM-PIC-NEXT: 1062: 48 2b 2d 27 10 00 00 subq 4135(%rip), %rbp
+# DISASM-PIC-NEXT: 1069: 4c 33 05 20 10 00 00 xorq 4128(%rip), %r8
+# DISASM-PIC-NEXT: 1070: 4c 85 3d 19 10 00 00 testq 4121(%rip), %r15
+
+.data
+.type bar, @object
+bar:
+ .byte 1
+ .size bar, .-bar
+
+.text
+.globl _start
+.type _start, @function
+_start:
+ adcl bar at GOTPCREL(%rip), %eax
+ addl bar at GOTPCREL(%rip), %ebx
+ andl bar at GOTPCREL(%rip), %ecx
+ cmpl bar at GOTPCREL(%rip), %edx
+ orl bar at GOTPCREL(%rip), %esi
+ sbbl bar at GOTPCREL(%rip), %edi
+ subl bar at GOTPCREL(%rip), %ebp
+ xorl bar at GOTPCREL(%rip), %r8d
+ testl %r15d, bar at GOTPCREL(%rip)
+ adcq bar at GOTPCREL(%rip), %rax
+ addq bar at GOTPCREL(%rip), %rbx
+ andq bar at GOTPCREL(%rip), %rcx
+ cmpq bar at GOTPCREL(%rip), %rdx
+ orq bar at GOTPCREL(%rip), %rdi
+ sbbq bar at GOTPCREL(%rip), %rsi
+ subq bar at GOTPCREL(%rip), %rbp
+ xorq bar at GOTPCREL(%rip), %r8
+ testq %r15, bar at GOTPCREL(%rip)
More information about the llvm-commits
mailing list