]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[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 #include "llvm/Support/DJB.h"
27
28 using namespace lldb;
29 using namespace lldb_private;
30
31 //----------------------------------------------------------------------
32 // Destructor
33 //----------------------------------------------------------------------
34 ObjCLanguageRuntime::~ObjCLanguageRuntime() {}
35
36 ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
37     : LanguageRuntime(process), m_impl_cache(),
38       m_has_new_literals_and_indexing(eLazyBoolCalculate),
39       m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
40       m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
41       m_negative_complete_class_cache() {}
42
43 bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
44                                    const ClassDescriptorSP &descriptor_sp,
45                                    const char *class_name) {
46   if (isa != 0) {
47     m_isa_to_descriptor[isa] = descriptor_sp;
48     // class_name is assumed to be valid
49     m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(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 bool exact_match = true;
112     const uint32_t max_matches = UINT32_MAX;
113     TypeList types;
114
115     llvm::DenseSet<SymbolFile *> searched_symbol_files;
116     const uint32_t num_types = module_sp->FindTypes(
117         name, exact_match, max_matches, searched_symbol_files, types);
118
119     if (num_types) {
120       uint32_t i;
121       for (i = 0; i < num_types; ++i) {
122         TypeSP type_sp(types.GetTypeAtIndex(i));
123
124         if (ClangASTContext::IsObjCObjectOrInterfaceType(
125                 type_sp->GetForwardCompilerType())) {
126           if (type_sp->IsCompleteObjCClass()) {
127             m_complete_class_cache[name] = type_sp;
128             return type_sp;
129           }
130         }
131       }
132     }
133   }
134   m_negative_complete_class_cache.insert(name);
135   return TypeSP();
136 }
137
138 size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type,
139                                                  const char *ivar_name) {
140   return LLDB_INVALID_IVAR_OFFSET;
141 }
142
143 bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid(
144     lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
145     bool check_version_specific) const {
146   if (!value)
147     return allow_NULLs;
148   if ((value % 2) == 1 && allow_tagged)
149     return true;
150   if ((value % ptr_size) == 0)
151     return (check_version_specific ? CheckPointer(value, ptr_size) : true);
152   else
153     return false;
154 }
155
156 ObjCLanguageRuntime::ObjCISA
157 ObjCLanguageRuntime::GetISA(const ConstString &name) {
158   ISAToDescriptorIterator pos = GetDescriptorIterator(name);
159   if (pos != m_isa_to_descriptor.end())
160     return pos->first;
161   return 0;
162 }
163
164 ObjCLanguageRuntime::ISAToDescriptorIterator
165 ObjCLanguageRuntime::GetDescriptorIterator(const ConstString &name) {
166   ISAToDescriptorIterator end = m_isa_to_descriptor.end();
167
168   if (name) {
169     UpdateISAToDescriptorMap();
170     if (m_hash_to_isa_map.empty()) {
171       // No name hashes were provided, we need to just linearly power through
172       // the names and find a match
173       for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
174            pos != end; ++pos) {
175         if (pos->second->GetClassName() == name)
176           return pos;
177       }
178     } else {
179       // Name hashes were provided, so use them to efficiently lookup name to
180       // isa/descriptor
181       const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
182       std::pair<HashToISAIterator, HashToISAIterator> range =
183           m_hash_to_isa_map.equal_range(name_hash);
184       for (HashToISAIterator range_pos = range.first; range_pos != range.second;
185            ++range_pos) {
186         ISAToDescriptorIterator pos =
187             m_isa_to_descriptor.find(range_pos->second);
188         if (pos != m_isa_to_descriptor.end()) {
189           if (pos->second->GetClassName() == name)
190             return pos;
191         }
192       }
193     }
194   }
195   return end;
196 }
197
198 std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
199           ObjCLanguageRuntime::ISAToDescriptorIterator>
200 ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) {
201   if (update_if_needed)
202     UpdateISAToDescriptorMapIfNeeded();
203
204   return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
205                    ObjCLanguageRuntime::ISAToDescriptorIterator>(
206       m_isa_to_descriptor.begin(), m_isa_to_descriptor.end());
207 }
208
209 ObjCLanguageRuntime::ObjCISA
210 ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
211   ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
212   if (objc_class_sp) {
213     ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
214     if (objc_super_class_sp)
215       return objc_super_class_sp->GetISA();
216   }
217   return 0;
218 }
219
220 ConstString
221 ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
222   ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa));
223   if (objc_class_sp)
224     return objc_class_sp->GetClassName();
225   return ConstString();
226 }
227
228 ObjCLanguageRuntime::ClassDescriptorSP
229 ObjCLanguageRuntime::GetClassDescriptorFromClassName(
230     const ConstString &class_name) {
231   ISAToDescriptorIterator pos = GetDescriptorIterator(class_name);
232   if (pos != m_isa_to_descriptor.end())
233     return pos->second;
234   return ClassDescriptorSP();
235 }
236
237 ObjCLanguageRuntime::ClassDescriptorSP
238 ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
239   ClassDescriptorSP objc_class_sp;
240   // if we get an invalid VO (which might still happen when playing around with
241   // pointers returned by the expression parser, don't consider this a valid
242   // ObjC object)
243   if (valobj.GetCompilerType().IsValid()) {
244     addr_t isa_pointer = valobj.GetPointerValue();
245     if (isa_pointer != LLDB_INVALID_ADDRESS) {
246       ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
247
248       Process *process = exe_ctx.GetProcessPtr();
249       if (process) {
250         Status error;
251         ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
252         if (isa != LLDB_INVALID_ADDRESS)
253           objc_class_sp = GetClassDescriptorFromISA(isa);
254       }
255     }
256   }
257   return objc_class_sp;
258 }
259
260 ObjCLanguageRuntime::ClassDescriptorSP
261 ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) {
262   ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
263       GetClassDescriptor(valobj));
264   if (objc_class_sp) {
265     if (!objc_class_sp->IsKVO())
266       return objc_class_sp;
267
268     ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
269     if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
270       return non_kvo_objc_class_sp;
271   }
272   return ClassDescriptorSP();
273 }
274
275 ObjCLanguageRuntime::ClassDescriptorSP
276 ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) {
277   if (isa) {
278     UpdateISAToDescriptorMap();
279     ObjCLanguageRuntime::ISAToDescriptorIterator pos =
280         m_isa_to_descriptor.find(isa);
281     if (pos != m_isa_to_descriptor.end())
282       return pos->second;
283   }
284   return ClassDescriptorSP();
285 }
286
287 ObjCLanguageRuntime::ClassDescriptorSP
288 ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) {
289   if (isa) {
290     ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
291     if (objc_class_sp && objc_class_sp->IsValid()) {
292       if (!objc_class_sp->IsKVO())
293         return objc_class_sp;
294
295       ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
296       if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
297         return non_kvo_objc_class_sp;
298     }
299   }
300   return ClassDescriptorSP();
301 }
302
303 CompilerType
304 ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
305                                                  bool for_expression) {
306   if (m_scratch_ast_ctx_ap)
307     return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
308   return CompilerType();
309 }
310
311 CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType(
312     ClangASTContext &ast_ctx, const char *name, bool for_expression) {
313   clang::ASTContext *clang_ast = ast_ctx.getASTContext();
314   if (!clang_ast)
315     return CompilerType();
316   return RealizeType(*clang_ast, name, for_expression);
317 }
318
319 ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
320
321 ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
322   return nullptr;
323 }
324
325 bool ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type,
326                                          uint64_t &size) {
327   void *opaque_ptr = compiler_type.GetOpaqueQualType();
328   size = m_type_size_cache.Lookup(opaque_ptr);
329   // an ObjC object will at least have an ISA, so 0 is definitely not OK
330   if (size > 0)
331     return true;
332
333   ClassDescriptorSP class_descriptor_sp =
334       GetClassDescriptorFromClassName(compiler_type.GetTypeName());
335   if (!class_descriptor_sp)
336     return false;
337
338   int32_t max_offset = INT32_MIN;
339   uint64_t sizeof_max = 0;
340   bool found = false;
341
342   for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
343     const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
344     int32_t cur_offset = ivar.m_offset;
345     if (cur_offset > max_offset) {
346       max_offset = cur_offset;
347       sizeof_max = ivar.m_size;
348       found = true;
349     }
350   }
351
352   size = 8 * (max_offset + sizeof_max);
353   if (found)
354     m_type_size_cache.Insert(opaque_ptr, size);
355
356   return found;
357 }
358
359 //------------------------------------------------------------------
360 // Exception breakpoint Precondition class for ObjC:
361 //------------------------------------------------------------------
362 void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(
363     const char *class_name) {
364   m_class_names.insert(class_name);
365 }
366
367 ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {}
368
369 bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
370     StoppointCallbackContext &context) {
371   return true;
372 }
373
374 void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(
375     Stream &stream, lldb::DescriptionLevel level) {}
376
377 Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(
378     Args &args) {
379   Status error;
380   if (args.GetArgumentCount() > 0)
381     error.SetErrorString(
382         "The ObjC Exception breakpoint doesn't support extra options.");
383   return error;
384 }