[Lldb-commits] [lldb] r143419 - in /lldb/trunk: include/lldb/Expression/ include/lldb/Target/ source/Expression/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Plugins/Process/Utility/ source/Target/ test/lang/objc/objc-checker/
Jim Ingham
jingham at apple.com
Mon Oct 31 19:46:54 PDT 2011
Author: jingham
Date: Mon Oct 31 21:46:54 2011
New Revision: 143419
URL: http://llvm.org/viewvc/llvm-project?rev=143419&view=rev
Log:
Enhanced the ObjC DynamicCheckerFunction to test for "object responds to selector" as well as
"object borked"... Also made the error when the checker fails reflect this fact rather than
report a crash at 0x0.
Also a little cleanup:
- StopInfoMachException had a redundant copy of the description string.
- ThreadPlanCallFunction had a redundant copy of the thread, and had a
copy of the process that it didn't really need.
Added:
lldb/trunk/test/lang/objc/objc-checker/
lldb/trunk/test/lang/objc/objc-checker/Makefile
lldb/trunk/test/lang/objc/objc-checker/TestObjCCheckers.py
lldb/trunk/test/lang/objc/objc-checker/main.m
Modified:
lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
lldb/trunk/source/Expression/IRDynamicChecks.cpp
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h
lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
Modified: lldb/trunk/include/lldb/Expression/IRDynamicChecks.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRDynamicChecks.h?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRDynamicChecks.h (original)
+++ lldb/trunk/include/lldb/Expression/IRDynamicChecks.h Mon Oct 31 21:46:54 2011
@@ -10,6 +10,7 @@
#ifndef liblldb_IRDynamicChecks_h_
#define liblldb_IRDynamicChecks_h_
+#include "lldb-types.h"
#include "llvm/Pass.h"
namespace llvm {
@@ -74,6 +75,8 @@
bool Install (Stream &error_stream,
ExecutionContext &exe_ctx);
+ bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message);
+
std::auto_ptr<ClangUtilityFunction> m_valid_pointer_check;
std::auto_ptr<ClangUtilityFunction> m_objc_object_check;
};
Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h Mon Oct 31 21:46:54 2011
@@ -127,6 +127,12 @@
{
return m_real_stop_info_sp;
}
+
+ lldb::addr_t
+ GetStopAddress ()
+ {
+ return m_stop_address;
+ }
protected:
void ReportRegisterState (const char *message);
@@ -148,8 +154,8 @@
Address m_function_addr;
Address m_start_addr;
lldb::addr_t m_function_sp;
- Process &m_process;
- Thread &m_thread;
+// Process &m_process;
+// Thread &m_thread;
Thread::RegisterCheckpoint m_register_backup;
lldb::ThreadPlanSP m_subplan_sp;
LanguageRuntime *m_cxx_language_runtime;
@@ -161,6 +167,7 @@
// This gets set in DoTakedown.
lldb::ValueSP m_return_value_sp; // If this contains a valid pointer, use the ABI to extract values when complete
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
+ lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};
Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h Mon Oct 31 21:46:54 2011
@@ -48,6 +48,9 @@
m_user_expression_sp.reset();
}
+ virtual lldb::StopInfoSP
+ GetRealStopInfo();
+
protected:
private:
ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
Modified: lldb/trunk/source/Expression/IRDynamicChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRDynamicChecks.cpp?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRDynamicChecks.cpp (original)
+++ lldb/trunk/source/Expression/IRDynamicChecks.cpp Mon Oct 31 21:46:54 2011
@@ -74,6 +74,25 @@
return true;
}
+bool
+DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &message)
+{
+ // FIXME: We have to get the checkers to know why they scotched the call in more detail,
+ // so we can print a better message here.
+ if (m_valid_pointer_check.get() != NULL && m_valid_pointer_check->ContainsAddress(addr))
+ {
+ message.Printf ("Attempted to dereference an invalid pointer.");
+ return true;
+ }
+ else if (m_objc_object_check.get() != NULL && m_objc_object_check->ContainsAddress(addr))
+ {
+ message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector");
+ return true;
+ }
+ return false;
+}
+
+
static std::string
PrintValue(llvm::Value *V, bool truncate = false)
{
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Mon Oct 31 21:46:54 2011
@@ -99,7 +99,7 @@
m_isa_to_name_cache(),
m_isa_to_parent_cache()
{
- m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(ConstString("gdb_object_getClass")) != NULL);
+ m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(ConstString("gdb_object_getClass"), eSymbolTypeCode) != NULL);
}
bool
@@ -492,38 +492,56 @@
ClangUtilityFunction *
AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
{
- char check_function_code[1024];
+ char check_function_code[2048];
int len = 0;
if (m_has_object_getClass)
{
len = ::snprintf (check_function_code,
sizeof(check_function_code),
- "extern \"C\" void *gdb_object_getClass(void *); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " if ($__lldb_arg_obj == (void *)0) \n"
- " return; // nil is ok \n"
- " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- "} \n",
+ "extern \"C\" void *gdb_object_getClass(void *); \n"
+ "extern \"C\" int printf(const char *format, ...); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " else if ($__lldb_arg_selector != (void *)0) \n"
+ " { \n"
+ " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
+ " respondsToSelector: \n"
+ " (struct objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " } \n"
+ "} \n",
name);
}
else
{
len = ::snprintf (check_function_code,
sizeof(check_function_code),
- "extern \"C\" void *gdb_class_getClass(void *); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " if ($__lldb_arg_obj == (void *)0) \n"
- " return; // nil is ok \n"
- " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
- " if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr)) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- "} \n",
+ "extern \"C\" void *gdb_class_getClass(void *); \n"
+ "extern \"C\" int printf(const char *format, ...); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
+ " if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " else if ($__lldb_arg_selector != (void *)0) \n"
+ " { \n"
+ " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
+ " respondsToSelector: \n"
+ " (struct objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " } \n"
+ "} \n",
name);
}
Modified: lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h Mon Oct 31 21:46:54 2011
@@ -67,7 +67,6 @@
uint32_t m_exc_data_count;
uint64_t m_exc_code;
uint64_t m_exc_subcode;
- std::string m_description;
};
Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Mon Oct 31 21:46:54 2011
@@ -47,9 +47,8 @@
m_stop_other_threads (stop_other_threads),
m_function_addr (function),
m_function_sp (NULL),
- m_process (thread.GetProcess()),
- m_thread (thread),
- m_takedown_done (false)
+ m_takedown_done (false),
+ m_stop_address (LLDB_INVALID_ADDRESS)
{
SetOkayToDiscard (discard_on_error);
@@ -163,8 +162,6 @@
m_stop_other_threads (stop_other_threads),
m_function_addr (function),
m_function_sp(NULL),
- m_process (thread.GetProcess()),
- m_thread (thread),
m_takedown_done (false)
{
SetOkayToDiscard (discard_on_error);
@@ -294,6 +291,7 @@
if (log)
log->Printf ("DoTakedown called for thread 0x%4.4llx, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
m_takedown_done = true;
+ m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
m_real_stop_info_sp = GetPrivateStopReason();
m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
SetPlanComplete();
@@ -324,7 +322,7 @@
}
else
{
- s->Printf("Thread plan to call 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()));
+ s->Printf("Thread plan to call 0x%llx", m_function_addr.GetLoadAddress(&m_thread.GetProcess().GetTarget()));
}
}
@@ -474,8 +472,8 @@
void
ThreadPlanCallFunction::SetBreakpoints ()
{
- m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
- m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
+ m_cxx_language_runtime = m_thread.GetProcess().GetLanguageRuntime(eLanguageTypeC_plus_plus);
+ m_objc_language_runtime = m_thread.GetProcess().GetLanguageRuntime(eLanguageTypeObjC);
if (m_cxx_language_runtime)
m_cxx_language_runtime->SetExceptionBreakpoints();
Modified: lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp?rev=143419&r1=143418&r2=143419&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp Mon Oct 31 21:46:54 2011
@@ -55,6 +55,20 @@
void
ThreadPlanCallUserExpression::GetDescription (Stream *s, lldb::DescriptionLevel level)
-{
+{
ThreadPlanCallFunction::GetDescription (s, level);
}
+
+StopInfoSP
+ThreadPlanCallUserExpression::GetRealStopInfo()
+{
+ StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo();
+ lldb::addr_t addr = GetStopAddress();
+ DynamicCheckerFunctions *checkers = m_thread.GetProcess().GetDynamicCheckers();
+ StreamString s;
+
+ if (checkers && checkers->DoCheckersExplainStop(addr, s))
+ stop_info_sp->SetDescription(s.GetData());
+
+ return stop_info_sp;
+}
Added: lldb/trunk/test/lang/objc/objc-checker/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-checker/Makefile?rev=143419&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/objc-checker/Makefile (added)
+++ lldb/trunk/test/lang/objc/objc-checker/Makefile Mon Oct 31 21:46:54 2011
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+LDFLAGS = $(CFLAGS) -lobjc -framework Foundation
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/test/lang/objc/objc-checker/TestObjCCheckers.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-checker/TestObjCCheckers.py?rev=143419&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/objc-checker/TestObjCCheckers.py (added)
+++ lldb/trunk/test/lang/objc/objc-checker/TestObjCCheckers.py Mon Oct 31 21:46:54 2011
@@ -0,0 +1,85 @@
+"""
+Use lldb Python API to make sure the dynamic checkers are doing their jobs.
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class ObjCDynamicValueTestCase(TestBase):
+
+ mydir = os.path.join("lang", "objc", "objc-checker")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @python_api_test
+ def test_get_dynamic_objc_vals_with_dsym(self):
+ """Test that checkers catch unrecognized selectors"""
+ self.buildDsym()
+ self.do_test_checkers()
+
+ @python_api_test
+ def test_get_objc_dynamic_vals_with_dwarf(self):
+ """Test that checkers catch unrecognized selectors"""
+ self.buildDwarf()
+ self.do_test_checkers()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ # Find the line number to break for main.c.
+
+ self.source_name = 'main.m'
+
+ def do_test_checkers (self):
+ """Make sure the dynamic checkers catch messages to unrecognized selectors"""
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ # Create a target from the debugger.
+
+ target = self.dbg.CreateTarget (exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Set up our breakpoints:
+
+
+ main_bkpt = target.BreakpointCreateBySourceRegex ("Set a breakpoint here.", lldb.SBFileSpec (self.source_name))
+ self.assertTrue(main_bkpt and
+ main_bkpt.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple (None, None, os.getcwd())
+
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ PROCESS_STOPPED)
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint (process, main_bkpt)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+
+ #
+ # The class Simple doesn't have a count method. Make sure that we don't
+ # actually try to send count but catch it as an unrecognized selector.
+
+ frame = thread.GetFrameAtIndex(0)
+ expr_value = frame.EvaluateExpression("(int) [my_simple count]", False)
+ expr_error = expr_value.GetError()
+
+ self.assertTrue (expr_error.Fail())
+
+ # Make sure the call produced no NSLog stdout.
+ stdout = process.GetSTDOUT(100)
+ self.assertTrue (len(stdout) == 0)
+
+ # Make sure the error is helpful:
+ err_string = expr_error.GetCString()
+ self.assertTrue ("selector" in err_string)
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/lang/objc/objc-checker/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-checker/main.m?rev=143419&view=auto
==============================================================================
--- lldb/trunk/test/lang/objc/objc-checker/main.m (added)
+++ lldb/trunk/test/lang/objc/objc-checker/main.m Mon Oct 31 21:46:54 2011
@@ -0,0 +1,30 @@
+#import <Foundation/Foundation.h>
+
+ at interface Simple : NSObject
+{
+ int _value;
+}
+- (int) value;
+- (void) setValue: (int) newValue;
+ at end
+
+ at implementation Simple
+- (int) value
+{
+ return _value;
+}
+
+- (void) setValue: (int) newValue
+{
+ _value = newValue;
+}
+ at end
+
+int main ()
+{
+ Simple *my_simple = [[Simple alloc] init];
+ my_simple.value = 20;
+ // Set a breakpoint here.
+ NSLog (@"Object has value: %d.", my_simple.value);
+ return 0;
+}
More information about the lldb-commits
mailing list