Skip to content

Commit 0379719

Browse files
committed
IRGen: Add option to enable stack protector
Adds frontend option -enable-stack-protector to enable emission of a stack protector. Disabled by default. When enabled enables LLVM's strong stack protection mode. rdar://93677524
1 parent 78f5e0b commit 0379719

File tree

8 files changed

+69
-22
lines changed

8 files changed

+69
-22
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ enum class ReflectionMetadataMode : unsigned {
9494
Runtime, ///< Make reflection metadata fully available.
9595
};
9696

97+
enum class StackProtectorMode : bool { NoStackProtector, StackProtector };
98+
9799
using clang::PointerAuthSchema;
98100

99101
struct PointerAuthOptions : clang::PointerAuthOptions {
@@ -280,6 +282,8 @@ class IRGenOptions {
280282
/// Whether we should run swift specific LLVM optimizations after IRGen.
281283
unsigned DisableSwiftSpecificLLVMOptzns : 1;
282284

285+
unsigned EnableStackProtector : 1;
286+
283287
/// Special codegen for playgrounds.
284288
unsigned Playground : 1;
285289

@@ -457,10 +461,10 @@ class IRGenOptions {
457461
DebugInfoFormat(IRGenDebugInfoFormat::None),
458462
DisableClangModuleSkeletonCUs(false), UseJIT(false),
459463
DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false),
460-
Playground(false), EmitStackPromotionChecks(false),
461-
UseSingleModuleLLVMEmission(false), FunctionSections(false),
462-
PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None),
463-
LLVMLTOKind(IRGenLLVMLTOKind::None),
464+
EnableStackProtector(false), Playground(false),
465+
EmitStackPromotionChecks(false), UseSingleModuleLLVMEmission(false),
466+
FunctionSections(false), PrintInlineTree(false),
467+
EmbedMode(IRGenEmbedMode::None), LLVMLTOKind(IRGenLLVMLTOKind::None),
464468
SwiftAsyncFramePointer(SwiftAsyncFramePointerKind::Auto),
465469
HasValueNamesSetting(false), ValueNames(false),
466470
ReflectionMetadata(ReflectionMetadataMode::Runtime),
@@ -543,6 +547,9 @@ class IRGenOptions {
543547
bool hasMultipleIRGenThreads() const { return !UseSingleModuleLLVMEmission && NumThreads > 1; }
544548
bool shouldPerformIRGenerationInParallel() const { return !UseSingleModuleLLVMEmission && NumThreads != 0; }
545549
bool hasMultipleIGMs() const { return hasMultipleIRGenThreads(); }
550+
StackProtectorMode getStackProtectorMode() const {
551+
return StackProtectorMode(EnableStackProtector);
552+
}
546553
};
547554

548555
} // end namespace swift

include/swift/Option/FrontendOptions.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,13 @@ def concurrency_model_EQ :
10791079
Joined<["-"], "concurrency-model=">,
10801080
Alias<concurrency_model>;
10811081

1082+
def enable_stack_protector :
1083+
Flag<["-"], "enable-stack-protector">,
1084+
HelpText<"Enable the stack protector">;
1085+
def disable_stack_protector :
1086+
Flag<["-"], "disable-stack-protector">,
1087+
HelpText<"Disable the stack-protector">;
1088+
10821089
def enable_new_llvm_pass_manager :
10831090
Flag<["-"], "enable-new-llvm-pass-manager">,
10841091
HelpText<"Enable the new llvm pass manager">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,6 +2407,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
24072407
OPT_enable_new_llvm_pass_manager,
24082408
Opts.LegacyPassManager);
24092409

2410+
Opts.EnableStackProtector =
2411+
Args.hasFlag(OPT_enable_stack_protector, OPT_disable_stack_protector,
2412+
Opts.EnableStackProtector);
2413+
24102414
return false;
24112415
}
24122416

lib/IRGen/GenDecl.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,11 +2246,11 @@ static bool isPointerTo(llvm::Type *ptrTy, llvm::Type *objTy) {
22462246
}
22472247

22482248
/// Get or create an LLVM function with these linkage rules.
2249-
llvm::Function *irgen::createFunction(IRGenModule &IGM,
2250-
LinkInfo &linkInfo,
2249+
llvm::Function *irgen::createFunction(IRGenModule &IGM, LinkInfo &linkInfo,
22512250
const Signature &signature,
22522251
llvm::Function *insertBefore,
2253-
OptimizationMode FuncOptMode) {
2252+
OptimizationMode FuncOptMode,
2253+
StackProtectorMode stackProtect) {
22542254
auto name = linkInfo.getName();
22552255

22562256
llvm::Function *existing = IGM.Module.getFunction(name);
@@ -2282,7 +2282,7 @@ llvm::Function *irgen::createFunction(IRGenModule &IGM,
22822282
.to(fn, linkInfo.isForDefinition());
22832283

22842284
llvm::AttrBuilder initialAttrs;
2285-
IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode);
2285+
IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode, stackProtect);
22862286
// Merge initialAttrs with attrs.
22872287
auto updatedAttrs = signature.getAttributes().addFnAttributes(
22882288
IGM.getLLVMContext(), initialAttrs);
@@ -3059,7 +3059,7 @@ void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) {
30593059
LinkInfo implLink = LinkInfo::get(*this, entity, ForDefinition);
30603060
auto implFn =
30613061
createFunction(*this, implLink, signature, nullptr /*insertBefore*/,
3062-
f->getOptimizationMode());
3062+
f->getOptimizationMode(), shouldEmitStackProtector(f));
30633063
implFn->addFnAttr(llvm::Attribute::NoInline);
30643064

30653065
IRGenFunction IGF(*this, implFn);
@@ -3168,6 +3168,10 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
31683168
return thunk;
31693169
}
31703170

