[Lldb-commits] [lldb] r112785 - in /lldb/trunk: include/lldb/Expression/IRDynamicChecks.h source/Expression/IRDynamicChecks.cpp

Sean Callanan scallanan at apple.com
Wed Sep 1 17:37:32 PDT 2010


Author: spyffe
Date: Wed Sep  1 19:37:32 2010
New Revision: 112785

URL: http://llvm.org/viewvc/llvm-project?rev=112785&view=rev
Log:
Added code to run pointer validation checks in
expressions.  If an expression dereferences an
invalid pointer, there will still be a crash -
just now the crash will be in the function
___clang_valid_pointer_check().

Modified:
    lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
    lldb/trunk/source/Expression/IRDynamicChecks.cpp

Modified: lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRDynamicChecks.h?rev=112785&r1=112784&r2=112785&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRDynamicChecks.h (original)
+++ lldb/trunk/include/lldb/Expression/IRDynamicChecks.h Wed Sep  1 19:37:32 2010
@@ -132,6 +132,26 @@
     //------------------------------------------------------------------
     llvm::PassManagerType getPotentialPassManagerType() const;
 private:
+    //------------------------------------------------------------------
+    /// A basic block-level pass to find all pointer dereferences and
+    /// validate them before use.
+    //------------------------------------------------------------------
+    
+    //------------------------------------------------------------------
+    /// The top-level pass implementation
+    ///
+    /// @param[in] M
+    ///     The module currently being processed.
+    ///
+    /// @param[in] BB
+    ///     The basic block currently being processed.
+    ///
+    /// @return
+    ///     True on success; false otherwise
+    //------------------------------------------------------------------
+    bool FindDataLoads(llvm::Module &M, 
+                       llvm::BasicBlock &BB);
+    
     std::string                 m_func_name;            ///< The name of the function to add checks to
     DynamicCheckerFunctions    &m_checker_functions;    ///< The checker functions for the process
 };

Modified: lldb/trunk/source/Expression/IRDynamicChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRDynamicChecks.cpp?rev=112785&r1=112784&r2=112785&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRDynamicChecks.cpp (original)
+++ lldb/trunk/source/Expression/IRDynamicChecks.cpp Wed Sep  1 19:37:32 2010
@@ -14,6 +14,7 @@
 
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Function.h"
+#include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/Value.h"
 
@@ -52,16 +53,6 @@
     return true;
 }
 
-IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
-                                 const char *func_name) :
-    ModulePass(&ID),
-    m_checker_functions(checker_functions),
-    m_func_name(func_name)
-{
-}
-
-/* A handy utility function used at several places in the code */
-
 static std::string 
 PrintValue(llvm::Value *V, bool truncate = false)
 {
@@ -74,6 +65,257 @@
     return s;
 }
 
