forked from OSchip/llvm-project
Objective C cleanup. Removed an cache that was no longer needed and changes the code that gets the dynamic type and class name to use our new Objective C cache.
llvm-svn: 166512
This commit is contained in:
parent
edf8e38701
commit
d64dd12fcf
|
@ -349,10 +349,10 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
SetName (ConstString &type_name_const_str);
|
||||
SetName (const ConstString &type_name);
|
||||
|
||||
void
|
||||
SetName (const char *type_name_str);
|
||||
SetName (const char *type_name_cstr);
|
||||
|
||||
void
|
||||
SetTypeSP (lldb::TypeSP type_sp);
|
||||
|
|
|
@ -45,14 +45,16 @@ public:
|
|||
public:
|
||||
|
||||
ClassDescriptor() :
|
||||
m_is_kvo(eLazyBoolCalculate),
|
||||
m_is_cf(eLazyBoolCalculate)
|
||||
{}
|
||||
|
||||
ClassDescriptor (ObjCISA isa, lldb::ProcessSP process) :
|
||||
m_is_kvo(eLazyBoolCalculate),
|
||||
m_is_cf(eLazyBoolCalculate)
|
||||
{}
|
||||
m_is_kvo (eLazyBoolCalculate),
|
||||
m_is_cf (eLazyBoolCalculate),
|
||||
m_type_wp ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~ClassDescriptor ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ConstString
|
||||
GetClassName () = 0;
|
||||
|
@ -118,9 +120,17 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual
|
||||
~ClassDescriptor ()
|
||||
{}
|
||||
lldb::TypeSP
|
||||
GetType ()
|
||||
{
|
||||
return m_type_wp.lock();
|
||||
}
|
||||
|
||||
void
|
||||
SetType (const lldb::TypeSP &type_sp)
|
||||
{
|
||||
m_type_wp = type_sp;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool
|
||||
|
@ -133,6 +143,7 @@ public:
|
|||
private:
|
||||
LazyBool m_is_kvo;
|
||||
LazyBool m_is_cf;
|
||||
lldb::TypeWP m_type_wp;
|
||||
};
|
||||
|
||||
// a convenience subclass of ClassDescriptor meant to represent invalid objects
|
||||
|
@ -141,6 +152,10 @@ public:
|
|||
public:
|
||||
ClassDescriptor_Invalid() {}
|
||||
|
||||
virtual
|
||||
~ClassDescriptor_Invalid ()
|
||||
{}
|
||||
|
||||
virtual ConstString
|
||||
GetClassName () { return ConstString(""); }
|
||||
|
||||
|
@ -164,11 +179,6 @@ public:
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual
|
||||
~ClassDescriptor_Invalid ()
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
virtual ClassDescriptorSP
|
||||
|
@ -443,10 +453,6 @@ protected:
|
|||
ISAToDescriptorMap m_isa_to_descriptor_cache;
|
||||
bool m_isa_to_descriptor_cache_is_up_to_date;
|
||||
|
||||
typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap;
|
||||
typedef ClassNameMap::iterator ClassNameIterator;
|
||||
ClassNameMap m_class_name_cache;
|
||||
|
||||
typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
|
||||
CompleteClassMap m_complete_class_cache;
|
||||
|
||||
|
|
|
@ -259,152 +259,31 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
|||
if (CouldHaveDynamicValue (in_value))
|
||||
{
|
||||
// First job, pull out the address at 0 offset from the object That will be the ISA pointer.
|
||||
Error error;
|
||||
const addr_t object_ptr = in_value.GetPointerValue();
|
||||
const addr_t isa_addr = m_process->ReadPointerFromMemory (object_ptr, error);
|
||||
|
||||
if (error.Fail())
|
||||
return false;
|
||||
|
||||
address.SetRawAddress(object_ptr);
|
||||
|
||||
// First check the cache...
|
||||
SymbolContext sc;
|
||||
class_type_or_name = LookupInClassNameCache (isa_addr);
|
||||
|
||||
if (!class_type_or_name.IsEmpty())
|
||||
ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
|
||||
if (objc_class_sp)
|
||||
{
|
||||
if (class_type_or_name.GetTypeSP())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
const addr_t object_ptr = in_value.GetPointerValue();
|
||||
address.SetRawAddress(object_ptr);
|
||||
|
||||
// We don't have the object cached, so make sure the class
|
||||
// address is readable, otherwise this is not a good object:
|
||||
m_process->ReadPointerFromMemory (isa_addr, error);
|
||||
|
||||
if (error.Fail())
|
||||
return false;
|
||||
|
||||
const char *class_name = NULL;
|
||||
Address isa_address;
|
||||
Target &target = m_process->GetTarget();
|
||||
target.GetSectionLoadList().ResolveLoadAddress (isa_addr, isa_address);
|
||||
|
||||
if (isa_address.IsValid())
|
||||
{
|
||||
// If the ISA pointer points to one of the sections in the binary, then see if we can
|
||||
// get the class name from the symbols.
|
||||
|
||||
SectionSP section_sp (isa_address.GetSection());
|
||||
|
||||
if (section_sp)
|
||||
{
|
||||
// If this points to a section that we know about, then this is
|
||||
// some static class or nothing. See if it is in the right section
|
||||
// and if its name is the right form.
|
||||
ConstString section_name = section_sp->GetName();
|
||||
static ConstString g_objc_class_section_name ("__objc_data");
|
||||
if (section_name == g_objc_class_section_name)
|
||||
{
|
||||
isa_address.CalculateSymbolContext(&sc, eSymbolContextModule | eSymbolContextSymbol);
|
||||
if (sc.symbol)
|
||||
{
|
||||
if (sc.symbol->GetType() == eSymbolTypeObjCClass)
|
||||
class_name = sc.symbol->GetName().GetCString();
|
||||
else if (sc.symbol->GetType() == eSymbolTypeObjCMetaClass)
|
||||
{
|
||||
// FIXME: Meta-classes can't have dynamic types...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char class_buffer[1024];
|
||||
if (class_name == NULL && use_dynamic == eDynamicCanRunTarget)
|
||||
{
|
||||
// If the class address didn't point into the binary, or
|
||||
// it points into the right section but there wasn't a symbol
|
||||
// there, try to look it up by calling the class method in the target.
|
||||
|
||||
ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
|
||||
|
||||
Thread *thread_to_use = exe_ctx.GetThreadPtr();
|
||||
|
||||
if (thread_to_use == NULL)
|
||||
thread_to_use = m_process->GetThreadList().GetSelectedThread().get();
|
||||
|
||||
if (thread_to_use == NULL)
|
||||
return false;
|
||||
|
||||
if (!RunFunctionToFindClassName (object_ptr, thread_to_use, class_buffer, 1024))
|
||||
return false;
|
||||
|
||||
class_name = class_buffer;
|
||||
|
||||
}
|
||||
|
||||
if (class_name && class_name[0])
|
||||
{
|
||||
class_type_or_name.SetName (class_name);
|
||||
|
||||
TypeList class_types;
|
||||
const bool exact_match = true;
|
||||
uint32_t num_matches = target.GetImages().FindTypes (sc,
|
||||
class_type_or_name.GetName(),
|
||||
exact_match,
|
||||
UINT32_MAX,
|
||||
class_types);
|
||||
if (num_matches == 1)
|
||||
{
|
||||
class_type_or_name.SetTypeSP (class_types.GetTypeAtIndex(0));
|
||||
return true;
|
||||
}
|
||||
ConstString class_name (objc_class_sp->GetClassName());
|
||||
class_type_or_name.SetName(class_name);
|
||||
TypeSP type_sp (objc_class_sp->GetType());
|
||||
if (type_sp)
|
||||
class_type_or_name.SetTypeSP (type_sp);
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < num_matches; i++)
|
||||
type_sp = LookupInCompleteClassCache (class_name);
|
||||
if (type_sp)
|
||||
{
|
||||
TypeSP this_type(class_types.GetTypeAtIndex(i));
|
||||
if (this_type)
|
||||
{
|
||||
// Only consider "real" ObjC classes. For now this means avoiding
|
||||
// the Type objects that are made up from the OBJC_CLASS_$_<NAME> symbols.
|
||||
// we don't want to use them since they are empty and useless.
|
||||
if (this_type->IsRealObjCClass())
|
||||
{
|
||||
// There can only be one type with a given name,
|
||||
// so we've just found duplicate definitions, and this
|
||||
// one will do as well as any other.
|
||||
// We don't consider something to have a dynamic type if
|
||||
// it is the same as the static type. So compare against
|
||||
// the value we were handed:
|
||||
|
||||
clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
|
||||
clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
|
||||
if (in_ast_ctx != this_ast_ctx
|
||||
|| !ClangASTContext::AreTypesSame (in_ast_ctx,
|
||||
in_value.GetClangType(),
|
||||
this_type->GetClangFullType()))
|
||||
{
|
||||
class_type_or_name.SetTypeSP (this_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
objc_class_sp->SetType (type_sp);
|
||||
class_type_or_name.SetTypeSP (type_sp);
|
||||
}
|
||||
}
|
||||
|
||||
AddToClassNameCache (isa_addr, class_type_or_name);
|
||||
if (class_type_or_name.GetTypeSP())
|
||||
if (type_sp)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1578,17 @@ AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
|
|||
Error error;
|
||||
ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
|
||||
if (isa != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (isa);
|
||||
if (isa && !objc_class_sp)
|
||||
{
|
||||
lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
|
||||
if (log)
|
||||
log->Printf("0x%llx: AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%llx",
|
||||
isa_pointer,
|
||||
isa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -838,15 +838,15 @@ TypeAndOrName::GetName () const
|
|||
}
|
||||
|
||||
void
|
||||
TypeAndOrName::SetName (ConstString &type_name_const_str)
|
||||
TypeAndOrName::SetName (const ConstString &type_name)
|
||||
{
|
||||
m_type_name = type_name_const_str;
|
||||
m_type_name = type_name;
|
||||
}
|
||||
|
||||
void
|
||||
TypeAndOrName::SetName (const char *type_name_str)
|
||||
TypeAndOrName::SetName (const char *type_name_cstr)
|
||||
{
|
||||
m_type_name.SetCString (type_name_str);
|
||||
m_type_name.SetCString (type_name_cstr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -58,47 +58,6 @@ ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t
|
|||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
void
|
||||
ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
|
||||
if (log)
|
||||
{
|
||||
log->Printf ("Caching: class 0x%llx name: %s.", class_addr, name);
|
||||
}
|
||||
|
||||
TypeAndOrName class_type_or_name;
|
||||
|
||||
if (type_sp)
|
||||
class_type_or_name.SetTypeSP (type_sp);
|
||||
else if (name && *name != '\0')
|
||||
class_type_or_name.SetName (name);
|
||||
else
|
||||
return;
|
||||
m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
|
||||
}
|
||||
|
||||
void
|
||||
ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_type_or_name)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
|
||||
if (log)
|
||||
{
|
||||
log->Printf ("Caching: class 0x%llx name: %s.", class_addr, class_type_or_name.GetName().AsCString());
|
||||
}
|
||||
|
||||
m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
|
||||
}
|
||||
|
||||
TypeAndOrName
|
||||
ObjCLanguageRuntime::LookupInClassNameCache (lldb::addr_t class_addr)
|
||||
{
|
||||
ClassNameMap::iterator pos, end = m_class_name_cache.end();
|
||||
pos = m_class_name_cache.find (class_addr);
|
||||
if (pos != end)
|
||||
return (*pos).second;
|
||||
return TypeAndOrName ();
|
||||
}
|
||||
|
||||
lldb::TypeSP
|
||||
ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
|
||||
|
@ -107,72 +66,77 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
|
|||
|
||||
if (complete_class_iter != m_complete_class_cache.end())
|
||||
{
|
||||
TypeSP ret(complete_class_iter->second);
|
||||
// Check the weak pointer to make sure the type hasn't been unloaded
|
||||
TypeSP complete_type_sp (complete_class_iter->second.lock());
|
||||
|
||||
if (!ret)
|
||||
m_complete_class_cache.erase(name);
|
||||
if (complete_type_sp)
|
||||
return complete_type_sp;
|
||||
else
|
||||
return TypeSP(complete_class_iter->second);
|
||||
m_complete_class_cache.erase(name);
|
||||
}
|
||||
|
||||
ModuleList &modules = m_process->GetTarget().GetImages();
|
||||
|
||||
|
||||
SymbolContextList sc_list;
|
||||
const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
|
||||
eSymbolTypeObjCClass,
|
||||
sc_list);
|
||||
|
||||
modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
|
||||
|
||||
if (sc_list.GetSize() == 0)
|
||||
return TypeSP();
|
||||
|
||||
SymbolContext sc;
|
||||
|
||||
sc_list.GetContextAtIndex(0, sc);
|
||||
|
||||
ModuleSP module_sp(sc.module_sp);
|
||||
|
||||
if (!module_sp)
|
||||
return TypeSP();
|
||||
|
||||
const SymbolContext null_sc;
|
||||
const bool exact_match = true;
|
||||
const uint32_t max_matches = UINT32_MAX;
|
||||
TypeList types;
|
||||
|
||||
module_sp->FindTypes (null_sc,
|
||||
name,
|
||||
exact_match,
|
||||
max_matches,
|
||||
types);
|
||||
|
||||
if (types.GetSize() == 1)
|
||||
if (matching_symbols)
|
||||
{
|
||||
TypeSP candidate_type = types.GetTypeAtIndex(0);
|
||||
SymbolContext sc;
|
||||
|
||||
if (ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
|
||||
{
|
||||
m_complete_class_cache[name] = TypeWP(candidate_type);
|
||||
return candidate_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_list.GetContextAtIndex(0, sc);
|
||||
|
||||
ModuleSP module_sp(sc.module_sp);
|
||||
|
||||
if (!module_sp)
|
||||
return TypeSP();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t ti = 0, te = types.GetSize();
|
||||
ti < te;
|
||||
++ti)
|
||||
{
|
||||
TypeSP candidate_type = types.GetTypeAtIndex(ti);
|
||||
|
||||
if (candidate_type->IsCompleteObjCClass() &&
|
||||
ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
|
||||
const SymbolContext null_sc;
|
||||
const bool exact_match = true;
|
||||
const uint32_t max_matches = UINT32_MAX;
|
||||
TypeList types;
|
||||
|
||||
const uint32_t num_types = module_sp->FindTypes (null_sc,
|
||||
name,
|
||||
exact_match,
|
||||
max_matches,
|
||||
types);
|
||||
|
||||
if (num_types)
|
||||
{
|
||||
m_complete_class_cache[name] = TypeWP(candidate_type);
|
||||
return candidate_type;
|
||||
TypeSP incomplete_type_sp;
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_types; ++i)
|
||||
{
|
||||
TypeSP type_sp (types.GetTypeAtIndex(i));
|
||||
|
||||
if (ClangASTContext::IsObjCClassType(type_sp->GetClangForwardType()))
|
||||
{
|
||||
if (type_sp->IsCompleteObjCClass())
|
||||
{
|
||||
m_complete_class_cache[name] = type_sp;
|
||||
return type_sp;
|
||||
}
|
||||
else if (!incomplete_type_sp)
|
||||
incomplete_type_sp = type_sp;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find any "real" definitions, so just use any??? Why was
|
||||
// this being done? Prior to this, if there was 1 match only, then it
|
||||
// would always use any objc definition, else we would only accept a
|
||||
// definition if it was the real thing???? Doesn't make sense.
|
||||
|
||||
if (incomplete_type_sp)
|
||||
{
|
||||
m_complete_class_cache[name] = incomplete_type_sp;
|
||||
return incomplete_type_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TypeSP();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue