[Lldb-commits] [lldb] r112690 - in /lldb/trunk: include/lldb/Expression/IRDynamicChecks.h include/lldb/Target/Process.h lldb.xcodeproj/project.pbxproj source/Commands/CommandObjectExpression.cpp source/Expression/ClangExpressionParser.cpp source/Expression/ClangUtilityFunction.cpp source/Expression/IRDynamicChecks.cpp

Sean Callanan scallanan at apple.com
Tue Aug 31 17:58:00 PDT 2010


Author: spyffe
Date: Tue Aug 31 19:58:00 2010
New Revision: 112690

URL: http://llvm.org/viewvc/llvm-project?rev=112690&view=rev
Log:
Added support for dynamic sanity checking in
expressions.  Values used by the expression are
checked by validation functions which cause the
program to crash if the values are unsafe.

Major changes:

- Added IRDynamicChecks.[ch], which contains the
  core code related to this feature

- Modified CommandObjectExpression to install the
  validator functions into the target process.

- Added an accessor to Process that gets/sets the
  helper functions

Added:
    lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
    lldb/trunk/source/Expression/IRDynamicChecks.cpp
Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/ClangExpressionParser.cpp
    lldb/trunk/source/Expression/ClangUtilityFunction.cpp

Added: lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRDynamicChecks.h?rev=112690&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRDynamicChecks.h (added)
+++ lldb/trunk/include/lldb/Expression/IRDynamicChecks.h Tue Aug 31 19:58:00 2010
@@ -0,0 +1,141 @@
+//===-- IRDynamicChecks.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IRDynamicChecks_h_
+#define liblldb_IRDynamicChecks_h_
+
+#include "llvm/Pass.h"
+
+namespace llvm {
+    class BasicBlock;
+    class CallInst;
+    class Constant;
+    class Function;
+    class Instruction;
+    class Module;
+    class TargetData;
+    class Value;
+}
+
+namespace lldb_private 
+{
+
+class ClangExpressionDeclMap;
+class ClangUtilityFunction;
+class ExecutionContext;
+class Stream;
+
+//----------------------------------------------------------------------
+/// @class DynamicCheckerFunctions IRDynamicChecks.h "lldb/Expression/IRDynamicChecks.h"
+/// @brief Encapsulates dynamic check functions used by expressions.
+///
+/// Each of the utility functions encapsulated in this class is responsible
+/// for validating some data that an expression is about to use.  Examples are:
+///
+/// a = *b;     // check that b is a valid pointer
+/// [b init];   // check that b is a valid object to send "init" to
+///
+/// The class installs each checker function into the target process and
+/// makes it available to IRDynamicChecks to use.
+//----------------------------------------------------------------------
+class DynamicCheckerFunctions
+{
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    //------------------------------------------------------------------
+    DynamicCheckerFunctions ();
+    
+    //------------------------------------------------------------------
+    /// Destructor
+    //------------------------------------------------------------------
+    ~DynamicCheckerFunctions ();
+    
+    //------------------------------------------------------------------
+    /// Install the utility functions into a process.  This binds the
+    /// instance of DynamicCheckerFunctions to that process.
+    ///
+    /// @param[in] error_stream
+    ///     A stream to print errors on.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to install the functions into.
+    ///
+    /// @return
+    ///     True on success; false on failure, or if the functions have
+    ///     already been installed.
+    //------------------------------------------------------------------
+    bool Install (Stream &error_stream,
+                  ExecutionContext &exe_ctx);
+    
+    std::auto_ptr<ClangUtilityFunction> m_valid_pointer_check;
+};
+
+//----------------------------------------------------------------------
+/// @class IRDynamicChecks IRDynamicChecks.h "lldb/Expression/IRDynamicChecks.h"
+/// @brief Adds dynamic checks to a user-entered expression to reduce its likelihood of crashing
+///
+/// When an IR function is executed in the target process, it may cause
+/// crashes or hangs by dereferencing NULL pointers, trying to call Objective-C
+/// methods on objects that do not respond to them, and so forth.
+///
+/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions
+/// to appropriate locations in an expression's IR.
+//----------------------------------------------------------------------
+class IRDynamicChecks : public llvm::ModulePass
+{
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    ///
+    /// @param[in] checker_functions
+    ///     The checker functions for the target process.
+    ///
+    /// @param[in] func_name
+    ///     The name of the function to prepare for execution in the target.
+    //------------------------------------------------------------------
+    IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
+                    const char* func_name = "___clang_expr");
+    
+    //------------------------------------------------------------------
+    /// Destructor
+    //------------------------------------------------------------------
+    ~IRDynamicChecks();
+    
+    //------------------------------------------------------------------
+    /// Run this IR transformer on a single module
+    ///
+    /// @param[in] M
+    ///     The module to run on.  This module is searched for the function
+    ///     ___clang_expr, and that function is passed to the passes one by 
+    ///     one.
+    ///
+    /// @return
+    ///     True on success; false otherwise
+    //------------------------------------------------------------------
+    bool runOnModule(llvm::Module &M);
+    
+    //------------------------------------------------------------------
+    /// Interface stub
+    //------------------------------------------------------------------
+    void assignPassManager(llvm::PMStack &PMS,
+                           llvm::PassManagerType T = llvm::PMT_ModulePassManager);
+    
+    //------------------------------------------------------------------
+    /// Returns PMT_ModulePassManager
+    //------------------------------------------------------------------
+    llvm::PassManagerType getPotentialPassManagerType() const;
+private:
+    std::string                 m_func_name;            ///< The name of the function to add checks to
+    DynamicCheckerFunctions    &m_checker_functions;    ///< The checker functions for the process
+};
+    
+}
+
+#endif

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=112690&r1=112689&r2=112690&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Tue Aug 31 19:58:00 2010
@@ -26,6 +26,7 @@
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Breakpoint/BreakpointSiteList.h"
 #include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/IRDynamicChecks.h"
 #include "lldb/Target/ExecutionContextScope.h"
 #include "lldb/Target/ObjCObjectPrinter.h"
 #include "lldb/Target/ThreadList.h"
