mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
[asan] add option -asan-keep-uninstrumented-functions
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184927 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0259c0cde5
commit
20985711c7
@ -44,6 +44,7 @@
|
|||||||
#include "llvm/Support/system_error.h"
|
#include "llvm/Support/system_error.h"
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include "llvm/Transforms/Utils/BlackList.h"
|
#include "llvm/Transforms/Utils/BlackList.h"
|
||||||
|
#include "llvm/Transforms/Utils/Cloning.h"
|
||||||
#include "llvm/Transforms/Utils/Local.h"
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -131,6 +132,19 @@ static cl::opt<std::string> ClBlacklistFile("asan-blacklist",
|
|||||||
cl::desc("File containing the list of objects to ignore "
|
cl::desc("File containing the list of objects to ignore "
|
||||||
"during instrumentation"), cl::Hidden);
|
"during instrumentation"), cl::Hidden);
|
||||||
|
|
||||||
|
// This is an experimental feature that will allow to choose between
|
||||||
|
// instrumented and non-instrumented code at link-time.
|
||||||
|
// If this option is on, just before instrumenting a function we create its
|
||||||
|
// clone; if the function is not changed by asan the clone is deleted.
|
||||||
|
// If we end up with a clone, we put the instrumented function into a section
|
||||||
|
// called "ASAN" and the uninstrumented function into a section called "NOASAN".
|
||||||
|
//
|
||||||
|
// This is still a prototype, we need to figure out a way to keep two copies of
|
||||||
|
// a function so that the linker can easily choose one of them.
|
||||||
|
static cl::opt<bool> ClKeepUninstrumented("asan-keep-uninstrumented-functions",
|
||||||
|
cl::desc("Keep uninstrumented copies of functions"),
|
||||||
|
cl::Hidden, cl::init(false));
|
||||||
|
|
||||||
// These flags allow to change the shadow mapping.
|
// These flags allow to change the shadow mapping.
|
||||||
// The shadow mapping looks like
|
// The shadow mapping looks like
|
||||||
// Shadow = (Mem >> scale) + (1 << offset_log)
|
// Shadow = (Mem >> scale) + (1 << offset_log)
|
||||||
@ -1106,8 +1120,7 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
// If needed, insert __asan_init before checking for SanitizeAddress attr.
|
// If needed, insert __asan_init before checking for SanitizeAddress attr.
|
||||||
maybeInsertAsanInitAtFunctionEntry(F);
|
maybeInsertAsanInitAtFunctionEntry(F);
|
||||||
|
|
||||||
if (!F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
if (!F.hasFnAttribute(Attribute::SanitizeAddress))
|
||||||
Attribute::SanitizeAddress))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ClDebugFunc.empty() && ClDebugFunc != F.getName())
|
if (!ClDebugFunc.empty() && ClDebugFunc != F.getName())
|
||||||
@ -1118,6 +1131,7 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
SmallSet<Value*, 16> TempsToInstrument;
|
SmallSet<Value*, 16> TempsToInstrument;
|
||||||
SmallVector<Instruction*, 16> ToInstrument;
|
SmallVector<Instruction*, 16> ToInstrument;
|
||||||
SmallVector<Instruction*, 8> NoReturnCalls;
|
SmallVector<Instruction*, 8> NoReturnCalls;
|
||||||
|
int NumAllocas = 0;
|
||||||
bool IsWrite;
|
bool IsWrite;
|
||||||
|
|
||||||
// Fill the set of memory operations to instrument.
|
// Fill the set of memory operations to instrument.
|
||||||
@ -1136,6 +1150,8 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
} else if (isa<MemIntrinsic>(BI) && ClMemIntrin) {
|
} else if (isa<MemIntrinsic>(BI) && ClMemIntrin) {
|
||||||
// ok, take it.
|
// ok, take it.
|
||||||
} else {
|
} else {
|
||||||
|
if (isa<AllocaInst>(BI))
|
||||||
|
NumAllocas++;
|
||||||
CallSite CS(BI);
|
CallSite CS(BI);
|
||||||
if (CS) {
|
if (CS) {
|
||||||
// A call inside BB.
|
// A call inside BB.
|
||||||
@ -1152,6 +1168,17 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Function *UninstrumentedDuplicate = 0;
|
||||||
|
bool LikelyToInstrument =
|
||||||
|
!NoReturnCalls.empty() || !ToInstrument.empty() || (NumAllocas > 0);
|
||||||
|
if (ClKeepUninstrumented && LikelyToInstrument) {
|
||||||
|
ValueToValueMapTy VMap;
|
||||||
|
UninstrumentedDuplicate = CloneFunction(&F, VMap, false);
|
||||||
|
UninstrumentedDuplicate->removeFnAttr(Attribute::SanitizeAddress);
|
||||||
|
UninstrumentedDuplicate->setName("NOASAN_" + F.getName());
|
||||||
|
F.getParent()->getFunctionList().push_back(UninstrumentedDuplicate);
|
||||||
|
}
|
||||||
|
|
||||||
// Instrument.
|
// Instrument.
|
||||||
int NumInstrumented = 0;
|
int NumInstrumented = 0;
|
||||||
for (size_t i = 0, n = ToInstrument.size(); i != n; i++) {
|
for (size_t i = 0, n = ToInstrument.size(); i != n; i++) {
|
||||||
@ -1176,9 +1203,25 @@ bool AddressSanitizer::runOnFunction(Function &F) {
|
|||||||
IRBuilder<> IRB(CI);
|
IRBuilder<> IRB(CI);
|
||||||
IRB.CreateCall(AsanHandleNoReturnFunc);
|
IRB.CreateCall(AsanHandleNoReturnFunc);
|
||||||
}
|
}
|
||||||
DEBUG(dbgs() << "ASAN done instrumenting:\n" << F << "\n");
|
|
||||||
|
|
||||||
return NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty();
|
bool res = NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty();
|
||||||
|
DEBUG(dbgs() << "ASAN done instrumenting: " << res << " " << F << "\n");
|
||||||
|
|
||||||
|
if (ClKeepUninstrumented) {
|
||||||
|
if (!res) {
|
||||||
|
// No instrumentation is done, no need for the duplicate.
|
||||||
|
if (UninstrumentedDuplicate)
|
||||||
|
UninstrumentedDuplicate->eraseFromParent();
|
||||||
|
} else {
|
||||||
|
// The function was instrumented. We must have the duplicate.
|
||||||
|
assert(UninstrumentedDuplicate);
|
||||||
|
UninstrumentedDuplicate->setSection("NOASAN");
|
||||||
|
assert(!F.hasSection());
|
||||||
|
F.setSection("ASAN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) {
|
static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) {
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
; Test the -asan-keep-uninstrumented-functions flag: FOO should get cloned
|
||||||
|
; RUN: opt < %s -asan -asan-keep-uninstrumented-functions -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-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
@a = global i32 0, align 4
|
||||||
|
|
||||||
|
define i32 @main() sanitize_address {
|
||||||
|
entry:
|
||||||
|
tail call void @FOO(i32* @a)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @FOO(i32* nocapture %x) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i32 1, i32* %x, align 4
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; main should not be cloned since it is not being instrumented by asan.
|
||||||
|
; CHECK-NOT: NOASAN_main
|
||||||
|
; CHECK: define void @FOO{{.*}} section "ASAN"
|
||||||
|
; CHECK: define void @NOASAN_FOO{{.*}} section "NOASAN"
|
Loading…
Reference in New Issue
Block a user