[lld] r338750 - [LLD] Update split stack support to handle more generic prologues. Improve error handling. Add test file for better code-coverage. Update tests to be more complete.
Jordan Rupprecht via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 2 11:13:40 PDT 2018
Author: rupprecht
Date: Thu Aug 2 11:13:40 2018
New Revision: 338750
URL: http://llvm.org/viewvc/llvm-project?rev=338750&view=rev
Log:
[LLD] Update split stack support to handle more generic prologues. Improve error handling. Add test file for better code-coverage. Update tests to be more complete.
Submitting patch on behalf of saugustine.
Differential Revision: https://reviews.llvm.org/D49926
Added:
lld/trunk/test/ELF/Inputs/x86-64-split-stack-extra.s
Modified:
lld/trunk/ELF/Arch/X86_64.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s
lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s
lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s
Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=338750&r1=338749&r2=338750&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Thu Aug 2 11:13:40 2018
@@ -482,22 +482,25 @@ namespace {
template <>
bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
uint8_t *End) const {
+ if (Loc + 8 >= End)
+ return false;
+
// Replace "cmp %fs:0x70,%rsp" and subsequent branch
// with "stc, nopl 0x0(%rax,%rax,1)"
- if (Loc + 8 < End && memcmp(Loc, "\x64\x48\x3b\x24\x25", 4) == 0) {
+ if (memcmp(Loc, "\x64\x48\x3b\x24\x25", 5) == 0) {
memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8);
return true;
}
- // Adjust "lea -0x200(%rsp),%r10" to lea "-0x4200(%rsp),%r10"
- if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x94\x24\x00\xfe\xff", 7) == 0) {
- memcpy(Loc, "\x4c\x8d\x94\x24\x00\xbe\xff", 7);
- return true;
- }
-
- // Adjust "lea -0x200(%rsp),%r11" to lea "-0x4200(%rsp),%r11"
- if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x9c\x24\x00\xfe\xff", 7) == 0) {
- memcpy(Loc, "\x4c\x8d\x9c\x24\x00\xbe\xff", 7);
+ // Adjust "lea X(%rsp),%rYY" to lea "(X - 0x4000)(%rsp),%rYY" where rYY could
+ // be r10 or r11. The lea instruction feeds a subsequent compare which checks
+ // if there is X available stack space. Making X larger effectively reserves
+ // that much additional space. The stack grows downward so subtract the value.
+ if (memcmp(Loc, "\x4c\x8d\x94\x24", 4) == 0 ||
+ memcmp(Loc, "\x4c\x8d\x9c\x24", 4) == 0) {
+ // The offset bytes are encoded four bytes after the start of the
+ // instruction.
+ write32le(Loc + 4, read32le(Loc + 4) - 0x4000);
return true;
}
return false;
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=338750&r1=338749&r2=338750&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Aug 2 11:13:40 2018
@@ -838,6 +838,11 @@ static void switchMorestackCallsToMorest
// __morestack inside that function should be switched to
// __morestack_non_split.
Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split");
+ if (!MoreStackNonSplit) {
+ error("Mixing split-stack objects requires a definition of "
+ "__morestack_non_split");
+ return;
+ }
// Sort both collections to compare addresses efficiently.
llvm::sort(MorestackCalls.begin(), MorestackCalls.end(),
@@ -862,8 +867,8 @@ static void switchMorestackCallsToMorest
}
}
-static bool enclosingPrologueAdjusted(uint64_t Offset,
- const DenseSet<Defined *> &Prologues) {
+static bool enclosingPrologueAttempted(uint64_t Offset,
+ const DenseSet<Defined *> &Prologues) {
for (Defined *F : Prologues)
if (F->Value <= Offset && Offset < F->Value + F->Size)
return true;
@@ -879,7 +884,7 @@ void InputSectionBase::adjustSplitStackF
uint8_t *End) {
if (!getFile<ELFT>()->SplitStack)
return;
- DenseSet<Defined *> AdjustedPrologues;
+ DenseSet<Defined *> Prologues;
std::vector<Relocation *> MorestackCalls;
for (Relocation &Rel : Relocations) {
@@ -902,21 +907,26 @@ void InputSectionBase::adjustSplitStackF
if (D->Type != STT_FUNC)
continue;
- if (enclosingPrologueAdjusted(Rel.Offset, AdjustedPrologues))
+ // If the callee's-file was compiled with split stack, nothing to do.
+ auto *IS = cast_or_null<InputSection>(D->Section);
+ if (!IS || IS->getFile<ELFT>()->SplitStack)
+ continue;
+
+ if (enclosingPrologueAttempted(Rel.Offset, Prologues))
continue;
if (Defined *F = getEnclosingFunction<ELFT>(Rel.Offset)) {
- if (Target->adjustPrologueForCrossSplitStack(Buf + F->Value, End)) {
- AdjustedPrologues.insert(F);
+ Prologues.insert(F);
+ if (Target->adjustPrologueForCrossSplitStack(Buf + getOffset(F->Value),
+ End))
continue;
- }
+ if (!getFile<ELFT>()->SomeNoSplitStack)
+ error(lld::toString(this) + ": " + F->getName() +
+ " (with -fsplit-stack) calls " + D->getName() +
+ " (without -fsplit-stack), but couldn't adjust its prologue");
}
- if (!getFile<ELFT>()->SomeNoSplitStack)
- error("function call at " + getErrorLocation(Buf + Rel.Offset) +
- "crosses a split-stack boundary, but unable " +
- "to adjust the enclosing function's prologue");
}
- switchMorestackCallsToMorestackNonSplit(AdjustedPrologues, MorestackCalls);
+ switchMorestackCallsToMorestackNonSplit(Prologues, MorestackCalls);
}
template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
Added: lld/trunk/test/ELF/Inputs/x86-64-split-stack-extra.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-split-stack-extra.s?rev=338750&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-split-stack-extra.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-split-stack-extra.s Thu Aug 2 11:13:40 2018
@@ -0,0 +1,10 @@
+# This file is split out to provide better code coverage.
+ .global split
+ .type split, at function
+split:
+ retq
+
+ .size split,. - split
+
+ .section .note.GNU-stack,"", at progbits
+ .section .note.GNU-split-stack,"", at progbits
Modified: lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s?rev=338750&r1=338749&r2=338750&view=diff
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s (original)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s Thu Aug 2 11:13:40 2018
@@ -1,15 +1,19 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-extra.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t3.o
-# RUN: not ld.lld --defsym __morestack=0x100 %t1.o %t2.o -o %t 2>&1 | FileCheck %s
+# RUN: not ld.lld --defsym __morestack=0x100 --defsym __more_stack_nonsplit=0x200 %t1.o %t2.o %t3.o -o %t 2>&1 | FileCheck %s
# An unknown prologue gives a match failure
-# CHECK: unable to adjust the enclosing function's
+# CHECK: error: {{.*}}.o:(.text): unknown_prologue (with -fsplit-stack) calls non_split (without -fsplit-stack), but couldn't adjust its prologue
# RUN: not ld.lld -r --defsym __morestack=0x100 %t1.o %t2.o -o %t 2>&1 | FileCheck %s -check-prefix=RELOCATABLE
# RELOCATABLE: Cannot mix split-stack and non-split-stack in a relocatable link
+# RUN: not ld.lld --defsym __morestack=0x100 --defsym _start=0x300 %t1.o %t2.o %t3.o -o %t 2>&1 | FileCheck %s -check-prefix=ERROR
+# ERROR: Mixing split-stack objects requires a definition of __morestack_non_split
+
.text
.global unknown_prologue
Modified: lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s?rev=338750&r1=338749&r2=338750&view=diff
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s (original)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s Thu Aug 2 11:13:40 2018
@@ -2,7 +2,7 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o
-# RUN: ld.lld --defsym __morestack=0x100 %t1.o %t2.o -o %t
+# RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o -o %t
# RUN: llvm-objdump -d %t 2>&1 | FileCheck %s
# An unknown prologue ordinarily gives a match failure, except that this
Modified: lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s?rev=338750&r1=338749&r2=338750&view=diff
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s (original)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s Thu Aug 2 11:13:40 2018
@@ -1,8 +1,9 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-extra.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t3.o
-# RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o -o %t -z notext
+# RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o %t3.o -o %t -z notext
# RUN: llvm-objdump -d %t | FileCheck %s
# Avoid duplicating the prologue for every test via macros.
@@ -25,11 +26,11 @@ prologue1_calls_\function_to_call:
.size prologue1_calls_\function_to_call,. - prologue1_calls_\function_to_call
.endm
-.macro prologue2 function_to_call register
+.macro prologue2 function_to_call register compare_amount
.global prologue2_calls_\function_to_call\register
.type prologue2_calls_\function_to_call\register, at function
prologue2_calls_\function_to_call\register:
- lea -0x200(%rsp),%\register
+ lea -\compare_amount(%rsp),%\register
cmp %fs:0x70,%\register
jae 1f
callq __morestack
@@ -65,20 +66,20 @@ prologue1 split
# calls plain __morestack, that any raw bytes written to the prologue
# make sense, and that the register number is preserved.
# CHECK: prologue2_calls_splitr10:
-# CHECK-NEXT: lea{{.*}} -{{[0-9]+}}(%rsp),{{.*}}%r10
+# CHECK-NEXT: lea{{.*}} -512(%rsp),{{.*}}%r10
# CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}}
# CHECK: jae{{.*}}
# CHECK-NEXT: callq{{.*}}<__morestack>
-prologue2 split r10
+prologue2 split r10 0x200
# CHECK: prologue2_calls_splitr11:
-# CHECK-NEXT: lea{{.*}} -{{[0-9]+}}(%rsp),{{.*}}%r11
+# CHECK-NEXT: lea{{.*}} -256(%rsp),{{.*}}%r11
# CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}}
# CHECK: jae{{.*}}
# CHECK-NEXT: callq{{.*}}<__morestack>
-prologue2 split r11
+prologue2 split r11 0x100
# For split-stack code calling non-split-stack code, ensure prologue v1
# calls __morestack_non_split, and that any raw bytes written to the prologue
@@ -95,30 +96,20 @@ prologue1 non_split
# calls __morestack_non_split, that any raw bytes written to the prologue
# make sense, and that the register number is preserved
# CHECK: prologue2_calls_non_splitr10:
-# CHECK-NEXT: lea{{.*$}}
+# CHECK-NEXT: lea{{.*}} -16640(%rsp),{{.*}}%r10
# CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r10
# CHECK: jae{{.*$}}
# CHECK-NEXT: callq{{.*}}<__morestack_non_split>
-prologue2 non_split r10
+prologue2 non_split r10 0x100
# CHECK: prologue2_calls_non_splitr11:
-# CHECK-NEXT: lea{{.*$}}
+# CHECK-NEXT: lea{{.*}} -16896(%rsp),{{.*}}%r11
# CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r11
# CHECK: jae{{.*$}}
# CHECK-NEXT: callq{{.*}}<__morestack_non_split>
-prologue2 non_split r11
-# call foo at plt # for code-coverage.
-
-
-
- .global split
- .type split, at function
-split:
- retq
-
- .size split,. - split
+prologue2 non_split r11 0x200
.section .note.GNU-stack,"", at progbits
.section .note.GNU-split-stack,"", at progbits
More information about the llvm-commits
mailing list