@@ -1353,6 +1354,16 @@
 
     bool
     IsRunning () const;
+    
+    DynamicCheckerFunctions *GetDynamicCheckers()
+    {
+        return m_dynamic_checkers.get();
+    }
+    
+    void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
+    {
+        m_dynamic_checkers.reset(dynamic_checkers);
+    }
 
     //------------------------------------------------------------------
     // lldb::ExecutionContextScope pure virtual functions
@@ -1405,6 +1416,7 @@
     BreakpointSiteList          m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend
                                                         ///< to insert in the target.
     ClangPersistentVariables    m_persistent_vars;      ///< These are the persistent variables associated with this process for the expression parser.
+    std::auto_ptr<DynamicCheckerFunctions>  m_dynamic_checkers; ///< The functions used by the expression parser to validate data that expressions use.
     UnixSignals                 m_unix_signals;         /// This is the current signal set for this process.
     ConstString                 m_target_triple;
     lldb::ABISP                 m_abi_sp;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=112690&r1=112689&r2=112690&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Aug 31 19:58:00 2010
@@ -341,6 +341,8 @@
 		49A8A3A011D568A300AD3B68 /* ASTResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */; };
 		49A8A3A411D568BF00AD3B68 /* ASTResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */; };
 		49BB309611F79450001A4197 /* TaggedASTType.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BB309511F79450001A4197 /* TaggedASTType.h */; };
+		49CF982A122C70BD007A0B96 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */; };
+		49CF9834122C718B007A0B96 /* IRDynamicChecks.h in Headers */ = {isa = PBXBuildFile; fileRef = 49CF9833122C718B007A0B96 /* IRDynamicChecks.h */; };
 		49D4FE831210B5FB00CDB854 /* ClangPersistentVariables.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */; };
 		49D4FE891210B61C00CDB854 /* ClangPersistentVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */; };
 		49D7072711B5AD03001AD875 /* ClangASTSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D7072611B5AD03001AD875 /* ClangASTSource.h */; };
