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