Skip to content

Commit 7a7ced9

Browse files
committed
[StackProtector] Introduce stack-protect-refinement pass to remove unnecessary protections.
This pass uses StackSafetyGlobalAnalysis to reduce number of functions that require stack protector.
1 parent 531cf82 commit 7a7ced9

30 files changed

+208
-18
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===- StackProtectRefinement.h - Stack Protect Refinement ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Remove ssp attributes from functions where we can prove it is safe.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_TRANSFORMS_SCALAR_STACKPROTECTREFINEMENT_H
14+
#define LLVM_TRANSFORMS_SCALAR_STACKPROTECTREFINEMENT_H
15+
16+
#include "llvm/Analysis/StackSafetyAnalysis.h"
17+
#include "llvm/IR/PassManager.h"
18+
19+
namespace llvm {
20+
21+
class BasicBlock;
22+
class Function;
23+
class Instruction;
24+
25+
class StackProtectRefinementPass
26+
: public PassInfoMixin<StackProtectRefinementPass> {
27+
public:
28+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
29+
30+
private:
31+
void processFunction(Function &F) const;
32+
33+
const StackSafetyGlobalInfo *SSI;
34+
};
35+
} // end namespace llvm
36+
37+
#endif // LLVM_TRANSFORMS_SCALAR_STACKPROTECTREFINEMENT_H

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@
333333
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
334334
#include "llvm/Transforms/Scalar/Sink.h"
335335
#include "llvm/Transforms/Scalar/SpeculativeExecution.h"
336+
#include "llvm/Transforms/Scalar/StackProtectRefinement.h"
336337
#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"
337338
#include "llvm/Transforms/Scalar/StructurizeCFG.h"
338339
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"
128128
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
129129
#include "llvm/Transforms/Scalar/SpeculativeExecution.h"
130+
#include "llvm/Transforms/Scalar/StackProtectRefinement.h"
130131
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
131132
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
132133
#include "llvm/Transforms/Utils/AddDiscriminators.h"
@@ -1278,6 +1279,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
12781279
else
12791280
MPM.addPass(buildInlinerPipeline(Level, Phase));
12801281

1282+
if (Level != OptimizationLevel::O0)
1283+
MPM.addPass(StackProtectRefinementPass());
1284+
12811285
// Remove any dead arguments exposed by cleanups, constant folding globals,
12821286
// and argument promotion.
12831287
MPM.addPass(DeadArgumentEliminationPass());
@@ -1944,6 +1948,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
19441948
// is fixed.
19451949
MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr));
19461950

1951+
MPM.addPass(StackProtectRefinementPass());
1952+
19471953
// Stop here at -O1.
19481954
if (Level == OptimizationLevel::O1) {
19491955
// The LowerTypeTestsPass needs to run to lower type metadata and the

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ MODULE_PASS("scc-oz-module-inliner",
160160
buildInlinerPipeline(OptimizationLevel::Oz,
161161
ThinOrFullLTOPhase::None))
162162
MODULE_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass())
163+
MODULE_PASS("stack-protect-refinement", StackProtectRefinementPass())
163164
MODULE_PASS("strip", StripSymbolsPass())
164165
MODULE_PASS("strip-dead-debug-info", StripDeadDebugInfoPass())
165166
MODULE_PASS("strip-dead-prototypes", StripDeadPrototypesPass())

