summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2017-07-07 00:48:25 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2017-07-07 00:48:25 +0000
commit2a7a4bc1c9252ed8e3d9a782504c64e885a26bce (patch)
tree0c731abdd1357079689f1e0bf8ffaae9ee1ab292 /llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
parent760a261e1e79ca591e209a6b9bdff14c10243f5a (diff)
downloadbcm5719-llvm-2a7a4bc1c9252ed8e3d9a782504c64e885a26bce.tar.gz
bcm5719-llvm-2a7a4bc1c9252ed8e3d9a782504c64e885a26bce.zip
Copy arguments passed by value into explicit allocas for ASan.
ASan determines the stack layout from alloca instructions. Since arguments marked as "byval" do not have an explicit alloca instruction, ASan does not produce red zones for them. This commit produces an explicit alloca instruction and copies the byval argument into the allocated memory so that red zones are produced. Patch by Matt Morehouse. Differential revision: https://reviews.llvm.org/D34789 llvm-svn: 307342
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp')
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 184940b7ea5..5f98cd566f3 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -22,9 +22,11 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/Argument.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
@@ -192,6 +194,11 @@ static cl::opt<uint32_t> ClMaxInlinePoisoningSize(
static cl::opt<bool> ClUseAfterReturn("asan-use-after-return",
cl::desc("Check stack-use-after-return"),
cl::Hidden, cl::init(true));
+static cl::opt<bool> ClRedzoneByvalArgs("asan-redzone-byval-args",
+ cl::desc("Create redzones for byval "
+ "arguments (extra copy "
+ "required)"), cl::Hidden,
+ cl::init(true));
static cl::opt<bool> ClUseAfterScope("asan-use-after-scope",
cl::desc("Check stack-use-after-scope"),
cl::Hidden, cl::init(false));
@@ -747,6 +754,9 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
bool runOnFunction() {
if (!ClStack) return false;
+
+ if (ClRedzoneByvalArgs) copyArgsPassedByValToAllocas();
+
// Collect alloca, ret, lifetime instructions etc.
for (BasicBlock *BB : depth_first(&F.getEntryBlock())) visit(*BB);
@@ -763,6 +773,11 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
return true;
}
+ // Arguments marked with the "byval" attribute are implicitly copied without
+ // using an alloca instruction. To produce redzones for those arguments, we
+ // copy them a second time into memory allocated with an alloca instruction.
+ void copyArgsPassedByValToAllocas();
+
// Finds all Alloca instructions and puts
// poisoned red zones around all of them.
// Then unpoison everything back before the function returns.
@@ -2528,6 +2543,28 @@ static int StackMallocSizeClass(uint64_t LocalStackSize) {
llvm_unreachable("impossible LocalStackSize");
}
+void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
+ BasicBlock &FirstBB = *F.begin();
+ IRBuilder<> IRB(&FirstBB, FirstBB.getFirstInsertionPt());
+ const DataLayout &DL = F.getParent()->getDataLayout();
+ for (Argument &Arg : F.args()) {
+ if (Arg.hasByValAttr()) {
+ Type *Ty = Arg.getType()->getPointerElementType();
+ unsigned Align = Arg.getParamAlignment();
+ if (Align == 0) Align = DL.getABITypeAlignment(Ty);
+
+ const std::string &Name = Arg.hasName() ? Arg.getName().str() :
+ "Arg" + std::to_string(Arg.getArgNo());
+ AllocaInst *AI = IRB.CreateAlloca(Ty, nullptr, Twine(Name) + ".byval");
+ AI->setAlignment(Align);
+ Arg.replaceAllUsesWith(AI);
+
+ uint64_t AllocSize = DL.getTypeAllocSize(Ty);
+ IRB.CreateMemCpy(AI, &Arg, AllocSize, Align);
+ }
+ }
+}
+
PHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond,
Value *ValueIfTrue,
Instruction *ThenTerm,
OpenPOWER on IntegriCloud