1254721Semaste//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste#include "clang/AST/Type.h"
10254721Semaste
11254721Semaste#include "lldb/Core/Log.h"
12254721Semaste#include "lldb/Core/MappedHash.h"
13254721Semaste#include "lldb/Core/Module.h"
14254721Semaste#include "lldb/Core/PluginManager.h"
15254721Semaste#include "lldb/Core/Timer.h"
16254721Semaste#include "lldb/Core/ValueObject.h"
17254721Semaste#include "lldb/Symbol/ClangASTContext.h"
18254721Semaste#include "lldb/Symbol/Type.h"
19254721Semaste#include "lldb/Symbol/TypeList.h"
20254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h"
21254721Semaste#include "lldb/Target/Target.h"
22254721Semaste
23254721Semaste#include "llvm/ADT/StringRef.h"
24254721Semaste
25254721Semasteusing namespace lldb;
26254721Semasteusing namespace lldb_private;
27254721Semaste
28254721Semaste//----------------------------------------------------------------------
29254721Semaste// Destructor
30254721Semaste//----------------------------------------------------------------------
31254721SemasteObjCLanguageRuntime::~ObjCLanguageRuntime()
32254721Semaste{
33254721Semaste}
34254721Semaste
35254721SemasteObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
36254721Semaste    LanguageRuntime (process),
37254721Semaste    m_has_new_literals_and_indexing (eLazyBoolCalculate),
38254721Semaste    m_isa_to_descriptor(),
39254721Semaste    m_isa_to_descriptor_stop_id (UINT32_MAX)
40254721Semaste{
41254721Semaste
42254721Semaste}
43254721Semaste
44254721Semastebool
45254721SemasteObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name)
46254721Semaste{
47254721Semaste    if (isa != 0)
48254721Semaste    {
49254721Semaste        m_isa_to_descriptor[isa] = descriptor_sp;
50254721Semaste        // class_name is assumed to be valid
51254721Semaste        m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
52254721Semaste        return true;
53254721Semaste    }
54254721Semaste    return false;
55254721Semaste}
56254721Semaste
57254721Semastevoid
58254721SemasteObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
59254721Semaste{
60254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
61254721Semaste    if (log)
62254721Semaste    {
63254721Semaste        log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
64254721Semaste    }
65254721Semaste    m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
66254721Semaste}
67254721Semaste
68254721Semastelldb::addr_t
69254721SemasteObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
70254721Semaste{
71254721Semaste    MsgImplMap::iterator pos, end = m_impl_cache.end();
72254721Semaste    pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
73254721Semaste    if (pos != end)
74254721Semaste        return (*pos).second;
75254721Semaste    return LLDB_INVALID_ADDRESS;
76254721Semaste}
77254721Semaste
78254721Semaste
79254721Semastelldb::TypeSP
80254721SemasteObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
81254721Semaste{
82254721Semaste    CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
83254721Semaste
84254721Semaste    if (complete_class_iter != m_complete_class_cache.end())
85254721Semaste    {
86254721Semaste        // Check the weak pointer to make sure the type hasn't been unloaded
87254721Semaste        TypeSP complete_type_sp (complete_class_iter->second.lock());
88254721Semaste
89254721Semaste        if (complete_type_sp)
90254721Semaste            return complete_type_sp;
91254721Semaste        else
92254721Semaste            m_complete_class_cache.erase(name);
93254721Semaste    }
94254721Semaste
95254721Semaste    if (m_negative_complete_class_cache.count(name) > 0)
96254721Semaste        return TypeSP();
97254721Semaste
98254721Semaste    const ModuleList &modules = m_process->GetTarget().GetImages();
99254721Semaste
100254721Semaste    SymbolContextList sc_list;
101254721Semaste    const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
102254721Semaste                                                                        eSymbolTypeObjCClass,
103254721Semaste                                                                        sc_list);
104254721Semaste
105254721Semaste    if (matching_symbols)
106254721Semaste    {
107254721Semaste        SymbolContext sc;
108254721Semaste
109254721Semaste        sc_list.GetContextAtIndex(0, sc);
110254721Semaste
111254721Semaste        ModuleSP module_sp(sc.module_sp);
112254721Semaste
113254721Semaste        if (!module_sp)
114254721Semaste            return TypeSP();
115254721Semaste
116254721Semaste        const SymbolContext null_sc;
117254721Semaste        const bool exact_match = true;
118254721Semaste        const uint32_t max_matches = UINT32_MAX;
119254721Semaste        TypeList types;
120254721Semaste
121254721Semaste        const uint32_t num_types = module_sp->FindTypes (null_sc,
122254721Semaste                                                         name,
123254721Semaste                                                         exact_match,
124254721Semaste                                                         max_matches,
125254721Semaste                                                         types);
126254721Semaste
127254721Semaste        if (num_types)
128254721Semaste        {
129254721Semaste            uint32_t i;
130254721Semaste            for (i = 0; i < num_types; ++i)
131254721Semaste            {
132254721Semaste                TypeSP type_sp (types.GetTypeAtIndex(i));
133254721Semaste
134254721Semaste                if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType())
135254721Semaste                {
136254721Semaste                    if (type_sp->IsCompleteObjCClass())
137254721Semaste                    {
138254721Semaste                        m_complete_class_cache[name] = type_sp;
139254721Semaste                        return type_sp;
140254721Semaste                    }
141254721Semaste                }
142254721Semaste            }
143254721Semaste        }
144254721Semaste    }
145254721Semaste    m_negative_complete_class_cache.insert(name);
146254721Semaste    return TypeSP();
147254721Semaste}
148254721Semaste
149254721Semastesize_t
150254721SemasteObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
151254721Semaste{
152254721Semaste    return LLDB_INVALID_IVAR_OFFSET;
153254721Semaste}
154254721Semaste
155254721Semastevoid
156254721SemasteObjCLanguageRuntime::MethodName::Clear()
157254721Semaste{
158254721Semaste    m_full.Clear();
159254721Semaste    m_class.Clear();
160254721Semaste    m_category.Clear();
161254721Semaste    m_selector.Clear();
162254721Semaste    m_type = eTypeUnspecified;
163254721Semaste    m_category_is_valid = false;
164254721Semaste}
165254721Semaste
166254721Semaste//bool
167254721Semaste//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
168254721Semaste//{
169254721Semaste//    Clear();
170254721Semaste//    if (name && name[0])
171254721Semaste//    {
172254721Semaste//        // If "strict" is true. then the method must be specified with a
173254721Semaste//        // '+' or '-' at the beginning. If "strict" is false, then the '+'
174254721Semaste//        // or '-' can be omitted
175254721Semaste//        bool valid_prefix = false;
176254721Semaste//
177254721Semaste//        if (name[0] == '+' || name[0] == '-')
178254721Semaste//        {
179254721Semaste//            valid_prefix = name[1] == '[';
180254721Semaste//        }
181254721Semaste//        else if (!strict)
182254721Semaste//        {
183254721Semaste//            // "strict" is false, the name just needs to start with '['
184254721Semaste//            valid_prefix = name[0] == '[';
185254721Semaste//        }
186254721Semaste//
187254721Semaste//        if (valid_prefix)
188254721Semaste//        {
189254721Semaste//            static RegularExpression g_regex("^([-+]?)\\[([A-Za-z_][A-Za-z_0-9]*)(\\([A-Za-z_][A-Za-z_0-9]*\\))? ([A-Za-z_][A-Za-z_0-9:]*)\\]$");
190254721Semaste//            llvm::StringRef matches[4];
191254721Semaste//            // Since we are using a global regular expression, we must use the threadsafe version of execute
192254721Semaste//            if (g_regex.ExecuteThreadSafe(name, matches, 4))
193254721Semaste//            {
194254721Semaste//                m_full.SetCString(name);
195254721Semaste//                if (matches[0].empty())
196254721Semaste//                    m_type = eTypeUnspecified;
197254721Semaste//                else if (matches[0][0] == '+')
198254721Semaste//                    m_type = eTypeClassMethod;
199254721Semaste//                else
200254721Semaste//                    m_type = eTypeInstanceMethod;
201254721Semaste//                m_class.SetString(matches[1]);
202254721Semaste//                m_selector.SetString(matches[3]);
203254721Semaste//                if (!matches[2].empty())
204254721Semaste//                    m_category.SetString(matches[2]);
205254721Semaste//            }
206254721Semaste//        }
207254721Semaste//    }
208254721Semaste//    return IsValid(strict);
209254721Semaste//}
210254721Semaste
211254721Semastebool
212254721SemasteObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
213254721Semaste{
214254721Semaste    Clear();
215254721Semaste    if (name && name[0])
216254721Semaste    {
217254721Semaste        // If "strict" is true. then the method must be specified with a
218254721Semaste        // '+' or '-' at the beginning. If "strict" is false, then the '+'
219254721Semaste        // or '-' can be omitted
220254721Semaste        bool valid_prefix = false;
221254721Semaste
222254721Semaste        if (name[0] == '+' || name[0] == '-')
223254721Semaste        {
224254721Semaste            valid_prefix = name[1] == '[';
225254721Semaste            if (name[0] == '+')
226254721Semaste                m_type = eTypeClassMethod;
227254721Semaste            else
228254721Semaste                m_type = eTypeInstanceMethod;
229254721Semaste        }
230254721Semaste        else if (!strict)
231254721Semaste        {
232254721Semaste            // "strict" is false, the name just needs to start with '['
233254721Semaste            valid_prefix = name[0] == '[';
234254721Semaste        }
235254721Semaste
236254721Semaste        if (valid_prefix)
237254721Semaste        {
238254721Semaste            int name_len = strlen (name);
239254721Semaste            // Objective C methods must have at least:
240254721Semaste            //      "-[" or "+[" prefix
241254721Semaste            //      One character for a class name
242254721Semaste            //      One character for the space between the class name
243254721Semaste            //      One character for the method name
244254721Semaste            //      "]" suffix
245254721Semaste            if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
246254721Semaste            {
247254721Semaste                m_full.SetCStringWithLength(name, name_len);
248254721Semaste            }
249254721Semaste        }
250254721Semaste    }
251254721Semaste    return IsValid(strict);
252254721Semaste}
253254721Semaste
254254721Semasteconst ConstString &
255254721SemasteObjCLanguageRuntime::MethodName::GetClassName ()
256254721Semaste{
257254721Semaste    if (!m_class)
258254721Semaste    {
259254721Semaste        if (IsValid(false))
260254721Semaste        {
261254721Semaste            const char *full = m_full.GetCString();
262254721Semaste            const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
263254721Semaste            const char *paren_pos = strchr (class_start, '(');
264254721Semaste            if (paren_pos)
265254721Semaste            {
266254721Semaste                m_class.SetCStringWithLength (class_start, paren_pos - class_start);
267254721Semaste            }
268254721Semaste            else
269254721Semaste            {
270254721Semaste                // No '(' was found in the full name, we can definitively say
271254721Semaste                // that our category was valid (and empty).
272254721Semaste                m_category_is_valid = true;
273254721Semaste                const char *space_pos = strchr (full, ' ');
274254721Semaste                if (space_pos)
275254721Semaste                {
276254721Semaste                    m_class.SetCStringWithLength (class_start, space_pos - class_start);
277254721Semaste                    if (!m_class_category)
278254721Semaste                    {
279254721Semaste                        // No category in name, so we can also fill in the m_class_category
280254721Semaste                        m_class_category = m_class;
281254721Semaste                    }
282254721Semaste                }
283254721Semaste            }
284254721Semaste        }
285254721Semaste    }
286254721Semaste    return m_class;
287254721Semaste}
288254721Semaste
289254721Semasteconst ConstString &
290254721SemasteObjCLanguageRuntime::MethodName::GetClassNameWithCategory ()
291254721Semaste{
292254721Semaste    if (!m_class_category)
293254721Semaste    {
294254721Semaste        if (IsValid(false))
295254721Semaste        {
296254721Semaste            const char *full = m_full.GetCString();
297254721Semaste            const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
298254721Semaste            const char *space_pos = strchr (full, ' ');
299254721Semaste            if (space_pos)
300254721Semaste            {
301254721Semaste                m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
302254721Semaste                // If m_class hasn't been filled in and the class with category doesn't
303254721Semaste                // contain a '(', then we can also fill in the m_class
304254721Semaste                if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
305254721Semaste                {
306254721Semaste                    m_class = m_class_category;
307254721Semaste                    // No '(' was found in the full name, we can definitively say
308254721Semaste                    // that our category was valid (and empty).
309254721Semaste                    m_category_is_valid = true;
310254721Semaste
311254721Semaste                }
312254721Semaste            }
313254721Semaste        }
314254721Semaste    }
315254721Semaste    return m_class_category;
316254721Semaste}
317254721Semaste
318254721Semasteconst ConstString &
319254721SemasteObjCLanguageRuntime::MethodName::GetSelector ()
320254721Semaste{
321254721Semaste    if (!m_selector)
322254721Semaste    {
323254721Semaste        if (IsValid(false))
324254721Semaste        {
325254721Semaste            const char *full = m_full.GetCString();
326254721Semaste            const char *space_pos = strchr (full, ' ');
327254721Semaste            if (space_pos)
328254721Semaste            {
329254721Semaste                ++space_pos; // skip the space
330254721Semaste                m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
331254721Semaste            }
332254721Semaste        }
333254721Semaste    }
334254721Semaste    return m_selector;
335254721Semaste}
336254721Semaste
337254721Semasteconst ConstString &
338254721SemasteObjCLanguageRuntime::MethodName::GetCategory ()
339254721Semaste{
340254721Semaste    if (!m_category_is_valid && !m_category)
341254721Semaste    {
342254721Semaste        if (IsValid(false))
343254721Semaste        {
344254721Semaste            m_category_is_valid = true;
345254721Semaste            const char *full = m_full.GetCString();
346254721Semaste            const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
347254721Semaste            const char *open_paren_pos = strchr (class_start, '(');
348254721Semaste            if (open_paren_pos)
349254721Semaste            {
350254721Semaste                ++open_paren_pos; // Skip the open paren
351254721Semaste                const char *close_paren_pos = strchr (open_paren_pos, ')');
352254721Semaste                if (close_paren_pos)
353254721Semaste                    m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
354254721Semaste            }
355254721Semaste        }
356254721Semaste    }
357254721Semaste    return m_category;
358254721Semaste}
359254721Semaste
360254721SemasteConstString
361254721SemasteObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
362254721Semaste{
363254721Semaste    if (IsValid(false))
364254721Semaste    {
365254721Semaste        if (HasCategory())
366254721Semaste        {
367254721Semaste            StreamString strm;
368254721Semaste            if (m_type == eTypeClassMethod)
369254721Semaste                strm.PutChar('+');
370254721Semaste            else if (m_type == eTypeInstanceMethod)
371254721Semaste                strm.PutChar('-');
372254721Semaste            strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
373254721Semaste            return ConstString(strm.GetString().c_str());
374254721Semaste        }
375254721Semaste
376254721Semaste        if (!empty_if_no_category)
377254721Semaste        {
378254721Semaste            // Just return the full name since it doesn't have a category
379254721Semaste            return GetFullName();
380254721Semaste        }
381254721Semaste    }
382254721Semaste    return ConstString();
383254721Semaste}
384254721Semaste
385254721Semastesize_t
386254721SemasteObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
387254721Semaste{
388254721Semaste    if (!append)
389254721Semaste        names.clear();
390254721Semaste    if (IsValid(false))
391254721Semaste    {
392254721Semaste        StreamString strm;
393254721Semaste        const bool is_class_method = m_type == eTypeClassMethod;
394254721Semaste        const bool is_instance_method = m_type == eTypeInstanceMethod;
395254721Semaste        const ConstString &category = GetCategory();
396254721Semaste        if (is_class_method || is_instance_method)
397254721Semaste        {
398254721Semaste            names.push_back (m_full);
399254721Semaste            if (category)
400254721Semaste            {
401254721Semaste                strm.Printf("%c[%s %s]",
402254721Semaste                            is_class_method ? '+' : '-',
403254721Semaste                            GetClassName().GetCString(),
404254721Semaste                            GetSelector().GetCString());
405254721Semaste                names.push_back(ConstString(strm.GetString().c_str()));
406254721Semaste            }
407254721Semaste        }
408254721Semaste        else
409254721Semaste        {
410254721Semaste            const ConstString &class_name = GetClassName();
411254721Semaste            const ConstString &selector = GetSelector();
412254721Semaste            strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
413254721Semaste            names.push_back(ConstString(strm.GetString().c_str()));
414254721Semaste            strm.Clear();
415254721Semaste            strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
416254721Semaste            names.push_back(ConstString(strm.GetString().c_str()));
417254721Semaste            strm.Clear();
418254721Semaste            if (category)
419254721Semaste            {
420254721Semaste                strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
421254721Semaste                names.push_back(ConstString(strm.GetString().c_str()));
422254721Semaste                strm.Clear();
423254721Semaste                strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
424254721Semaste                names.push_back(ConstString(strm.GetString().c_str()));
425254721Semaste            }
426254721Semaste        }
427254721Semaste    }
428254721Semaste    return names.size();
429254721Semaste}
430254721Semaste
431254721Semaste
432254721Semastebool
433254721SemasteObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
434254721Semaste                                                      uint32_t ptr_size,
435254721Semaste                                                      bool allow_NULLs,
436254721Semaste                                                      bool allow_tagged,
437254721Semaste                                                      bool check_version_specific) const
438254721Semaste{
439254721Semaste    if (!value)
440254721Semaste        return allow_NULLs;
441254721Semaste    if ( (value % 2) == 1  && allow_tagged)
442254721Semaste        return true;
443254721Semaste    if ((value % ptr_size) == 0)
444254721Semaste        return (check_version_specific ? CheckPointer(value,ptr_size) : true);
445254721Semaste    else
446254721Semaste        return false;
447254721Semaste}
448254721Semaste
449254721SemasteObjCLanguageRuntime::ObjCISA
450254721SemasteObjCLanguageRuntime::GetISA(const ConstString &name)
451254721Semaste{
452254721Semaste    ISAToDescriptorIterator pos = GetDescriptorIterator (name);
453254721Semaste    if (pos != m_isa_to_descriptor.end())
454254721Semaste        return pos->first;
455254721Semaste    return 0;
456254721Semaste}
457254721Semaste
458254721SemasteObjCLanguageRuntime::ISAToDescriptorIterator
459254721SemasteObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name)
460254721Semaste{
461254721Semaste    ISAToDescriptorIterator end = m_isa_to_descriptor.end();
462254721Semaste
463254721Semaste    if (name)
464254721Semaste    {
465254721Semaste        UpdateISAToDescriptorMap();
466254721Semaste        if (m_hash_to_isa_map.empty())
467254721Semaste        {
468254721Semaste            // No name hashes were provided, we need to just linearly power through the
469254721Semaste            // names and find a match
470254721Semaste            for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos)
471254721Semaste            {
472254721Semaste                if (pos->second->GetClassName() == name)
473254721Semaste                    return pos;
474254721Semaste            }
475254721Semaste        }
476254721Semaste        else
477254721Semaste        {
478254721Semaste            // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor
479254721Semaste            const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString());
480254721Semaste            std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash);
481254721Semaste            for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos)
482254721Semaste            {
483254721Semaste                ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second);
484254721Semaste                if (pos != m_isa_to_descriptor.end())
485254721Semaste                {
486254721Semaste                    if (pos->second->GetClassName() == name)
487254721Semaste                        return pos;
488254721Semaste                }
489254721Semaste            }
490254721Semaste        }
491254721Semaste    }
492254721Semaste    return end;
493254721Semaste}
494254721Semaste
495254721Semaste
496254721SemasteObjCLanguageRuntime::ObjCISA
497254721SemasteObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
498254721Semaste{
499254721Semaste    ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
500254721Semaste    if (objc_class_sp)
501254721Semaste    {
502254721Semaste        ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
503254721Semaste        if (objc_super_class_sp)
504254721Semaste            return objc_super_class_sp->GetISA();
505254721Semaste    }
506254721Semaste    return 0;
507254721Semaste}
508254721Semaste
509254721SemasteConstString
510254721SemasteObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
511254721Semaste{
512254721Semaste    ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
513254721Semaste    if (objc_class_sp)
514254721Semaste        return objc_class_sp->GetClassName();
515254721Semaste    return ConstString();
516254721Semaste}
517254721Semaste
518254721SemasteObjCLanguageRuntime::ClassDescriptorSP
519254721SemasteObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
520254721Semaste{
521254721Semaste    ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
522254721Semaste    if (pos != m_isa_to_descriptor.end())
523254721Semaste        return pos->second;
524254721Semaste    return ClassDescriptorSP();
525254721Semaste
526254721Semaste}
527254721Semaste
528254721SemasteObjCLanguageRuntime::ClassDescriptorSP
529254721SemasteObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
530254721Semaste{
531254721Semaste    ClassDescriptorSP objc_class_sp;
532254721Semaste    // if we get an invalid VO (which might still happen when playing around
533254721Semaste    // with pointers returned by the expression parser, don't consider this
534254721Semaste    // a valid ObjC object)
535254721Semaste    if (valobj.GetClangType().IsValid())
536254721Semaste    {
537254721Semaste        addr_t isa_pointer = valobj.GetPointerValue();
538254721Semaste        if (isa_pointer != LLDB_INVALID_ADDRESS)
539254721Semaste        {
540254721Semaste            ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
541254721Semaste
542254721Semaste            Process *process = exe_ctx.GetProcessPtr();
543254721Semaste            if (process)
544254721Semaste            {
545254721Semaste                Error error;
546254721Semaste                ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
547254721Semaste                if (isa != LLDB_INVALID_ADDRESS)
548254721Semaste                    objc_class_sp = GetClassDescriptorFromISA (isa);
549254721Semaste            }
550254721Semaste        }
551254721Semaste    }
552254721Semaste    return objc_class_sp;
553254721Semaste}
554254721Semaste
555254721SemasteObjCLanguageRuntime::ClassDescriptorSP
556254721SemasteObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
557254721Semaste{
558254721Semaste    ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
559254721Semaste    if (objc_class_sp)
560254721Semaste    {
561254721Semaste        if (!objc_class_sp->IsKVO())
562254721Semaste            return objc_class_sp;
563254721Semaste
564254721Semaste        ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
565254721Semaste        if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
566254721Semaste            return non_kvo_objc_class_sp;
567254721Semaste    }
568254721Semaste    return ClassDescriptorSP();
569254721Semaste}
570254721Semaste
571254721Semaste
572254721SemasteObjCLanguageRuntime::ClassDescriptorSP
573254721SemasteObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
574254721Semaste{
575254721Semaste    if (isa)
576254721Semaste    {
577254721Semaste        UpdateISAToDescriptorMap();
578254721Semaste        ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);
579254721Semaste        if (pos != m_isa_to_descriptor.end())
580254721Semaste            return pos->second;
581254721Semaste    }
582254721Semaste    return ClassDescriptorSP();
583254721Semaste}
584254721Semaste
585254721SemasteObjCLanguageRuntime::ClassDescriptorSP
586254721SemasteObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
587254721Semaste{
588254721Semaste    if (isa)
589254721Semaste    {
590254721Semaste        ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
591254721Semaste        if (objc_class_sp && objc_class_sp->IsValid())
592254721Semaste        {
593254721Semaste            if (!objc_class_sp->IsKVO())
594254721Semaste                return objc_class_sp;
595254721Semaste
596254721Semaste            ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
597254721Semaste            if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
598254721Semaste                return non_kvo_objc_class_sp;
599254721Semaste        }
600254721Semaste    }
601254721Semaste    return ClassDescriptorSP();
602254721Semaste}
603254721Semaste
604254721Semaste
605254721Semaste
606