]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
Merge ^/head r306412 through r306905.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Target / ObjCLanguageRuntime.cpp
1 //===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "clang/AST/Type.h"
10
11 #include "lldb/Core/Log.h"
12 #include "lldb/Core/MappedHash.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Core/Timer.h"
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Symbol/ClangASTContext.h"
18 #include "lldb/Symbol/SymbolContext.h"
19 #include "lldb/Symbol/SymbolFile.h"
20 #include "lldb/Symbol/Type.h"
21 #include "lldb/Symbol/TypeList.h"
22 #include "lldb/Target/ObjCLanguageRuntime.h"
23 #include "lldb/Target/Target.h"
24
25 #include "llvm/ADT/StringRef.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29
30 //----------------------------------------------------------------------
31 // Destructor
32 //----------------------------------------------------------------------
33 ObjCLanguageRuntime::~ObjCLanguageRuntime()
34 {
35 }
36
37 ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
38     LanguageRuntime (process),
39     m_impl_cache(),
40     m_has_new_literals_and_indexing (eLazyBoolCalculate),
41     m_isa_to_descriptor(),
42     m_hash_to_isa_map(),
43     m_type_size_cache(),
44     m_isa_to_descriptor_stop_id (UINT32_MAX),
45     m_complete_class_cache(),
46     m_negative_complete_class_cache()
47 {
48 }
49
50 bool
51 ObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name)
52 {
53     if (isa != 0)
54     {
55         m_isa_to_descriptor[isa] = descriptor_sp;
56         // class_name is assumed to be valid
57         m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
58         return true;
59     }
60     return false;
61 }
62
63 void
64 ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
65 {
66     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
67     if (log)
68     {
69         log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
70     }
71     m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
72 }
73
74 lldb::addr_t
75 ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
76 {
77     MsgImplMap::iterator pos, end = m_impl_cache.end();
78     pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
79     if (pos != end)
80         return (*pos).second;
81     return LLDB_INVALID_ADDRESS;
82 }
83
84
85 lldb::TypeSP
86 ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
87 {
88     CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
89     
90     if (complete_class_iter != m_complete_class_cache.end())
91     {
92         // Check the weak pointer to make sure the type hasn't been unloaded
93         TypeSP complete_type_sp (complete_class_iter->second.lock());
94         
95         if (complete_type_sp)
96             return complete_type_sp;
97         else
98             m_complete_class_cache.erase(name);
99     }
100     
101     if (m_negative_complete_class_cache.count(name) > 0)
102         return TypeSP();
103     
104     const ModuleList &modules = m_process->GetTarget().GetImages();
105
106     SymbolContextList sc_list;
107     const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
108                                                                         eSymbolTypeObjCClass,
109                                                                         sc_list);
110     
111     if (matching_symbols)
112     {
113         SymbolContext sc;
114         
115         sc_list.GetContextAtIndex(0, sc);
116         
117         ModuleSP module_sp(sc.module_sp);
118         
119         if (!module_sp)
120             return TypeSP();
121         
122         const SymbolContext null_sc;
123         const bool exact_match = true;
124         const uint32_t max_matches = UINT32_MAX;
125         TypeList types;
126
127         llvm::DenseSet<SymbolFile *> searched_symbol_files;
128         const uint32_t num_types = module_sp->FindTypes (null_sc,
129                                                          name,
130                                                          exact_match,
131                                                          max_matches,
132                                                          searched_symbol_files,
133                                                          types);
134         
135         if (num_types)
136         {            
137             uint32_t i;
138             for (i = 0; i < num_types; ++i)
139             {
140                 TypeSP type_sp (types.GetTypeAtIndex(i));
141                 
142                 if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetForwardCompilerType ()))
143                 {
144                     if (type_sp->IsCompleteObjCClass())
145                     {
146                         m_complete_class_cache[name] = type_sp;
147                         return type_sp;
148                     }
149                 }
150             }
151         }
152     }
153     m_negative_complete_class_cache.insert(name);
154     return TypeSP();
155 }
156
157 size_t
158 ObjCLanguageRuntime::GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name)
159 {
160     return LLDB_INVALID_IVAR_OFFSET;
161 }
162
163 bool
164 ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
165                                                       uint32_t ptr_size,
166                                                       bool allow_NULLs,
167                                                       bool allow_tagged,
168                                                       bool check_version_specific) const
169 {
170     if (!value)
171         return allow_NULLs;
172     if ( (value % 2) == 1  && allow_tagged)
173         return true;
174     if ((value % ptr_size) == 0)
175         return (check_version_specific ? CheckPointer(value,ptr_size) : true);
176     else
177         return false;
178 }
179
180 ObjCLanguageRuntime::ObjCISA
181 ObjCLanguageRuntime::GetISA(const ConstString &name)
182 {
183     ISAToDescriptorIterator pos = GetDescriptorIterator (name);
184     if (pos != m_isa_to_descriptor.end())
185         return pos->first;
186     return 0;
187 }
188
189 ObjCLanguageRuntime::ISAToDescriptorIterator
190 ObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name)
191 {
192     ISAToDescriptorIterator end = m_isa_to_descriptor.end();
193
194     if (name)
195     {
196         UpdateISAToDescriptorMap();
197         if (m_hash_to_isa_map.empty())
198         {
199             // No name hashes were provided, we need to just linearly power through the
200             // names and find a match
201             for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos)
202             {
203                 if (pos->second->GetClassName() == name)
204                     return pos;
205             }
206         }
207         else
208         {
209             // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor
210             const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString());
211             std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash);
212             for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos)
213             {
214                 ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second);
215                 if (pos != m_isa_to_descriptor.end())
216                 {
217                     if (pos->second->GetClassName() == name)
218                         return pos;
219                 }
220             }
221         }
222     }
223     return end;
224 }
225
226 std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,ObjCLanguageRuntime::ISAToDescriptorIterator>
227 ObjCLanguageRuntime::GetDescriptorIteratorPair (bool update_if_needed)
228 {
229     if (update_if_needed)
230         UpdateISAToDescriptorMapIfNeeded();
231     
232     return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
233                      ObjCLanguageRuntime::ISAToDescriptorIterator>(
234                         m_isa_to_descriptor.begin(),
235                         m_isa_to_descriptor.end());
236 }
237
238
239 ObjCLanguageRuntime::ObjCISA
240 ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
241 {
242     ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
243     if (objc_class_sp)
244     {
245         ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
246         if (objc_super_class_sp)
247             return objc_super_class_sp->GetISA();
248     }
249     return 0;
250 }
251
252 ConstString
253 ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
254 {
255     ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
256     if (objc_class_sp)
257         return objc_class_sp->GetClassName();
258     return ConstString();
259 }
260
261 ObjCLanguageRuntime::ClassDescriptorSP
262 ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
263 {
264     ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
265     if (pos != m_isa_to_descriptor.end())
266         return pos->second;
267     return ClassDescriptorSP();
268
269 }
270
271 ObjCLanguageRuntime::ClassDescriptorSP
272 ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
273 {
274     ClassDescriptorSP objc_class_sp;
275     // if we get an invalid VO (which might still happen when playing around
276     // with pointers returned by the expression parser, don't consider this
277     // a valid ObjC object)
278     if (valobj.GetCompilerType().IsValid())
279     {
280         addr_t isa_pointer = valobj.GetPointerValue();
281         if (isa_pointer != LLDB_INVALID_ADDRESS)
282         {
283             ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
284             
285             Process *process = exe_ctx.GetProcessPtr();
286             if (process)
287             {
288                 Error error;
289                 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
290                 if (isa != LLDB_INVALID_ADDRESS)
291                     objc_class_sp = GetClassDescriptorFromISA (isa);
292             }
293         }
294     }
295     return objc_class_sp;
296 }
297
298 ObjCLanguageRuntime::ClassDescriptorSP
299 ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
300 {
301     ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
302     if (objc_class_sp)
303     {
304         if (!objc_class_sp->IsKVO())
305             return objc_class_sp;
306         
307         ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
308         if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
309             return non_kvo_objc_class_sp;
310     }
311     return ClassDescriptorSP();
312 }
313
314
315 ObjCLanguageRuntime::ClassDescriptorSP
316 ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
317 {
318     if (isa)
319     {
320         UpdateISAToDescriptorMap();
321         ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);    
322         if (pos != m_isa_to_descriptor.end())
323             return pos->second;
324     }
325     return ClassDescriptorSP();
326 }
327
328 ObjCLanguageRuntime::ClassDescriptorSP
329 ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
330 {
331     if (isa)
332     {
333         ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
334         if (objc_class_sp && objc_class_sp->IsValid())
335         {
336             if (!objc_class_sp->IsKVO())
337                 return objc_class_sp;
338
339             ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
340             if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
341                 return non_kvo_objc_class_sp;
342         }
343     }
344     return ClassDescriptorSP();
345 }
346
347
348 CompilerType
349 ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression)
350 {
351     if (m_scratch_ast_ctx_ap)
352         return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
353     return CompilerType();
354 }
355
356 CompilerType
357 ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression)
358 {
359     clang::ASTContext *clang_ast = ast_ctx.getASTContext();
360     if (!clang_ast)
361         return CompilerType();
362     return RealizeType(*clang_ast, name, for_expression);
363 }
364
365 ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
366
367 ObjCLanguageRuntime::EncodingToTypeSP
368 ObjCLanguageRuntime::GetEncodingToType ()
369 {
370     return nullptr;
371 }
372
373 bool
374 ObjCLanguageRuntime::GetTypeBitSize (const CompilerType& compiler_type,
375                                      uint64_t &size)
376 {
377     void *opaque_ptr = compiler_type.GetOpaqueQualType();
378     size = m_type_size_cache.Lookup(opaque_ptr);
379     // an ObjC object will at least have an ISA, so 0 is definitely not OK
380     if (size > 0)
381         return true;
382     
383     ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(compiler_type.GetTypeName());
384     if (!class_descriptor_sp)
385         return false;
386     
387     int32_t max_offset = INT32_MIN;
388     uint64_t sizeof_max = 0;
389     bool found = false;
390     
391     for (size_t idx = 0;
392          idx < class_descriptor_sp->GetNumIVars();
393          idx++)
394     {
395         const auto& ivar = class_descriptor_sp->GetIVarAtIndex(idx);
396         int32_t cur_offset = ivar.m_offset;
397         if (cur_offset > max_offset)
398         {
399             max_offset = cur_offset;
400             sizeof_max = ivar.m_size;
401             found = true;
402         }
403     }
404     
405     size = 8 * (max_offset + sizeof_max);
406     if (found)
407         m_type_size_cache.Insert(opaque_ptr, size);
408     
409     return found;
410 }
411
412 //------------------------------------------------------------------
413 // Exception breakpoint Precondition class for ObjC:
414 //------------------------------------------------------------------
415 void
416 ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(const char *class_name)
417 {
418     m_class_names.insert(class_name);
419 }
420
421 ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition()
422 {
423 }
424
425 bool
426 ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCallbackContext &context)
427 {
428     return true;
429 }
430
431 void
432 ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(Stream &stream, lldb::DescriptionLevel level)
433 {
434 }
435
436 Error
437 ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(Args &args)
438 {
439     Error error;
440     if (args.GetArgumentCount() > 0)
441         error.SetErrorString("The ObjC Exception breakpoint doesn't support extra options.");
442     return error;
443 }