+//----------------------------------------------------------------------
+/// @class Instrumenter IRDynamicChecks.cpp
+/// @brief Finds and instruments individual LLVM IR instructions
+///
+/// When instrumenting LLVM IR, it is frequently desirable to first search
+/// for instructions, and then later modify them.  This way iterators
+/// remain intact, and multiple passes can look at the same code base without
+/// treading on each other's toes.
+///
+/// The Instrumenter class implements this functionality.  A client first
+/// calls Inspect on a function, which populates a list of instructions to
+/// be instrumented.  Then, later, when all passes' Inspect functions have
+/// been called, the client calls Instrument, which adds the desired
+/// instrumentation.
+///
+/// A subclass of Instrumenter must override InstrumentInstruction, which
+/// is responsible for adding whatever instrumentation is necessary.
+///
+/// A subclass of Instrumenter may override:
+///
+/// - InspectInstruction [default: does nothing]
+///
+/// - InspectBasicBlock [default: iterates through the instructions in a 
+///   basic block calling InspectInstruction]
+///
+/// - InspectFunction [default: iterates through the basic blocks in a 
+///   function calling InspectBasicBlock]
+//----------------------------------------------------------------------
+class Instrumenter {
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    ///
+    /// @param[in] module
+    ///     The module being instrumented.
+    //------------------------------------------------------------------
+    Instrumenter (llvm::Module &module,
+                  DynamicCheckerFunctions &checker_functions) :
+        m_module(module),
+        m_checker_functions(checker_functions)
+    {
+    }
+    
+    //------------------------------------------------------------------
+    /// Inspect a function to find instructions to instrument
+    ///
+    /// @param[in] function
+    ///     The function to inspect.
+    ///
+    /// @return
+    ///     True on success; false on error.
+    //------------------------------------------------------------------
+    bool Inspect (llvm::Function &function)
+    {
+        return InspectFunction(function);
+    }
+    
+    //------------------------------------------------------------------
+    /// Instrument all the instructions found by Inspect()
+    ///
+    /// @return
+    ///     True on success; false on error.
+    //------------------------------------------------------------------
+    bool Instrument ()
+    {
+        for (InstIterator ii = m_to_instrument.begin(), last_ii = m_to_instrument.end();
+             ii != last_ii;
+             ++ii)
+        {
+            if (!InstrumentInstruction(*ii))
+                return false;
+        }
+        
+        return true;
+    }
+protected:
+    //------------------------------------------------------------------
+    /// Add instrumentation to a single instruction
+    ///
+    /// @param[in] inst
+    ///     The instruction to be instrumented. 
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
+    
+    //------------------------------------------------------------------
+    /// Register a single instruction to be instrumented
+    ///
+    /// @param[in] inst
+    ///     The instruction to be instrumented.
+    //------------------------------------------------------------------
+    void RegisterInstruction(llvm::Instruction &i)
+    {
+        m_to_instrument.push_back(&i);
+    }
+    
+    //------------------------------------------------------------------
+    /// Determine whether a single instruction is interesting to
+    /// instrument, and, if so, call RegisterInstruction
+    ///
+    /// @param[in] i
+    ///     The instruction to be inspected.
+    ///
+    /// @return
+    ///     False if there was an error scanning; true otherwise.
+    //------------------------------------------------------------------
+    virtual bool InspectInstruction(llvm::Instruction &i)
+    {
+        return true;
+    }
+    
+    //------------------------------------------------------------------
+    /// Scan a basic block to see if any instructions are interesting
+    ///
+    /// @param[in] bb
+    ///     The basic block to be inspected.
+    ///
+    /// @return
+    ///     False if there was an error scanning; true otherwise.
+    //------------------------------------------------------------------
+    virtual bool InspectBasicBlock(llvm::BasicBlock &bb)
+    {
+        for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
+             ii != last_ii;
+             ++ii)
+        {
+            if (!InspectInstruction(*ii))
+                return false;
+        }
+        
+        return true;
+    }
+    
+    //------------------------------------------------------------------
+    /// Scan a function to see if any instructions are interesting
+    ///
+    /// @param[in] f
+    ///     The function to be inspected. 
+    ///
+    /// @return
+    ///     False if there was an error scanning; true otherwise.
+    //------------------------------------------------------------------
+    virtual bool InspectFunction(llvm::Function &f)
+    {
+        for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
+             bbi != last_bbi;
+             ++bbi)
+        {
+            if (!InspectBasicBlock(*bbi))
+                return false;
+        }
+        
+        return true;
+    }
+    
+    typedef std::vector <llvm::Instruction *>   InstVector;
+    typedef InstVector::iterator                InstIterator;
+    
+    InstVector                  m_to_instrument;        ///< List of instructions the inspector found
+    llvm::Module               &m_module;               ///< The module which is being instrumented
+    DynamicCheckerFunctions    &m_checker_functions;    ///< The dynamic checker functions for the process
+};
+
+class ValidPointerChecker : public Instrumenter
+{
+public:
+    ValidPointerChecker(llvm::Module &module,
+                        DynamicCheckerFunctions &checker_functions) :
+        Instrumenter(module, checker_functions),
+        m_valid_pointer_check_func(NULL)
+    {
+    }
+private:
+    bool InstrumentInstruction(llvm::Instruction *inst)
+    {
+        lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+        if(log)
+            log->Printf("Instrumenting load/store instruction: %s\n", 
+                        PrintValue(inst).c_str());
+        
+        if (!m_valid_pointer_check_func)
+        {
+            std::vector<const llvm::Type*> params;
+            
+            const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
+                                                                 (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
+            
+            m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
+            
+            params.push_back(m_i8ptr_ty);
+            
+            FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
+            PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
+            Constant *fun_addr_int = ConstantInt::get(intptr_ty, m_checker_functions.m_valid_pointer_check->StartAddress(), false);
+            m_valid_pointer_check_func = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+        }
+        
+        llvm::Value *dereferenced_ptr;
+        
+        if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
+            dereferenced_ptr = li->getPointerOperand();
+        else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst))
+            dereferenced_ptr = si->getPointerOperand();
+        else
+            return false;
+        
+        // Insert an instruction to cast the loaded value to int8_t*
+        
+        BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr,
+                                                m_i8ptr_ty,
+                                                "",
+                                                inst);
+        
+        // Insert an instruction to call the helper with the result
+        
+        SmallVector <llvm::Value*, 1> args;
+        args.push_back(bit_cast);
+        
+        CallInst::Create(m_valid_pointer_check_func, 
+                         args.begin(),
+                         args.end(),
+                         "",
+                         inst);
+            
+        return true;
+    }
+    
+    bool InspectInstruction(llvm::Instruction &i)
+    {
+        if (dyn_cast<llvm::LoadInst> (&i) ||
+            dyn_cast<llvm::StoreInst> (&i))
+            RegisterInstruction(i);
+        
+        return true;
+    }
+    
+    llvm::Value         *m_valid_pointer_check_func;
+    const PointerType   *m_i8ptr_ty;
+};
+
+IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
+                                 const char *func_name) :
+    ModulePass(&ID),
+    m_checker_functions(checker_functions),
+    m_func_name(func_name)
+{
+}
+
 IRDynamicChecks::~IRDynamicChecks()
 {
 }
@@ -92,14 +334,14 @@
         
         return false;
     }
+
+    ValidPointerChecker vpc(M, m_checker_functions);
     
-    llvm::Function::iterator bbi;
+    if (!vpc.Inspect(*function))
+        return false;
     
-    for (bbi = function->begin();
-         bbi != function->end();
-         ++bbi)
-    {
-    }
+    if (!vpc.Instrument())
+        return false;
     
     return true;    
 }





More information about the lldb-commits mailing list