[llvm-commits] [PATCH] Add options to AddressSanitizer passes to make them configurable by frontend.
John Criswell
criswell at illinois.edu
Wed Nov 28 11:53:59 PST 2012
On 11/28/12 1:24 PM, Alexey Samsonov wrote:
> Hi kcc,
>
> This patch allows caller to enable/disable optional ASan features
> by passing arguments to createAddressSanitizer{Module,Function}Pass().
Just an FYI that, in my experience, passing configuration options via
the class's constructor is less than ideal. The problem is that the
pass will not exhibit the same behavior when it is used via opt or
bugpoint as it does when it is used in clang. The user must know that
invoking clang with one option will require invoking bugpoint with a
similarly named option. If the user doesn't know that, then he/she will
get different results, and it will not be obvious why.
An alternative is to factor out each piece of functionality controlled
by a command-line option into a separate pass and have clang schedule
the pass for execution based on its command line options. For example,
SAFECode has an option called -fmemsafety-terminate that causes the
generated program to terminate on the first memory safety error.
Instead of passing a flag into the instrumentation pass's constructor so
that it knows how to instrument the program to get the desired
termination behavior, the instrumentation pass simply assumes that the
option is set to false and instruments the program to keep running after
an error is detected. If -fmemsafety-terminate is specified, clang runs
an additional SAFECode instrumentation pass that changes the call to the
SAFECode run-time library initialization function to specify termination
after the first error.
In this way, if you ask clang what passes it ran, and then you specify
those passes to opt/bugpoint, you always get the same behavior. Users
don't need to know which opt/bugpoint options to use to get the same
behavior that you see in Clang.
I'm not sure if such a refactoring is possible for the options you've
added, but you may want to consider it.
-- John T.
>
> http://llvm-reviews.chandlerc.com/D145
>
> Files:
> include/llvm/Transforms/Instrumentation.h
> lib/Transforms/Instrumentation/AddressSanitizer.cpp
>
> Index: include/llvm/Transforms/Instrumentation.h
> ===================================================================
> --- include/llvm/Transforms/Instrumentation.h
> +++ include/llvm/Transforms/Instrumentation.h
> @@ -34,8 +34,10 @@
> bool UseExtraChecksum = false);
>
> // Insert AddressSanitizer (address sanity checking) instrumentation
> -FunctionPass *createAddressSanitizerFunctionPass();
> -ModulePass *createAddressSanitizerModulePass();
> +FunctionPass *createAddressSanitizerFunctionPass(
> + bool CheckInitOrder = false, bool CheckUseAfterReturn = false,
> + bool UseLifetime = false);
> +ModulePass *createAddressSanitizerModulePass(bool CheckInitOrder = false);
> // Insert ThreadSanitizer (race detection) instrumentation
> FunctionPass *createThreadSanitizerPass();
>
> Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp
> ===================================================================
> --- lib/Transforms/Instrumentation/AddressSanitizer.cpp
> +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp
> @@ -136,6 +136,10 @@
> static cl::opt<bool> ClOptGlobals("asan-opt-globals",
> cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true));
>
> +static cl::opt<bool> ClUseLifetime("asan-use-lifetime",
> + cl::desc("Use llvm.lifetime intrinsics to insert extra checks"),
> + cl::Hidden, cl::init(false));
> +
> // Debug flags.
> static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
> cl::init(0));
> @@ -186,7 +190,13 @@
>
> /// AddressSanitizer: instrument the code in module to find memory bugs.
> struct AddressSanitizer : public FunctionPass {
> - AddressSanitizer();
> + AddressSanitizer(bool CheckInitOrder = false,
> + bool CheckUseAfterReturn = false,
> + bool UseLifetime = false)
> + : FunctionPass(ID),
> + CheckInitOrder(CheckInitOrder || ClInitializers),
> + CheckUseAfterReturn(CheckUseAfterReturn || ClUseAfterReturn),
> + UseLifetime(UseLifetime || ClUseLifetime) {}
> virtual const char *getPassName() const {
> return "AddressSanitizerFunctionPass";
> }
> @@ -231,6 +241,9 @@
> bool LooksLikeCodeInBug11395(Instruction *I);
> void FindDynamicInitializers(Module &M);
>
> + bool CheckInitOrder;
> + bool CheckUseAfterReturn;
> + bool UseLifetime;
> LLVMContext *C;
> DataLayout *TD;
> uint64_t MappingOffset;
> @@ -250,17 +263,20 @@
>
> class AddressSanitizerModule : public ModulePass {
> public:
> + AddressSanitizerModule(bool CheckInitOrder = false)
> + : ModulePass(ID),
> + CheckInitOrder(CheckInitOrder || ClInitializers) {}
> bool runOnModule(Module &M);
> static char ID; // Pass identification, replacement for typeid
> - AddressSanitizerModule() : ModulePass(ID) { }
> virtual const char *getPassName() const {
> return "AddressSanitizerModule";
> }
> private:
> bool ShouldInstrumentGlobal(GlobalVariable *G);
> void createInitializerPoisonCalls(Module &M, Value *FirstAddr,
> Value *LastAddr);
>
> + bool CheckInitOrder;
> OwningPtr<BlackList> BL;
> SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
> Type *IntptrTy;
> @@ -274,17 +290,18 @@
> INITIALIZE_PASS(AddressSanitizer, "asan",
> "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
> false, false)
> -AddressSanitizer::AddressSanitizer() : FunctionPass(ID) { }
> -FunctionPass *llvm::createAddressSanitizerFunctionPass() {
> - return new AddressSanitizer();
> +FunctionPass *llvm::createAddressSanitizerFunctionPass(
> + bool CheckInitOrder, bool CheckUseAfterReturn, bool UseLifetime) {
> + return new AddressSanitizer(CheckInitOrder, CheckUseAfterReturn,
> + UseLifetime);
> }
>
> char AddressSanitizerModule::ID = 0;
> INITIALIZE_PASS(AddressSanitizerModule, "asan-module",
> "AddressSanitizer: detects use-after-free and out-of-bounds bugs."
> "ModulePass", false, false)
> -ModulePass *llvm::createAddressSanitizerModulePass() {
> - return new AddressSanitizerModule();
> +ModulePass *llvm::createAddressSanitizerModulePass(bool CheckInitOrder) {
> + return new AddressSanitizerModule(CheckInitOrder);
> }
>
> static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
> @@ -395,7 +412,7 @@
> if (GlobalVariable *G = dyn_cast<GlobalVariable>(Addr)) {
> // If initialization order checking is disabled, a simple access to a
> // dynamically initialized global is always valid.
> - if (!ClInitializers)
> + if (!CheckInitOrder)
> return;
> // If a global variable does not have dynamic initialization we don't
> // have to instrument it. However, if a global does not have initailizer
> @@ -689,7 +706,7 @@
> NULL);
>
> // Populate the first and last globals declared in this TU.
> - if (ClInitializers && GlobalHasDynamicInitializer) {
> + if (CheckInitOrder && GlobalHasDynamicInitializer) {
> LastDynamic = ConstantExpr::getPointerCast(NewGlobal, IntptrTy);
> if (FirstDynamic == 0)
> FirstDynamic = LastDynamic;
> @@ -704,7 +721,7 @@
> ConstantArray::get(ArrayOfGlobalStructTy, Initializers), "");
>
> // Create calls for poisoning before initializers run and unpoisoning after.
> - if (ClInitializers && FirstDynamic && LastDynamic)
> + if (CheckInitOrder && FirstDynamic && LastDynamic)
> createInitializerPoisonCalls(M, FirstDynamic, LastDynamic);
>
> Function *AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction(
> @@ -1068,7 +1085,7 @@
>
> uint64_t LocalStackSize = TotalSize + (AllocaVec.size() + 1) * RedzoneSize();
>
> - bool DoStackMalloc = ClUseAfterReturn
> + bool DoStackMalloc = CheckUseAfterReturn
> && LocalStackSize <= kMaxStackMallocSize;
>
> Instruction *InsBefore = AllocaVec[0];
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121128/cbba2ada/attachment.html>
More information about the llvm-commits
mailing list