[PATCH] D15779: [ELF] - Implemented optimization for R_X86_64_GOTPCREL relocation.
Rafael Espíndola via llvm-commits
llvm-commits at lists.llvm.org
Mon May 23 19:27:50 PDT 2016
I decided to apply the patch to give it a better review.
Some of the issues I pointed out in the review (R_RELAX_GOT referring
to got entry) were the causes of other changes (unnecessary continue).
Also, the *GOTPCRELX relocations can always be relaxed if the symbol
is not ifunc or preemptable, no? It is just that it is not always a
mov->lea.
In any case, I have attached the result of simplifying your patch a
bit. Let me know what you think.
Cheers,
Rafael
On 23 May 2016 at 19:36, Rafael Ávila de Espíndola
<llvm-commits at lists.llvm.org> wrote:
> rafael added inline comments.
>
> ================
> Comment at: ELF/Writer.cpp:535
> @@ +534,3 @@
> + if (Target->canRelaxGot(Type, Body, Data, Offset))
> + return R_RELAX_GOT;
> +
> ----------------
> I don't think you can do an early return here. You should set Expr and let the function continue so we get the checks.
>
>
> http://reviews.llvm.org/D15779
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
-------------- next part --------------
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index fd69502..f6d5445 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -168,6 +168,7 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
switch (Expr) {
case R_HINT:
llvm_unreachable("cannot relocate hint relocs");
+ case R_RELAXABLE_GOT_PC:
case R_RELAX_TLS_GD_TO_LE:
case R_RELAX_TLS_GD_TO_IE:
case R_RELAX_TLS_IE_TO_LE:
@@ -249,6 +250,7 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
return SymVA - P;
}
case R_PC:
+ case R_RELAX_GOT_PC:
return Body.getVA<ELFT>(A) - P;
case R_PAGE_PC:
return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P);
@@ -323,6 +325,9 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) {
}
switch (Expr) {
+ case R_RELAX_GOT_PC:
+ Target->relaxGot(BufLoc, SymVA);
+ break;
case R_RELAX_TLS_IE_TO_LE:
Target->relaxTlsIeToLe(BufLoc, Type, SymVA);
break;
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index cd122cf..b5429da 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -47,6 +47,8 @@ enum RelExpr {
R_PPC_OPD,
R_PPC_PLT_OPD,
R_PPC_TOC,
+ R_RELAXABLE_GOT_PC,
+ R_RELAX_GOT_PC,
R_RELAX_TLS_GD_TO_IE,
R_RELAX_TLS_GD_TO_LE,
R_RELAX_TLS_IE_TO_LE,
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index ec88ec0..ad05825 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -113,6 +113,7 @@ public:
int32_t Index, unsigned RelOff) const override;
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) 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;
void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
@@ -232,6 +233,10 @@ bool TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
return false;
}
+void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
+}
+
void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
llvm_unreachable("Should not have claimed to be relaxable");
@@ -516,10 +521,11 @@ RelExpr X86_64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
case R_X86_64_GOT32:
return R_GOT_FROM_END;
case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTTPOFF:
return R_GOT_PC;
+ case R_X86_64_GOTPCRELX:
+ case R_X86_64_REX_GOTPCRELX:
+ return R_RELAXABLE_GOT_PC;
}
}
@@ -727,6 +733,11 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
}
}
+void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
+ Loc[-2] = 0x8d;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+}
+
// Relocation masks following the #lo(value), #hi(value), #ha(value),
// #higher(value), #highera(value), #highest(value), and #highesta(value)
// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
diff --git a/ELF/Target.h b/ELF/Target.h
index ed8df82..c1ff103 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -88,6 +88,7 @@ public:
uint32_t ThunkSize = 0;
+ 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;
virtual void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 0ee7a46..6d0bac1 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -452,7 +452,8 @@ static bool needsPlt(RelExpr Expr) {
// True if this expression is of the form Sym - X, where X is a position in the
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr Expr) {
- return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC;
+ return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC ||
+ Expr == R_RELAX_GOT_PC;
}
template <class ELFT>
@@ -529,10 +530,17 @@ RelExpr Writer<ELFT>::adjustExpr(const elf::ObjectFile<ELFT> &File,
if (Target->needsThunk(Type, File, Body))
return R_THUNK;
bool Preemptible = Body.isPreemptible();
- if (Body.isGnuIFunc())
+ if (Body.isGnuIFunc()) {
Expr = toPlt(Expr);
- else if (needsPlt(Expr) && !Preemptible)
- Expr = fromPlt(Expr);
+ } else if (!Preemptible) {
+ if (needsPlt(Expr))
+ Expr = fromPlt(Expr);
+ if (Expr == R_RELAXABLE_GOT_PC)
+ Expr = R_RELAX_GOT_PC;
+ }
+
+ if (Expr == R_RELAXABLE_GOT_PC)
+ Expr = R_GOT_PC;
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
return Expr;
diff --git a/test/ELF/Inputs/gotpc-relax-und-dso.s b/test/ELF/Inputs/gotpc-relax-und-dso.s
new file mode 100644
index 0000000..cbe39f3
--- /dev/null
+++ b/test/ELF/Inputs/gotpc-relax-und-dso.s
@@ -0,0 +1,4 @@
+.globl dsofoo
+.type dsofoo, @function
+dsofoo:
+ nop
diff --git a/test/ELF/gotpc-relax-und-dso.s b/test/ELF/gotpc-relax-und-dso.s
new file mode 100644
index 0000000..e8f23d8
--- /dev/null
+++ b/test/ELF/gotpc-relax-und-dso.s
@@ -0,0 +1,73 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %S/Inputs/gotpc-relax-und-dso.s -o %tdso.o
+# RUN: ld.lld -shared %tdso.o -o %t.so
+# RUN: ld.lld -shared %t.o %t.so -o %tout
+# RUN: llvm-readobj -r -s %tout | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s
+
+# RELOC: Relocations [
+# RELOC-NEXT: Section ({{.*}}) .rela.dyn {
+# RELOC-NEXT: 0x20A8 R_X86_64_GLOB_DAT dsofoo 0x0
+# RELOC-NEXT: 0x20B0 R_X86_64_GLOB_DAT foo 0x0
+# RELOC-NEXT: 0x20A0 R_X86_64_GLOB_DAT und 0x0
+# RELOC-NEXT: }
+# RELOC-NEXT: ]
+
+# 0x101e + 7 - 36 = 0x1001
+# 0x1025 + 7 - 43 = 0x1001
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: 1000: 90 nop
+# DISASM: hid:
+# DISASM-NEXT: 1001: 90 nop
+# DISASM: _start:
+# DISASM-NEXT: 1002: 48 8b 05 97 10 00 00 movq 4247(%rip), %rax
+# DISASM-NEXT: 1009: 48 8b 05 90 10 00 00 movq 4240(%rip), %rax
+# DISASM-NEXT: 1010: 48 8b 05 91 10 00 00 movq 4241(%rip), %rax
+# DISASM-NEXT: 1017: 48 8b 05 8a 10 00 00 movq 4234(%rip), %rax
+# DISASM-NEXT: 101e: 48 8d 05 dc ff ff ff leaq -36(%rip), %rax
+# DISASM-NEXT: 1025: 48 8d 05 d5 ff ff ff leaq -43(%rip), %rax
+# DISASM-NEXT: 102c: 48 8b 05 7d 10 00 00 movq 4221(%rip), %rax
+# DISASM-NEXT: 1033: 48 8b 05 76 10 00 00 movq 4214(%rip), %rax
+# DISASM-NEXT: 103a: 8b 05 60 10 00 00 movl 4192(%rip), %eax
+# DISASM-NEXT: 1040: 8b 05 5a 10 00 00 movl 4186(%rip), %eax
+# DISASM-NEXT: 1046: 8b 05 5c 10 00 00 movl 4188(%rip), %eax
+# DISASM-NEXT: 104c: 8b 05 56 10 00 00 movl 4182(%rip), %eax
+# DISASM-NEXT: 1052: 8d 05 a9 ff ff ff leal -87(%rip), %eax
+# DISASM-NEXT: 1058: 8d 05 a3 ff ff ff leal -93(%rip), %eax
+# DISASM-NEXT: 105e: 8b 05 4c 10 00 00 movl 4172(%rip), %eax
+# DISASM-NEXT: 1064: 8b 05 46 10 00 00 movl 4166(%rip), %eax
+
+.text
+.globl foo
+.type foo, @function
+foo:
+ nop
+
+.globl hid
+.hidden hid
+.type hid, @function
+hid:
+ nop
+
+.globl _start
+.type _start, @function
+_start:
+ movq und at GOTPCREL(%rip), %rax
+ movq und at GOTPCREL(%rip), %rax
+ movq dsofoo at GOTPCREL(%rip), %rax
+ movq dsofoo at GOTPCREL(%rip), %rax
+ movq hid at GOTPCREL(%rip), %rax
+ movq hid at GOTPCREL(%rip), %rax
+ movq foo at GOTPCREL(%rip), %rax
+ movq foo at GOTPCREL(%rip), %rax
+
+ movl und at GOTPCREL(%rip), %eax
+ movl und at GOTPCREL(%rip), %eax
+ movl dsofoo at GOTPCREL(%rip), %eax
+ movl dsofoo at GOTPCREL(%rip), %eax
+ movl hid at GOTPCREL(%rip), %eax
+ movl hid at GOTPCREL(%rip), %eax
+ movl foo at GOTPCREL(%rip), %eax
+ movl foo at GOTPCREL(%rip), %eax
diff --git a/test/ELF/gotpc-relax.s b/test/ELF/gotpc-relax.s
new file mode 100644
index 0000000..4c7114b
--- /dev/null
+++ b/test/ELF/gotpc-relax.s
@@ -0,0 +1,69 @@
+# 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 -r %t1 | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+## There is no relocations.
+# RELOC: Relocations [
+# RELOC: ]
+
+# 0x11003 + 7 - 10 = 0x11000
+# 0x1100a + 7 - 17 = 0x11000
+# 0x11011 + 7 - 23 = 0x11001
+# 0x11018 + 7 - 30 = 0x11001
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: 11000: 90 nop
+# DISASM: hid:
+# DISASM-NEXT: 11001: 90 nop
+# DISASM: ifunc:
+# DISASM-NEXT: 11002: c3 retq
+# DISASM: _start:
+# DISASM-NEXT: 11003: 48 8d 05 f6 ff ff ff leaq -10(%rip), %rax
+# DISASM-NEXT: 1100a: 48 8d 05 ef ff ff ff leaq -17(%rip), %rax
+# DISASM-NEXT: 11011: 48 8d 05 e9 ff ff ff leaq -23(%rip), %rax
+# DISASM-NEXT: 11018: 48 8d 05 e2 ff ff ff leaq -30(%rip), %rax
+# DISASM-NEXT: 1101f: 48 8b 05 da 0f 00 00 movq 4058(%rip), %rax
+# DISASM-NEXT: 11026: 48 8b 05 d3 0f 00 00 movq 4051(%rip), %rax
+# DISASM-NEXT: 1102d: 8d 05 cd ff ff ff leal -51(%rip), %eax
+# DISASM-NEXT: 11033: 8d 05 c7 ff ff ff leal -57(%rip), %eax
+# DISASM-NEXT: 11039: 8d 05 c2 ff ff ff leal -62(%rip), %eax
+# DISASM-NEXT: 1103f: 8d 05 bc ff ff ff leal -68(%rip), %eax
+# DISASM-NEXT: 11045: 8b 05 b5 0f 00 00 movl 4021(%rip), %eax
+# DISASM-NEXT: 1104b: 8b 05 af 0f 00 00 movl 4015(%rip), %eax
+
+.text
+.globl foo
+.type foo, @function
+foo:
+ nop
+
+.globl hid
+.hidden hid
+.type hid, @function
+hid:
+ nop
+
+.text
+.type ifunc STT_GNU_IFUNC
+.globl ifunc
+.type ifunc, @function
+ifunc:
+ ret
+
+.globl _start
+.type _start, @function
+_start:
+ movq foo at GOTPCREL(%rip), %rax
+ movq foo at GOTPCREL(%rip), %rax
+ movq hid at GOTPCREL(%rip), %rax
+ movq hid at GOTPCREL(%rip), %rax
+ movq ifunc at GOTPCREL(%rip), %rax
+ movq ifunc at GOTPCREL(%rip), %rax
+ movl foo at GOTPCREL(%rip), %eax
+ movl foo at GOTPCREL(%rip), %eax
+ movl hid at GOTPCREL(%rip), %eax
+ movl hid at GOTPCREL(%rip), %eax
+ movl ifunc at GOTPCREL(%rip), %eax
+ movl ifunc at GOTPCREL(%rip), %eax
More information about the llvm-commits
mailing list