summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2010-09-01 00:58:00 +0000
committerSean Callanan <scallanan@apple.com>2010-09-01 00:58:00 +0000
commit6961e87847cd39a65ecde0342ec5c7d1dee9622c (patch)
treeb49e5acd42822d3575f26dd66242ebce14d65293
parent6aaebe877bbff9d9b3b6e639d6e79d79fa50ebea (diff)
downloadbcm5719-llvm-6961e87847cd39a65ecde0342ec5c7d1dee9622c.tar.gz
bcm5719-llvm-6961e87847cd39a65ecde0342ec5c7d1dee9622c.zip
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 llvm-svn: 112690
-rw-r--r--lldb/include/lldb/Expression/IRDynamicChecks.h141
-rw-r--r--lldb/include/lldb/Target/Process.h12
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj9
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp21
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp11
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp12
-rw-r--r--lldb/source/Expression/IRDynamicChecks.cpp117
7 files changed, 320 insertions, 3 deletions
diff --git a/lldb/include/lldb/Expression/IRDynamicChecks.h b/lldb/include/lldb/Expression/IRDynamicChecks.h
new file mode 100644
index 00000000000..bb875ae8f5a
--- /dev/null
+++ b/lldb/include/lldb/Expression/IRDynamicChecks.h
@@ -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
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 9664e94bb8d..d8e86370ae8 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -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 @@ public:
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 @@ protected:
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;
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 29a29924de3..267a01f2ca6 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -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;
};
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index b29c0c7777d..9026b743a0e 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -190,6 +190,27 @@ bool
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))
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 7c4cc6a0d52..1bc8866975b 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -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 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr,
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();
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index 3acd3f283fa..17ba7dba331 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -37,7 +37,9 @@ using namespace lldb_private;
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 @@ ClangUtilityFunction::ClangUtilityFunction (const char *text,
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
//
diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp
new file mode 100644
index 00000000000..21fd7d26250
--- /dev/null
+++ b/lldb/source/Expression/IRDynamicChecks.cpp
@@ -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;
+}
OpenPOWER on IntegriCloud