[llvm-commits] [PATCH] Add options to AddressSanitizer passes to make them configurable by frontend.

Alexey Samsonov samsonov at google.com
Wed Nov 28 13:25:49 PST 2012


Hi John,

On Wed, Nov 28, 2012 at 11:53 AM, John Criswell <criswell at illinois.edu>wrote:

>  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.
>

I see your point. My plan was to make Clang create ASan pass with default
arguments (i.e. the effect of "clang -fsanitize=address" would run the same
pass "opt -asan").
We want to "expose" optional ASan instrumentation, which is currently
controlled by llvm flags, to Clang users. So that
"-fsanitize=address,use-after-return" would do the same as "opt -asan
-asan-use-after-return". So, we won't alter default ASan behavior unless
Clang user explicitly asks for it.


>
> 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.
>

Probably it's possible to break ASan features into several (communicating?)
passes, but I think the complexity would overweight benefit from it. I'm
open to other opinions, though.


>
> -- 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 listllvm-commits at cs.uiuc.eduhttp://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>


-- 
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121128/d5f5f2af/attachment.html>


More information about the llvm-commits mailing list