[lld] r337332 - Implement framework for linking split-stack object files, and x86_64 support.
Sterling Augustine via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 17 16:16:02 PDT 2018
Author: saugustine
Date: Tue Jul 17 16:16:02 2018
New Revision: 337332
URL: http://llvm.org/viewvc/llvm-project?rev=337332&view=rev
Log:
Implement framework for linking split-stack object files, and x86_64 support.
Added:
lld/trunk/test/ELF/Inputs/x86-64-split-stack-main.s
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
Removed:
lld/trunk/test/ELF/splitstacks.s
Modified:
lld/trunk/ELF/Arch/X86_64.cpp
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Tue Jul 17 16:16:02 2018
@@ -43,6 +43,8 @@ public:
void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ bool adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const override;
private:
void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
@@ -469,6 +471,40 @@ void X86_64<ELFT>::relaxGot(uint8_t *Loc
write32le(Loc - 1, Val + 1);
}
+// A split-stack prologue starts by checking the amount of stack remaining
+// in one of two ways:
+// A) Comparing of the stack pointer to a field in the tcb.
+// B) Or a load of a stack pointer offset with an lea to r10 or r11.
+template <>
+bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ // 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) {
+ 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);
+ return true;
+ }
+ return false;
+}
+
+template <>
+bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ llvm_unreachable("Target doesn't support split stacks.");
+}
+
// These nonstandard PLT entries are to migtigate Spectre v2 security
// vulnerability. In order to mitigate Spectre v2, we want to avoid indirect
// branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Jul 17 16:16:02 2018
@@ -645,13 +645,24 @@ InputSectionBase *ObjFile<ELFT>::createI
if (Name == ".note.GNU-stack")
return &InputSection::Discarded;
- // Split stacks is a feature to support a discontiguous stack. At least
- // as of 2017, it seems that the feature is not being used widely.
- // Only GNU gold supports that. We don't. For the details about that,
- // see https://gcc.gnu.org/wiki/SplitStacks
+ // Split stacks is a feature to support a discontiguous stack,
+ // commonly used in the programming language Go. For the details,
+ // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
+ // for split stack will include a .note.GNU-split-stack section.
if (Name == ".note.GNU-split-stack") {
- error(toString(this) +
- ": object file compiled with -fsplit-stack is not supported");
+ if (Config->Relocatable) {
+ error("Cannot mix split-stack and non-split-stack in a relocatable link");
+ return &InputSection::Discarded;
+ }
+ this->SplitStack = true;
+ return &InputSection::Discarded;
+ }
+
+ // An object file cmpiled for split stack, but where some of the
+ // functions were compiled with the no_split_stack_attribute will
+ // include a .note.GNU-no-split-stack section.
+ if (Name == ".note.GNU-no-split-stack") {
+ this->SomeNoSplitStack = true;
return &InputSection::Discarded;
}
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Tue Jul 17 16:16:02 2018
@@ -207,6 +207,14 @@ public:
// symbol table.
StringRef SourceFile;
+ // True if the file defines functions compiled with
+ // -fsplit-stack. Usually false.
+ bool SplitStack = false;
+
+ // True if the file defines functions compiled with -fsplit-stack,
+ // but had one or more functions with the no_split_stack attribute.
+ bool SomeNoSplitStack = false;
+
private:
void
initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Jul 17 16:16:02 2018
@@ -14,6 +14,7 @@
#include "LinkerScript.h"
#include "OutputSections.h"
#include "Relocations.h"
+#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
@@ -26,7 +27,10 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/xxhash.h"
+#include <algorithm>
#include <mutex>
+#include <set>
+#include <vector>
using namespace llvm;
using namespace llvm::ELF;
@@ -212,6 +216,17 @@ InputSection *InputSectionBase::getLinkO
return cast<InputSection>(File->getSections()[Link]);
}
+// Find a function symbol that encloses a given location.
+template <class ELFT>
+Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) {
+ for (Symbol *B : File->getSymbols())
+ if (Defined *D = dyn_cast<Defined>(B))
+ if (D->Section == this && D->Type == STT_FUNC &&
+ D->Value <= Offset && Offset < D->Value + D->Size)
+ return D;
+ return nullptr;
+}
+
// Returns a source location string. Used to construct an error message.
template <class ELFT>
std::string InputSectionBase::getLocation(uint64_t Offset) {
@@ -230,12 +245,8 @@ std::string InputSectionBase::getLocatio
if (SrcFile.empty())
SrcFile = toString(File);
- // Find a function symbol that encloses a given location.
- for (Symbol *B : File->getSymbols())
- if (auto *D = dyn_cast<Defined>(B))
- if (D->Section == this && D->Type == STT_FUNC)
- if (D->Value <= Offset && Offset < D->Value + D->Size)
- return SrcFile + ":(function " + toString(*D) + ")";
+ if (Defined *D = getEnclosingFunction<ELFT>(Offset))
+ return SrcFile + ":(function " + toString(*D) + ")";
// If there's no symbol, print out the offset in the section.
return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str();
@@ -747,6 +758,9 @@ static void relocateNonAllocForRelocatab
template <class ELFT>
void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
+ if (Flags & SHF_EXECINSTR)
+ adjustSplitStackFunctionPrologues<ELFT>(Buf, BufEnd);
+
if (Flags & SHF_ALLOC) {
relocateAlloc(Buf, BufEnd);
return;
@@ -825,6 +839,103 @@ void InputSectionBase::relocateAlloc(uin
}
}
+// For each function-defining prologue, find any calls to __morestack,
+// and replace them with calls to __morestack_non_split.
+static void switchMorestackCallsToMorestackNonSplit(
+ llvm::DenseSet<Defined *>& Prologues,
+ std::vector<Relocation *>& MorestackCalls) {
+
+ // If the target adjusted a function's prologue, all calls to
+ // __morestack inside that function should be switched to
+ // __morestack_non_split.
+ Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split");
+
+ // Sort both collections to compare addresses efficiently.
+ llvm::sort(MorestackCalls.begin(), MorestackCalls.end(),
+ [](const Relocation *L, const Relocation *R) {
+ return L->Offset < R->Offset;
+ });
+ std::vector<Defined *> Functions(Prologues.begin(), Prologues.end());
+ llvm::sort(
+ Functions.begin(), Functions.end(),
+ [](const Defined *L, const Defined *R) { return L->Value < R->Value; });
+
+ auto It = MorestackCalls.begin();
+ for (Defined *F : Functions) {
+ // Find the first call to __morestack within the function.
+ while (It != MorestackCalls.end() && (*It)->Offset < F->Value)
+ ++It;
+ // Adjust all calls inside the function.
+ while (It != MorestackCalls.end() && (*It)->Offset < F->Value + F->Size) {
+ (*It)->Sym = MoreStackNonSplit;
+ ++It;
+ }
+ }
+}
+
+static bool
+enclosingPrologueAdjusted(uint64_t Offset,
+ const llvm::DenseSet<Defined *> &Prologues) {
+ for (Defined *F : Prologues)
+ if (F->Value <= Offset && Offset < F->Value + F->Size)
+ return true;
+ return false;
+}
+
+// If a function compiled for split stack calls a function not
+// compiled for split stack, then the caller needs its prologue
+// adjusted to ensure that the called function will have enough stack
+// available. Find those functions, and adjust their prologues.
+template <class ELFT>
+void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf,
+ uint8_t *End) {
+ if (!getFile<ELFT>()->SplitStack)
+ return;
+ llvm::DenseSet<Defined *> AdjustedPrologues;
+ std::vector<Relocation *> MorestackCalls;
+
+ for (Relocation &Rel : Relocations) {
+ // Local symbols can't possibly be cross-calls, and should have been
+ // resolved long before this line.
+ if (Rel.Sym->isLocal())
+ continue;
+
+ Defined *D = dyn_cast<Defined>(Rel.Sym);
+ // A reference to an undefined symbol was an error, and should not
+ // have gotten to this point.
+ if (!D)
+ continue;
+
+ // Ignore calls into the split-stack api.
+ if (D->getName().startswith("__morestack")) {
+ if (D->getName().equals("__morestack"))
+ MorestackCalls.push_back(&Rel);
+ continue;
+ }
+
+ // A relocation to non-function isn't relevant. Sometimes
+ // __morestack is not marked as a function, so this check comes
+ // after the name check.
+ if (D->Type != STT_FUNC)
+ continue;
+
+ if (enclosingPrologueAdjusted(Rel.Offset, AdjustedPrologues))
+ continue;
+
+ if (Defined *F = getEnclosingFunction<ELFT>(Rel.Offset)) {
+ if (Target->adjustPrologueForCrossSplitStack(Buf + F->Value, End)) {
+ AdjustedPrologues.insert(F);
+ continue;
+ }
+ }
+ 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);
+}
+
template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
if (Type == SHT_NOBITS)
return;
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Tue Jul 17 16:16:02 2018
@@ -106,7 +106,7 @@ public:
static bool classof(const SectionBase *S) { return S->kind() != Output; }
- // The file which contains this section. It's dynamic type is always
+ // The file which contains this section. Its dynamic type is always
// ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as
// its static type.
InputFile *File;
@@ -164,6 +164,11 @@ public:
InputSection *getLinkOrderDep() const;
+ // Get the function symbol that encloses this offset from within the
+ // section.
+ template <class ELFT>
+ Defined *getEnclosingFunction(uint64_t Offset);
+
// Compilers emit zlib-compressed debug sections if the -gz option
// is given. This function checks if this section is compressed, and
// if so, decompress in memory.
@@ -185,6 +190,15 @@ public:
// This vector contains such "cooked" relocations.
std::vector<Relocation> Relocations;
+ // A function compiled with -fsplit-stack calling a function
+ // compiled without -fsplit-stack needs its prologue adjusted. Find
+ // such functions and adjust their prologues. This is very similar
+ // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more
+ // information.
+ template <typename ELFT>
+ void adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End);
+
+
template <typename T> llvm::ArrayRef<T> getDataAs() const {
size_t S = Data.size();
assert(S % sizeof(T) == 0);
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Tue Jul 17 16:16:02 2018
@@ -130,6 +130,12 @@ bool TargetInfo::needsThunk(RelExpr Expr
return false;
}
+bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const {
+ llvm_unreachable("Target doesn't support split stacks.");
+}
+
+
bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {
return true;
}
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=337332&r1=337331&r2=337332&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Tue Jul 17 16:16:02 2018
@@ -59,6 +59,13 @@ public:
virtual bool needsThunk(RelExpr Expr, RelType RelocType,
const InputFile *File, uint64_t BranchAddr,
const Symbol &S) const;
+
+ // The function with a prologue starting at Loc was compiled with
+ // -fsplit-stack and it calls a function compiled without. Adjust the prologue
+ // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.
+ virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc,
+ uint8_t *End) const;
+
// Return true if we can reach Dst from Src with Relocation RelocType
virtual bool inBranchRange(RelType Type, uint64_t Src,
uint64_t Dst) const;
Added: lld/trunk/test/ELF/Inputs/x86-64-split-stack-main.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-split-stack-main.s?rev=337332&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-split-stack-main.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-split-stack-main.s Tue Jul 17 16:16:02 2018
@@ -0,0 +1,16 @@
+ .text
+
+ .global non_split
+ .type non_split, at function
+non_split:
+ retq
+ .size non_split,. - non_split
+
+ .global non_function_text_symbol
+non_function_text_symbol:
+ .byte 0x01
+ .type non_function_text_symbol, at STT_OBJECT
+ .size non_function_text_symbol, 1
+
+
+ .section .note.GNU-stack,"", at progbits
Removed: lld/trunk/test/ELF/splitstacks.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/splitstacks.s?rev=337331&view=auto
==============================================================================
--- lld/trunk/test/ELF/splitstacks.s (original)
+++ lld/trunk/test/ELF/splitstacks.s (removed)
@@ -1,11 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
-
-# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck %s
-# CHECK: .o: object file compiled with -fsplit-stack is not supported
-
-.globl _start
-_start:
- nop
-
-.section .note.GNU-split-stack,"", at progbits
Added: 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=337332&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s (added)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-fail.s Tue Jul 17 16:16:02 2018
@@ -0,0 +1,31 @@
+# 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: not ld.lld --defsym __morestack=0x100 %t1.o %t2.o -o %t 2>&1 | FileCheck %s
+
+# An unknown prologue gives a match failure
+# CHECK: unable to adjust the enclosing function's
+
+# 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
+
+ .text
+
+ .global unknown_prologue
+ .type unknown_prologue, at function
+unknown_prologue:
+ push %rbp
+ mov %rsp,%rbp
+ cmp %fs:0x70,%rsp
+ jae 1f
+ callq __morestack
+ retq
+1:
+ callq non_split
+ leaveq
+ retq
+
+ .size unknown_prologue,. - unknown_prologue
+
+ .section .note.GNU-split-stack,"", at progbits
Added: 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=337332&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s (added)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-silent.s Tue Jul 17 16:16:02 2018
@@ -0,0 +1,32 @@
+# 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: ld.lld --defsym __morestack=0x100 %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
+# object file includes a .note.GNU-no-split-stack section, which tells the
+# linker to expect such prologues, and therefore not error.
+
+# CHECK: __morestack
+
+ .text
+
+ .global unknown_prologue
+ .type unknown_prologue, at function
+unknown_prologue:
+ push %rbp
+ mov %rsp,%rbp
+ cmp %fs:0x70,%rsp
+ jae 1f
+ callq __morestack
+ retq
+1:
+ callq non_split
+ leaveq
+ retq
+
+ .size unknown_prologue,. - unknown_prologue
+ .section .note.GNU-split-stack,"", at progbits
+ .section .note.GNU-no-split-stack,"", at progbits
Added: 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=337332&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s (added)
+++ lld/trunk/test/ELF/x86-64-split-stack-prologue-adjust-success.s Tue Jul 17 16:16:02 2018
@@ -0,0 +1,124 @@
+# 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: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o -o %t -z notext
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+# Avoid duplicating the prologue for every test via macros.
+
+.macro prologue1 function_to_call
+ .global prologue1_calls_\function_to_call
+ .type prologue1_calls_\function_to_call, at function
+prologue1_calls_\function_to_call:
+ cmp %fs:0x70,%rsp
+ jae 1f
+ callq __morestack
+ retq
+1:
+ # Various and duplicate calls to ensure every code path is taken.
+ callq \function_to_call
+ callq \function_to_call
+ callq 1b
+ callq non_function_text_symbol
+ retq
+ .size prologue1_calls_\function_to_call,. - prologue1_calls_\function_to_call
+.endm
+
+.macro prologue2 function_to_call register
+ .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
+ cmp %fs:0x70,%\register
+ jae 1f
+ callq __morestack
+ retq
+1:
+ # Various and duplicate calls to ensure every code path is taken.
+ callq \function_to_call
+ callq \function_to_call
+ callq 1b
+ callq non_function_text_symbol
+ retq
+ .size prologue2_calls_\function_to_call\register,. - prologue2_calls_\function_to_call\register
+.endm
+
+ .local foo
+foo:
+ .section .text,"ax", at progbits
+ .quad foo
+
+ .text
+
+# For split-stack code calling split-stack code, ensure prologue v1 still
+# calls plain __morestack, and that any raw bytes written to the prologue
+# make sense.
+# CHECK: prologue1_calls_split:
+# CHECK-NEXT: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%rsp
+# CHECK: jae{{.*$}}
+# CHECK-NEXT: callq{{.*}}<__morestack>
+
+prologue1 split
+
+# For split-stack code calling split-stack code, ensure prologue v2 still
+# 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: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}}
+# CHECK: jae{{.*}}
+# CHECK-NEXT: callq{{.*}}<__morestack>
+
+prologue2 split r10
+
+# CHECK: prologue2_calls_splitr11:
+# CHECK-NEXT: lea{{.*}} -{{[0-9]+}}(%rsp),{{.*}}%r11
+# CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}}
+# CHECK: jae{{.*}}
+# CHECK-NEXT: callq{{.*}}<__morestack>
+
+prologue2 split r11
+
+# 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
+# make sense.
+# CHECK: prologue1_calls_non_split:
+# CHECK-NEXT: stc{{.*$}}
+# CHECK-NEXT: nopl{{.*$}}
+# CHECK: jae{{.*$}}
+# CHECK-NEXT: callq{{.*}}<__morestack_non_split>
+
+prologue1 non_split
+
+# For split-stack code calling non-split-stack code, ensure prologue v2
+# 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: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r10
+# CHECK: jae{{.*$}}
+# CHECK-NEXT: callq{{.*}}<__morestack_non_split>
+
+prologue2 non_split r10
+
+# CHECK: prologue2_calls_non_splitr11:
+# CHECK-NEXT: lea{{.*$}}
+# 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
+
+ .section .note.GNU-stack,"", at progbits
+ .section .note.GNU-split-stack,"", at progbits
More information about the llvm-commits
mailing list