[Lldb-commits] [lldb] r127830 - /lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
Jim Ingham
jingham at apple.com
Thu Mar 17 14:04:33 PDT 2011
Author: jingham
Date: Thu Mar 17 16:04:33 2011
New Revision: 127830
URL: http://llvm.org/viewvc/llvm-project?rev=127830&view=rev
Log:
Fix a problem where we were looking up the class pointer in the {class/sel -> implementation} cache for a objc_msgSendSuper call - where we should have looked up the class's super-class.
Modified:
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=127830&r1=127829&r2=127830&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Thu Mar 17 16:04:33 2011
@@ -664,35 +664,127 @@
if (!success)
return ret_plan_sp;
- // Pull the class out of the Object and see if we've already cached this method call,
- // If so we can push a run-to-address plan directly. Otherwise we have to figure out where
- // the implementation lives.
-
- Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
-
- // This is a little cheesy, but since object->isa is the first field,
- // making the object value a load address value and resolving it will get
- // the pointer sized data pointed to by that value...
ExecutionContext exe_ctx;
thread.CalculateExecutionContext (exe_ctx);
- isa_value.SetValueType(Value::eValueTypeLoadAddress);
- isa_value.ResolveValue(&exe_ctx, clang_ast_context->getASTContext());
- lldb::addr_t isa_addr = isa_value.GetScalar().ULongLong();
+ // isa_addr will store the class pointer that the method is being dispatched to - so either the class
+ // directly or the super class if this is one of the objc_msgSendSuper flavors. That's mostly used to
+ // look up the class/selector pair in our cache.
+
+ lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
+
+ // Figure out the class this is being dispatched to and see if we've already cached this method call,
+ // If so we can push a run-to-address plan directly. Otherwise we have to figure out where
+ // the implementation lives.
- if (log)
+ if (this_dispatch.is_super)
{
- log->Printf("Resolving method call for class - 0x%llx and selector - 0x%llx",
- isa_addr, sel_addr);
+ if (this_dispatch.is_super2)
+ {
+ // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing
+ // the object and the class to which the super message is being sent. So we need to dig the super
+ // out of the class and use that.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext());
+
+ if (super_value.GetScalar().IsValid())
+ {
+
+ // isa_value now holds the class pointer. The second word of the class pointer is the super-class pointer:
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext());
+ if (super_value.GetScalar().IsValid())
+ isa_addr = super_value.GetScalar().ULongLong();
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the super class value from the class in objc_super.");
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ }
+ else
+ {
+ // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing
+ // the object and the super class to which the super message is being sent. So the class we want is
+ // the second element of this structure.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext());
+
+ if (super_value.GetScalar().IsValid())
+ {
+ isa_addr = super_value.GetScalar().ULongLong();
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ }
}
- ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
- assert(objc_runtime != NULL);
+ else
+ {
+ // In the direct dispatch case, the object->isa is the class pointer we want.
+
+ // This is a little cheesy, but since object->isa is the first field,
+ // making the object value a load address value and resolving it will get
+ // the pointer sized data pointed to by that value...
+
+ // Note, it isn't a fatal error not to be able to get the address from the object, since this might
+ // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus.
+
+ Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
+
+ isa_value.SetValueType(Value::eValueTypeLoadAddress);
+ isa_value.ResolveValue(&exe_ctx, clang_ast_context->getASTContext());
+ if (isa_value.GetScalar().IsValid())
+ {
+ isa_addr = isa_value.GetScalar().ULongLong();
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the isa value from object.");
+ }
+
+ }
+
+ // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache:
+ lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
- lldb::addr_t impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
-
- if (impl_addr == LLDB_INVALID_ADDRESS)
- {
+ if (isa_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ {
+ log->Printf("Resolving call for class - 0x%llx and selector - 0x%llx",
+ isa_addr, sel_addr);
+ }
+ ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
+ assert(objc_runtime != NULL);
+
+ impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
+ }
+
+ if (impl_addr != LLDB_INVALID_ADDRESS)
+ {
+ // Yup, it was in the cache, so we can run to that address directly.
+
+ if (log)
+ log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);
+
+ ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
+ }
+ else
+ {
// We haven't seen this class/selector pair yet. Look it up.
StreamString errors;
Address impl_code_address;
@@ -866,13 +958,6 @@
log->Printf("Using ObjC step plan: %s.\n", s.GetData());
}
}
- else
- {
- if (log)
- log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);
-
- ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
- }
}
return ret_plan_sp;
More information about the lldb-commits
mailing list