[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