Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -139,6 +139,9 @@ // st_name of the symbol. std::vector> KeptLocalSyms; + // If an object file compiled in split stack mode. + bool SplitStacks = false; + private: void initializeSections(llvm::DenseSet &ComdatGroups); void initializeSymbols(); Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -245,6 +245,15 @@ if (Name == ".note.GNU-stack") return InputSection::Discarded; + // .note.GNU-split-stack is a marker section that used if object file compiled + // in split stack mode. If we are not generating relocatable output, then + // such section can be discarded. + if (Name == ".note.GNU-split-stack") { + SplitStacks = true; + if (!Config->Relocatable) + return InputSection::Discarded; + } + // A MIPS object file has a special section that contains register // usage info, which needs to be handled by the linker specially. if (Config->EMachine == EM_MIPS && Name == ".reginfo") { Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -35,7 +35,7 @@ // All input object files must be for the same architecture // (e.g. it does not make sense to link x86 object files with // MIPS object files.) This function checks for that error. -template static bool isCompatible(InputFile *FileP) { +template static bool isCompatibleArch(InputFile *FileP) { auto *F = dyn_cast>(FileP); if (!F) return true; @@ -49,11 +49,25 @@ return false; } +// If relocatable output (-r) is used to link an object with the split-stack +// note with an object without the split-stack note, issue an error. +// https://gcc.gnu.org/wiki/SplitStacks +template +static bool isCompatibleObj(ObjectFile *O, ObjList &Files) { + if (!Config->Relocatable) + return true; + bool Comp = Files.front()->SplitStacks == O->SplitStacks; + if (!Comp) + error("when using -r, cannot mix split-stack vs non-split-stack: " + + Files.front()->getName() + " " + O->getName()); + return Comp; +} + // Add symbols in File to the symbol table. template void SymbolTable::addFile(std::unique_ptr File) { InputFile *FileP = File.get(); - if (!isCompatible(FileP)) + if (!isCompatibleArch(FileP)) return; // .a file @@ -92,6 +106,8 @@ auto *F = cast>(FileP); ObjectFiles.emplace_back(cast>(File.release())); F->parse(ComdatGroups); + if (!isCompatibleObj(F, ObjectFiles)) + return; for (SymbolBody *B : F->getSymbols()) resolve(B); } Index: test/ELF/relocatable-splitstacks.s =================================================================== --- test/ELF/relocatable-splitstacks.s +++ test/ELF/relocatable-splitstacks.s @@ -0,0 +1,33 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: echo "" > %t.s +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t2.o + +## Check that when generating relocatable output we should not be +## able to mix the files with different splitstacks mode. +# RUN: not ld.lld -r %t1.o %t2.o -o %t 2>&1 | \ +# RUN: FileCheck --check-prefix=MIX %s +# MIX: when using -r, cannot mix split-stack vs non-split-stack: + +## Check that we are able to generate relocatable output when +## linking files with the same splitstacks mode. +# RUN: ld.lld -r %t2.o %t2.o -o %t2 2>&1 +# RUN: llvm-readobj %t2 > /dev/null + +## Check that .note.GNU-split-stack is not discarded when using -r +# RUN: ld.lld -r %t1.o -o %t3 +# RUN: llvm-readobj -s %t3 | FileCheck %s --check-prefix=KEEPNOTE +# KEEPNOTE: Sections [ +# KEEPNOTE: Name: .note.GNU-split-stack + +## Check that .note.GNU-split-stack is discarded when not using -r +# RUN: ld.lld %t1.o -o %t4 +# RUN: llvm-readobj -s %t4 | FileCheck %s --check-prefix=REMOVENOTE +# REMOVENOTE: Sections [ +# REMOVENOTE-NOT: Name: .note.GNU-split-stack + +.globl _start +_start: + nop + +.section .note.GNU-split-stack,"",@progbits