Skip to content

Commit f1c7f73

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 f1c7f73

30 files changed

+203
-18
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
#ifndef LLVM_TRANSFORMS_SCALAR_STACK_PROTECT_REFINEMENT_H
10+
#define LLVM_TRANSFORMS_SCALAR_STACK_PROTECT_REFINEMENT_H
11+
12+
#include "llvm/Analysis/StackSafetyAnalysis.h"
13+
#include "llvm/IR/PassManager.h"
14+
15+
namespace llvm {
16+
17+
class BasicBlock;
18+
class Function;
19+
class Instruction;
20+
21+
class StackProtectRefinementPass
22+
: public PassInfoMixin<StackProtectRefinementPass> {
23+
public:
24+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
25+
26+
private:
27+
void processFunction(Function &F) const;
28+
29+
const StackSafetyGlobalInfo *SSI;
30+
};
31+
} // end namespace llvm
32+
33+
#endif // LLVM_TRANSFORMS_SCALAR_STACK_PROTECT_REFINEMENT_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
@@ -59,6 +59,7 @@ MODULE_PASS("canonicalize-aliases", CanonicalizeAliasesPass())
5959
MODULE_PASS("check-debugify", NewPMCheckDebugifyPass())
6060
MODULE_PASS("constmerge", ConstantMergePass())
6161
MODULE_PASS("coro-cleanup", CoroCleanupPass())
62+
MODULE_PASS("stack-protect-refinement", StackProtectRefinementPass())
6263
MODULE_PASS("coro-early", CoroEarlyPass())
6364
MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
6465
MODULE_PASS("ctx-instr-gen",

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: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
if (hasAlloca) {
43+
NumFuncsWithAllocaInst++;
44+
NumFuncsWithRemovedStackProtectAttr++;
45+
}
46+
47+
F.removeFnAttr(Attribute::StackProtect);
48+
F.removeFnAttr(Attribute::StackProtectStrong);
49+
}
50+
51+
PreservedAnalyses StackProtectRefinementPass::run(Module &M,
52+
ModuleAnalysisManager &MAM) {
53+
if (!UseStackSafety)
54+
return PreservedAnalyses::all();
55+
56+
SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M);
57+
for (Function &F : M)
58+
if (F.hasFnAttribute(Attribute::StackProtect) ||
59+
F.hasFnAttribute(Attribute::StackProtectStrong))
60+
processFunction(F);
61+
62+
return PreservedAnalyses::all();
63+
}

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)