llvm/lib/Transforms/Scalar/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ add_llvm_component_library(LLVMScalarOpts
7575
SimplifyCFGPass.cpp
7676
Sink.cpp
7777
SpeculativeExecution.cpp
78+
StackProtectRefinement.cpp
7879
StraightLineStrengthReduce.cpp
7980
StructurizeCFG.cpp
8081
TailRecursionElimination.cpp
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===- StackProtectRefinement.cpp - Stack Protect Refinement --------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Transforms/Scalar/StackProtectRefinement.h"
10+
#include "llvm/ADT/Statistic.h"
11+
#include "llvm/IR/InstIterator.h"
12+
#include "llvm/IR/Instructions.h"
13+
#include "llvm/Support/CommandLine.h"
14+
15+
using namespace llvm;
16+
17+
#define DEBUG_TYPE "stack-protect-refinement"
18+
19+
STATISTIC(
20+
NumFuncsWithAllocaInst,
21+
"Number of functions with an instruction to allocate memory on the stack");
22+
STATISTIC(NumFuncsWithRemovedStackProtectAttr,
23+
"Number of functions with alloca and removed stack protect attr");
24+
25+
static cl::opt<bool>
26+
UseStackSafety("optimize-ssp", cl::init(true), cl::Hidden,
27+
cl::desc("Use Stack Safety analysis results"));
28+
29+
void StackProtectRefinementPass::processFunction(Function &F) const {
30+
31+
bool hasAlloca = false;
32+
33+
for (auto &I : instructions(&F)) {
34+
if (auto *AI = dyn_cast<AllocaInst>(&I)) {
35+
hasAlloca = true;
36+
if (!SSI->isSafe(*AI)) {
37+
NumFuncsWithAllocaInst++;
38+
return;
39+
}
40+
}
41+
}
42+
43+
if (hasAlloca) {
44+
NumFuncsWithAllocaInst++;
45+
NumFuncsWithRemovedStackProtectAttr++;
46+
}
47+
48+
F.removeFnAttr(Attribute::StackProtect);
49+
F.removeFnAttr(Attribute::StackProtectStrong);
50+
}
51+
52+
PreservedAnalyses StackProtectRefinementPass::run(Module &M,
53+
ModuleAnalysisManager &MAM) {
54+
if (!UseStackSafety)
55+
return PreservedAnalyses::all();
56+
57+
SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M);
58+
for (Function &F : M)
59+
if (F.hasFnAttribute(Attribute::StackProtect) ||
60+
F.hasFnAttribute(Attribute::StackProtectStrong))
61+
processFunction(F);
62+
63+
return PreservedAnalyses::all();
64+
}

llvm/test/CodeGen/AArch64/GlobalISel/dynamic-alloca-lifetime.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc -mtriple aarch64-unknown-unknown -global-isel \
1+
; RUN: llc -optimize-ssp=false -mtriple aarch64-unknown-unknown -global-isel \
22
; RUN: -no-stack-coloring=false -pass-remarks-missed=gisel* < %s \
33
; RUN: 2>&1 | FileCheck %s
44

llvm/test/CodeGen/ARM/ifcvt-regmask-noreturn.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc %s -o - -verify-machineinstrs | FileCheck %s
1+
; RUN: llc %s -o - -optimize-ssp=false -verify-machineinstrs | FileCheck %s
22

33
target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
44
target triple = "thumbv7s-apple-ios8.0.0"

llvm/test/CodeGen/ARM/ssp-data-layout.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc < %s -frame-pointer=all -mcpu=cortex-a8 -mtriple arm-linux-gnu -target-abi=apcs -o - | FileCheck %s
1+
; RUN: llc < %s -optimize-ssp=false -frame-pointer=all -mcpu=cortex-a8 -mtriple arm-linux-gnu -target-abi=apcs -o - | FileCheck %s
22
; This test is fairly fragile. The goal is to ensure that "large" stack
33
; objects are allocated closest to the stack protector (i.e., farthest away
44
; from the Stack Pointer.) In standard SSP mode this means that large (>=

llvm/test/CodeGen/X86/2009-04-14-IllegalRegs.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2-
; RUN: llc < %s -mtriple=i386-apple-darwin -O0 -regalloc=fast | FileCheck %s
2+
; RUN: llc < %s -optimize-ssp=false -mtriple=i386-apple-darwin -O0 -regalloc=fast | FileCheck %s
33
; rdar://6787136
44

55
%struct.X = type { i8, [32 x i8] }

0 commit comments

Comments
 (0)