mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
[asan] Change dynamic alloca instrumentation to only consider allocas that are dominating all exits from function.
Reviewed in http://reviews.llvm.org/D6412 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222991 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eed2e8bf98
commit
434494196b
@ -27,6 +27,7 @@
|
|||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/DIBuilder.h"
|
#include "llvm/IR/DIBuilder.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/IRBuilder.h"
|
#include "llvm/IR/IRBuilder.h"
|
||||||
#include "llvm/IR/InlineAsm.h"
|
#include "llvm/IR/InlineAsm.h"
|
||||||
@ -348,10 +349,15 @@ static size_t RedzoneSizeForScale(int MappingScale) {
|
|||||||
|
|
||||||
/// AddressSanitizer: instrument the code in module to find memory bugs.
|
/// AddressSanitizer: instrument the code in module to find memory bugs.
|
||||||
struct AddressSanitizer : public FunctionPass {
|
struct AddressSanitizer : public FunctionPass {
|
||||||
AddressSanitizer() : FunctionPass(ID) {}
|
AddressSanitizer() : FunctionPass(ID) {
|
||||||
|
initializeAddressSanitizerPass(*PassRegistry::getPassRegistry());
|
||||||
|
}
|
||||||
const char *getPassName() const override {
|
const char *getPassName() const override {
|
||||||
return "AddressSanitizerFunctionPass";
|
return "AddressSanitizerFunctionPass";
|
||||||
}
|
}
|
||||||
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
AU.addRequired<DominatorTreeWrapperPass>();
|
||||||
|
}
|
||||||
void instrumentMop(Instruction *I, bool UseCalls);
|
void instrumentMop(Instruction *I, bool UseCalls);
|
||||||
void instrumentPointerComparisonOrSubtraction(Instruction *I);
|
void instrumentPointerComparisonOrSubtraction(Instruction *I);
|
||||||
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
|
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
|
||||||
@ -369,6 +375,8 @@ struct AddressSanitizer : public FunctionPass {
|
|||||||
bool doInitialization(Module &M) override;
|
bool doInitialization(Module &M) override;
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
|
DominatorTree &getDominatorTree() const { return *DT; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeCallbacks(Module &M);
|
void initializeCallbacks(Module &M);
|
||||||
|
|
||||||
@ -380,6 +388,7 @@ struct AddressSanitizer : public FunctionPass {
|
|||||||
int LongSize;
|
int LongSize;
|
||||||
Type *IntptrTy;
|
Type *IntptrTy;
|
||||||
ShadowMapping Mapping;
|
ShadowMapping Mapping;
|
||||||
|
DominatorTree *DT;
|
||||||
Function *AsanCtorFunction;
|
Function *AsanCtorFunction;
|
||||||
Function *AsanInitFunction;
|
Function *AsanInitFunction;
|
||||||
Function *AsanHandleNoReturnFunc;
|
Function *AsanHandleNoReturnFunc;
|
||||||
@ -471,10 +480,11 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
|
|||||||
AllocaInst *AI;
|
AllocaInst *AI;
|
||||||
Value *LeftRzAddr;
|
Value *LeftRzAddr;
|
||||||
Value *RightRzAddr;
|
Value *RightRzAddr;
|
||||||
|
bool Poison;
|
||||||
explicit DynamicAllocaCall(AllocaInst *AI,
|
explicit DynamicAllocaCall(AllocaInst *AI,
|
||||||
Value *LeftRzAddr = nullptr,
|
Value *LeftRzAddr = nullptr,
|
||||||
Value *RightRzAddr = nullptr)
|
Value *RightRzAddr = nullptr)
|
||||||
: AI(AI), LeftRzAddr(LeftRzAddr), RightRzAddr(RightRzAddr)
|
: AI(AI), LeftRzAddr(LeftRzAddr), RightRzAddr(RightRzAddr), Poison(true)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
SmallVector<DynamicAllocaCall, 1> DynamicAllocaVec;
|
SmallVector<DynamicAllocaCall, 1> DynamicAllocaVec;
|
||||||
@ -520,6 +530,8 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
|
|||||||
|
|
||||||
// Unpoison dynamic allocas redzones.
|
// Unpoison dynamic allocas redzones.
|
||||||
void unpoisonDynamicAlloca(DynamicAllocaCall &AllocaCall) {
|
void unpoisonDynamicAlloca(DynamicAllocaCall &AllocaCall) {
|
||||||
|
if (!AllocaCall.Poison)
|
||||||
|
return;
|
||||||
for (auto Ret : RetVec) {
|
for (auto Ret : RetVec) {
|
||||||
IRBuilder<> IRBRet(Ret);
|
IRBuilder<> IRBRet(Ret);
|
||||||
PointerType *Int32PtrTy = PointerType::getUnqual(IRBRet.getInt32Ty());
|
PointerType *Int32PtrTy = PointerType::getUnqual(IRBRet.getInt32Ty());
|
||||||
@ -605,6 +617,14 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
|
|||||||
// ---------------------- Helpers.
|
// ---------------------- Helpers.
|
||||||
void initializeCallbacks(Module &M);
|
void initializeCallbacks(Module &M);
|
||||||
|
|
||||||
|
bool doesDominateAllExits(const Instruction *I) const {
|
||||||
|
for (auto Ret : RetVec) {
|
||||||
|
if (!ASan.getDominatorTree().dominates(I, Ret))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool isDynamicAlloca(AllocaInst &AI) const {
|
bool isDynamicAlloca(AllocaInst &AI) const {
|
||||||
return AI.isArrayAllocation() || !AI.isStaticAlloca();
|
return AI.isArrayAllocation() || !AI.isStaticAlloca();
|
||||||
}
|
}
|
||||||
@ -634,7 +654,11 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
char AddressSanitizer::ID = 0;
|
char AddressSanitizer::ID = 0;
|
||||||
INITIALIZE_PASS(AddressSanitizer, "asan",
|
INITIALIZE_PASS_BEGIN(AddressSanitizer, "asan",
|
||||||
|
"AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
|
||||||
|
false, false)
|
||||||
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||||
|
INITIALIZE_PASS_END(AddressSanitizer, "asan",
|
||||||
"AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
|
"AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
|
||||||
false, false)
|
false, false)
|
||||||
FunctionPass *llvm::createAddressSanitizerFunctionPass() {
|
FunctionPass *llvm::createAddressSanitizerFunctionPass() {
|
||||||
@ -1354,6 +1378,8 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n");
|
DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n");
|
||||||
initializeCallbacks(*F.getParent());
|
initializeCallbacks(*F.getParent());
|
||||||
|
|
||||||
|
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||||
|
|
||||||
// If needed, insert __asan_init before checking for SanitizeAddress attr.
|
// If needed, insert __asan_init before checking for SanitizeAddress attr.
|
||||||
maybeInsertAsanInitAtFunctionEntry(F);
|
maybeInsertAsanInitAtFunctionEntry(F);
|
||||||
|
|
||||||
@ -1825,6 +1851,12 @@ Value *FunctionStackPoisoner::computePartialRzMagic(Value *PartialSize,
|
|||||||
void FunctionStackPoisoner::handleDynamicAllocaCall(
|
void FunctionStackPoisoner::handleDynamicAllocaCall(
|
||||||
DynamicAllocaCall &AllocaCall) {
|
DynamicAllocaCall &AllocaCall) {
|
||||||
AllocaInst *AI = AllocaCall.AI;
|
AllocaInst *AI = AllocaCall.AI;
|
||||||
|
if (!doesDominateAllExits(AI)) {
|
||||||
|
// We do not yet handle complex allocas
|
||||||
|
AllocaCall.Poison = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IRBuilder<> IRB(AI);
|
IRBuilder<> IRB(AI);
|
||||||
|
|
||||||
PointerType *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
PointerType *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
; Test that undecidable dynamic allocas are skipped by ASan.
|
||||||
|
|
||||||
|
; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s
|
||||||
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define void @g(i64 %n) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp sgt i64 %n, 100
|
||||||
|
br i1 %cmp, label %do_alloca, label %done
|
||||||
|
|
||||||
|
do_alloca:
|
||||||
|
; CHECK-NOT: store i32 -892679478
|
||||||
|
%0 = alloca i8, i64 %n, align 1
|
||||||
|
call void @f(i8* %0)
|
||||||
|
br label %done
|
||||||
|
|
||||||
|
done:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @f(i8*)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user