@@ -933,6 +935,8 @@
 		49BB309511F79450001A4197 /* TaggedASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaggedASTType.h; path = include/lldb/Symbol/TaggedASTType.h; sourceTree = "<group>"; };
 		49BF48DC11ADF356008863BD /* ObjCObjectPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCObjectPrinter.cpp; path = source/Target/ObjCObjectPrinter.cpp; sourceTree = "<group>"; };
 		49BF48E011ADF37D008863BD /* ObjCObjectPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCObjectPrinter.h; path = include/lldb/Target/ObjCObjectPrinter.h; sourceTree = "<group>"; };
+		49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRDynamicChecks.cpp; path = source/Expression/IRDynamicChecks.cpp; sourceTree = "<group>"; };
+		49CF9833122C718B007A0B96 /* IRDynamicChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRDynamicChecks.h; path = include/lldb/Expression/IRDynamicChecks.h; sourceTree = "<group>"; };
 		49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangPersistentVariables.h; path = include/lldb/Expression/ClangPersistentVariables.h; sourceTree = "<group>"; };
 		49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangPersistentVariables.cpp; path = source/Expression/ClangPersistentVariables.cpp; sourceTree = "<group>"; };
 		49D7072611B5AD03001AD875 /* ClangASTSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTSource.h; path = include/lldb/Expression/ClangASTSource.h; sourceTree = "<group>"; };
@@ -1882,6 +1886,8 @@
 				49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */,
 				4911934B1226383D00578B7F /* ASTStructExtractor.h */,
 				491193501226386000578B7F /* ASTStructExtractor.cpp */,
+				49CF9833122C718B007A0B96 /* IRDynamicChecks.h */,
+				49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
 				49307AB111DEA4F20081F992 /* IRForTarget.h */,
 				49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
 				49DA743411DE6BB2006AEF7E /* IRToDWARF.h */,
@@ -2254,6 +2260,7 @@
 				49445E351225AB6A00C11A81 /* ClangUserExpression.h in Headers */,
 				4911934C1226383D00578B7F /* ASTStructExtractor.h in Headers */,
 				497C86C2122823F300B54702 /* ClangUtilityFunction.h in Headers */,
+				49CF9834122C718B007A0B96 /* IRDynamicChecks.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2308,7 +2315,6 @@
 			isa = PBXProject;
 			buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
 			compatibilityVersion = "Xcode 3.1";
-			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				en,
@@ -2713,6 +2719,7 @@
 				49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */,
 				491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */,
 				497C86BE122823D800B54702 /* ClangUtilityFunction.cpp in Sources */,
