[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