3171+
StackProtectorMode IRGenModule::shouldEmitStackProtector(SILFunction *f) {
3172+
return IRGen.Opts.getStackProtectorMode();
3173+
}
3174+
31713175
/// Find the entry point for a SIL function.
31723176
llvm::Function *IRGenModule::getAddrOfSILFunction(
31733177
SILFunction *f, ForDefinition_t forDefinition,
@@ -3263,7 +3267,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
32633267
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
32643268

32653269
fn = createFunction(*this, link, signature, insertBefore,
3266-
f->getOptimizationMode());
3270+
f->getOptimizationMode(), shouldEmitStackProtector(f));
32673271

32683272
// If `hasCReferences` is true, then the function is either marked with
32693273
// @_silgen_name OR @_cdecl. If it is the latter, it must have a definition

lib/IRGen/GenDecl.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,11 @@ namespace irgen {
4141
llvm::GlobalValue *global,
4242
const LinkEntity &entity);
4343

44-
llvm::Function *createFunction(IRGenModule &IGM,
45-
LinkInfo &linkInfo,
46-
const Signature &signature,
47-
llvm::Function *insertBefore = nullptr,
48-
OptimizationMode FuncOptMode =
49-
OptimizationMode::NotSet);
44+
llvm::Function *createFunction(
45+
IRGenModule &IGM, LinkInfo &linkInfo, const Signature &signature,
46+
llvm::Function *insertBefore = nullptr,
47+
OptimizationMode FuncOptMode = OptimizationMode::NotSet,
48+
StackProtectorMode stackProtect = StackProtectorMode::NoStackProtector);
5049

5150
llvm::GlobalVariable *
5251
createVariable(IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *objectType,

lib/IRGen/IRGenModule.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,8 +1246,9 @@ void IRGenModule::setHasNoFramePointer(llvm::Function *F) {
12461246
}
12471247

12481248
/// Construct initial function attributes from options.
1249-
void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
1250-
OptimizationMode FuncOptMode) {
1249+
void IRGenModule::constructInitialFnAttributes(
1250+
llvm::AttrBuilder &Attrs, OptimizationMode FuncOptMode,
1251+
StackProtectorMode stackProtector) {
12511252
// Add the default attributes for the Clang configuration.
12521253
clang::CodeGen::addDefaultFunctionDefinitionAttributes(getClangCGM(), Attrs);
12531254

@@ -1261,6 +1262,10 @@ void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
12611262
Attrs.removeAttribute(llvm::Attribute::MinSize);
12621263
Attrs.removeAttribute(llvm::Attribute::OptimizeForSize);
12631264
}
1265+
if (stackProtector == StackProtectorMode::StackProtector) {
1266+
Attrs.addAttribute(llvm::Attribute::StackProtectStrong);
1267+
Attrs.addAttribute("stack-protector-buffer-size", llvm::utostr(8));
1268+
}
12641269
}
12651270

12661271
llvm::AttributeList IRGenModule::constructInitialAttributes() {

lib/IRGen/IRGenModule.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "SwiftTargetInfo.h"
2323
#include "TypeLayout.h"
2424
#include "swift/AST/Decl.h"
25+
#include "swift/AST/IRGenOptions.h"
2526
#include "swift/AST/LinkLibrary.h"
2627
#include "swift/AST/Module.h"
2728
#include "swift/AST/ReferenceCounting.h"
@@ -32,8 +33,8 @@
3233
#include "swift/Basic/OptimizationMode.h"
3334
#include "swift/Basic/SuccessorMap.h"
3435
#include "swift/IRGen/ValueWitness.h"
35-
#include "swift/SIL/SILFunction.h"
3636
#include "swift/SIL/RuntimeEffect.h"
37+
#include "swift/SIL/SILFunction.h"
3738
#include "llvm/ADT/DenseMap.h"
3839
#include "llvm/ADT/DenseSet.h"
3940
#include "llvm/ADT/Hashing.h"
@@ -1441,12 +1442,14 @@ private: \
14411442
/// invalid.
14421443
bool finalize();
14431444

1444-
void constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
1445-
OptimizationMode FuncOptMode =
1446-
OptimizationMode::NotSet);
1445+
void constructInitialFnAttributes(
1446+
llvm::AttrBuilder &Attrs,
1447+
OptimizationMode FuncOptMode = OptimizationMode::NotSet,
1448+
StackProtectorMode stackProtect = StackProtectorMode::NoStackProtector);
14471449
void setHasNoFramePointer(llvm::AttrBuilder &Attrs);
14481450
void setHasNoFramePointer(llvm::Function *F);
14491451
llvm::AttributeList constructInitialAttributes();
1452+
StackProtectorMode shouldEmitStackProtector(SILFunction *f);
14501453

14511454
void emitProtocolDecl(ProtocolDecl *D);
14521455
void emitEnumDecl(EnumDecl *D);

test/IRGen/stack_protector.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -enable-stack-protector -emit-ir %s -o - | %FileCheck %s
2+
3+
@_silgen_name("escape")
4+
func f<T>(_ arg: UnsafePointer<T>)
5+
6+
public func escapeGenericValue<T>(_ t: T) {
7+
withUnsafePointer(to: t) { ptr in
8+
f(ptr)
9+
}
10+
}
11+
12+
// CHECK: define {{.*}}swiftcc void @"$s15stack_protector21requestStackProtectoryyF"() [[SSPATTRS:#[0-9]+]] {
13+
public func requestStackProtector() {
14+
var x: Int = 0
15+
escapeGenericValue(x)
16+
}
17+
18+
// CHECK: [[SSPATTRS]] = { sspstrong {{.*}}"stack-protector-buffer-size"="8"

0 commit comments

Comments
 (0)