+				49CF982A122C70BD007A0B96 /* IRDynamicChecks.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=112690&r1=112689&r2=112690&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Tue Aug 31 19:58:00 2010
@@ -190,6 +190,27 @@
 CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream,
                                              CommandReturnObject *result)
 {
+    if (!m_exe_ctx.process)
+    {
+        error_stream.Printf ("Execution context doesn't contain a process");
+        return false;
+    }
+    
+    if (!m_exe_ctx.process->GetDynamicCheckers())
+    {
+        DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
+        
+        StreamString install_errors;
+        
+        if (!dynamic_checkers->Install(install_errors, m_exe_ctx))
+        {
+            error_stream.Printf("Couldn't install dynamic checkers into the execution context: %s", install_errors.GetData());
+            return false;
+        }
+        
+        m_exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
+    }
+    
     ClangUserExpression user_expression (expr);
     
     if (!user_expression.Parse (error_stream, m_exe_ctx))

Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=112690&r1=112689&r2=112690&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Tue Aug 31 19:58:00 2010
@@ -13,8 +13,10 @@
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
 #include "lldb/Expression/ClangASTSource.h"
 #include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/IRDynamicChecks.h"
 #include "lldb/Expression/IRForTarget.h"
 #include "lldb/Expression/IRToDWARF.h"
 #include "lldb/Expression/RecordingMemoryManager.h"
@@ -409,6 +411,15 @@
             err.SetErrorString("Couldn't convert the expression to DWARF");
             return err;
         }
+        
+        IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName());
+        
+        if (!ir_dynamic_checks.runOnModule(*module))
+        {
+            err.SetErrorToGenericError();
+            err.SetErrorString("Couldn't add dynamic checks to the expression");
+            return err;
+        }        
     }
     
     m_jit_mm = new RecordingMemoryManager();

Modified: lldb/trunk/source/Expression/ClangUtilityFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUtilityFunction.cpp?rev=112690&r1=112689&r2=112690&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUtilityFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangUtilityFunction.cpp Tue Aug 31 19:58:00 2010
@@ -37,7 +37,9 @@
 ClangUtilityFunction::ClangUtilityFunction (const char *text, 
                                             const char *name) :
     m_function_text(text),
-    m_function_name(name)
+    m_function_name(name),
+    m_jit_begin(LLDB_INVALID_ADDRESS),
+    m_jit_end(LLDB_INVALID_ADDRESS)
 {
 }
 
@@ -56,7 +58,13 @@
 bool
 ClangUtilityFunction::Install (Stream &error_stream,
                                ExecutionContext &exe_ctx)
-{    
+{
+    if (m_jit_begin != LLDB_INVALID_ADDRESS)
+    {
+        error_stream.PutCString("error: already installed\n");
+        return false;
+    }
+    
     ////////////////////////////////////
     // Set up the target and compiler
     //

Added: lldb/trunk/source/Expression/IRDynamicChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRDynamicChecks.cpp?rev=112690&view=auto
==============================================================================
--- lldb/trunk/source/Expression/IRDynamicChecks.cpp (added)
+++ lldb/trunk/source/Expression/IRDynamicChecks.cpp Tue Aug 31 19:58:00 2010
@@ -0,0 +1,117 @@
+//===-- IRDynamicChecks.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/IRDynamicChecks.h"
+#include "lldb/Expression/ClangUtilityFunction.h"
+
+#include "lldb/Core/Log.h"
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+#include "llvm/Value.h"
+
+using namespace llvm;
+using namespace lldb_private;
+
+static char ID;
+
+static const char valid_pointer_check_text[] = 
+    "extern \"C\" void "
+    "___clang_valid_pointer_check (unsigned char *ptr)"
+    "{"
+        "unsigned char val = *ptr;"
+    "}";
+
+static const char valid_pointer_check_name[] = 
+    "___clang_valid_pointer_check";
+
+DynamicCheckerFunctions::DynamicCheckerFunctions ()
+{
+    m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
+                                                         valid_pointer_check_name));
+}
+
+DynamicCheckerFunctions::~DynamicCheckerFunctions ()
+{
+}
+
+bool
+DynamicCheckerFunctions::Install(Stream &error_stream,
+                                 ExecutionContext &exe_ctx)
+{
+    if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
+        return false;
+        
+    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)
+{
+    std::string s;
+    raw_string_ostream rso(s);
+    V->print(rso);
+    rso.flush();
+    if (truncate)
+        s.resize(s.length() - 1);
+    return s;
+}
+
+IRDynamicChecks::~IRDynamicChecks()
+{
+}
+
+bool
+IRDynamicChecks::runOnModule(llvm::Module &M)
+{
+    lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+    
+    llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
+    
+    if (!function)
+    {
+        if (log)
+            log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
+        
+        return false;
+    }
+    
+    llvm::Function::iterator bbi;
+    
+    for (bbi = function->begin();
+         bbi != function->end();
+         ++bbi)
+    {
+    }
+    
+    return true;    
+}
+
+void
+IRDynamicChecks::assignPassManager(PMStack &PMS,
+                                   PassManagerType T)
+{
+}
+
+PassManagerType
+IRDynamicChecks::getPotentialPassManagerType() const
+{
+    return PMT_ModulePassManager;
+}





More information about the lldb-commits mailing list