LLDB  mainline
ObjCLanguageRuntime.cpp
Go to the documentation of this file.
1 //===-- ObjCLanguageRuntime.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "clang/AST/Type.h"
9 
10 #include "ObjCLanguageRuntime.h"
11 
13 #include "lldb/Core/MappedHash.h"
14 #include "lldb/Core/Module.h"
16 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Symbol/SymbolFile.h"
19 #include "lldb/Symbol/Type.h"
20 #include "lldb/Symbol/TypeList.h"
21 #include "lldb/Symbol/Variable.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Utility/Log.h"
24 #include "lldb/Utility/Timer.h"
25 
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/Support/DJB.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
33 
34 // Destructor
35 ObjCLanguageRuntime::~ObjCLanguageRuntime() {}
36 
37 ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
38  : LanguageRuntime(process), m_impl_cache(),
39  m_has_new_literals_and_indexing(eLazyBoolCalculate),
40  m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
41  m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
42  m_negative_complete_class_cache() {}
43 
45  static ConstString g_self = ConstString("self");
46  static ConstString g_cmd = ConstString("_cmd");
47  return name == g_self || name == g_cmd;
48 }
49 
51  const ClassDescriptorSP &descriptor_sp,
52  const char *class_name) {
53  if (isa != 0) {
54  m_isa_to_descriptor[isa] = descriptor_sp;
55  // class_name is assumed to be valid
56  m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
57  return true;
58  }
59  return false;
60 }
61 
63  lldb::addr_t selector,
64  lldb::addr_t impl_addr) {
66  if (log) {
67  LLDB_LOGF(log,
68  "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64
69  " implementation 0x%" PRIx64 ".",
70  class_addr, selector, impl_addr);
71  }
72  m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>(
73  ClassAndSel(class_addr, selector), impl_addr));
74 }
75 
77  lldb::addr_t selector) {
78  MsgImplMap::iterator pos, end = m_impl_cache.end();
79  pos = m_impl_cache.find(ClassAndSel(class_addr, selector));
80  if (pos != end)
81  return (*pos).second;
82  return LLDB_INVALID_ADDRESS;
83 }
84 
85 lldb::TypeSP
87  CompleteClassMap::iterator complete_class_iter =
88  m_complete_class_cache.find(name);
89 
90  if (complete_class_iter != m_complete_class_cache.end()) {
91  // Check the weak pointer to make sure the type hasn't been unloaded
92  TypeSP complete_type_sp(complete_class_iter->second.lock());
93 
94  if (complete_type_sp)
95  return complete_type_sp;
96  else
97  m_complete_class_cache.erase(name);
98  }
99 
100  if (m_negative_complete_class_cache.count(name) > 0)
101  return TypeSP();
102 
103  const ModuleList &modules = m_process->GetTarget().GetImages();
104 
105  SymbolContextList sc_list;
106  modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
107  const size_t matching_symbols = sc_list.GetSize();
108 
109  if (matching_symbols) {
110  SymbolContext sc;
111 
112  sc_list.GetContextAtIndex(0, sc);
113 
114  ModuleSP module_sp(sc.module_sp);
115 
116  if (!module_sp)
117  return TypeSP();
118 
119  const bool exact_match = true;
120  const uint32_t max_matches = UINT32_MAX;
121  TypeList types;
122 
123  llvm::DenseSet<SymbolFile *> searched_symbol_files;
124  module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files,
125  types);
126 
127  for (uint32_t i = 0; i < types.GetSize(); ++i) {
128  TypeSP type_sp(types.GetTypeAtIndex(i));
129 
131  type_sp->GetForwardCompilerType())) {
132  if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) {
133  m_complete_class_cache[name] = type_sp;
134  return type_sp;
135  }
136  }
137  }
138  }
139  m_negative_complete_class_cache.insert(name);
140  return TypeSP();
141 }
142 
144  const char *ivar_name) {
146 }
147 
149  lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
150  bool check_version_specific) const {
151  if (!value)
152  return allow_NULLs;
153  if ((value % 2) == 1 && allow_tagged)
154  return true;
155  if ((value % ptr_size) == 0)
156  return (check_version_specific ? CheckPointer(value, ptr_size) : true);
157  else
158  return false;
159 }
160 
164  if (pos != m_isa_to_descriptor.end())
165  return pos->first;
166  return 0;
167 }
168 
172 
173  if (name) {
175  if (m_hash_to_isa_map.empty()) {
176  // No name hashes were provided, we need to just linearly power through
177  // the names and find a match
178  for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
179  pos != end; ++pos) {
180  if (pos->second->GetClassName() == name)
181  return pos;
182  }
183  } else {
184  // Name hashes were provided, so use them to efficiently lookup name to
185  // isa/descriptor
186  const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
187  std::pair<HashToISAIterator, HashToISAIterator> range =
188  m_hash_to_isa_map.equal_range(name_hash);
189  for (HashToISAIterator range_pos = range.first; range_pos != range.second;
190  ++range_pos) {
192  m_isa_to_descriptor.find(range_pos->second);
193  if (pos != m_isa_to_descriptor.end()) {
194  if (pos->second->GetClassName() == name)
195  return pos;
196  }
197  }
198  }
199  }
200  return end;
201 }
202 
206  if (update_if_needed)
208 
210  ObjCLanguageRuntime::ISAToDescriptorIterator>(
212 }
213 
216  ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
217  if (objc_class_sp) {
218  ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
219  if (objc_super_class_sp)
220  return objc_super_class_sp->GetISA();
221  }
222  return 0;
223 }
224 
227  ConstString class_name) {
229  if (pos != m_isa_to_descriptor.end())
230  return pos->second;
231  return ClassDescriptorSP();
232 }
233 
236  ClassDescriptorSP objc_class_sp;
237  // if we get an invalid VO (which might still happen when playing around with
238  // pointers returned by the expression parser, don't consider this a valid
239  // ObjC object)
240  if (valobj.GetCompilerType().IsValid()) {
241  addr_t isa_pointer = valobj.GetPointerValue();
242  if (isa_pointer != LLDB_INVALID_ADDRESS) {
243  ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
244 
245  Process *process = exe_ctx.GetProcessPtr();
246  if (process) {
247  Status error;
248  ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
249  if (isa != LLDB_INVALID_ADDRESS)
250  objc_class_sp = GetClassDescriptorFromISA(isa);
251  }
252  }
253  }
254  return objc_class_sp;
255 }
256 
260  GetClassDescriptor(valobj));
261  if (objc_class_sp) {
262  if (!objc_class_sp->IsKVO())
263  return objc_class_sp;
264 
265  ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
266  if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
267  return non_kvo_objc_class_sp;
268  }
269  return ClassDescriptorSP();
270 }
271 
274  if (isa) {
277  m_isa_to_descriptor.find(isa);
278  if (pos != m_isa_to_descriptor.end())
279  return pos->second;
280  }
281  return ClassDescriptorSP();
282 }
283 
286  if (isa) {
287  ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
288  if (objc_class_sp && objc_class_sp->IsValid()) {
289  if (!objc_class_sp->IsKVO())
290  return objc_class_sp;
291 
292  ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
293  if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
294  return non_kvo_objc_class_sp;
295  }
296  }
297  return ClassDescriptorSP();
298 }
299 
302  bool for_expression) {
303  if (m_scratch_ast_ctx_up)
304  return RealizeType(*m_scratch_ast_ctx_up, name, for_expression);
305  return CompilerType();
306 }
307 
309 
311  return nullptr;
312 }
313 
315  uint64_t &size) {
316  void *opaque_ptr = compiler_type.GetOpaqueQualType();
317  size = m_type_size_cache.Lookup(opaque_ptr);
318  // an ObjC object will at least have an ISA, so 0 is definitely not OK
319  if (size > 0)
320  return true;
321 
322  ClassDescriptorSP class_descriptor_sp =
324  if (!class_descriptor_sp)
325  return false;
326 
327  int32_t max_offset = INT32_MIN;
328  uint64_t sizeof_max = 0;
329  bool found = false;
330 
331  for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
332  const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
333  int32_t cur_offset = ivar.m_offset;
334  if (cur_offset > max_offset) {
335  max_offset = cur_offset;
336  sizeof_max = ivar.m_size;
337  found = true;
338  }
339  }
340 
341  size = 8 * (max_offset + sizeof_max);
342  if (found)
343  m_type_size_cache.Insert(opaque_ptr, size);
344 
345  return found;
346 }
347 
348 lldb::BreakpointPreconditionSP
350  bool throw_bp) {
351  if (language != eLanguageTypeObjC)
352  return lldb::BreakpointPreconditionSP();
353  if (!throw_bp)
354  return lldb::BreakpointPreconditionSP();
355  BreakpointPreconditionSP precondition_sp(
357  return precondition_sp;
358 }
359 
360 // Exception breakpoint Precondition class for ObjC:
362  const char *class_name) {
363  m_class_names.insert(class_name);
364 }
365 
367 
369  StoppointCallbackContext &context) {
370  return true;
371 }
372 
374  Stream &stream, lldb::DescriptionLevel level) {}
375 
377  Args &args) {
378  Status error;
379  if (args.GetArgumentCount() > 0)
380  error.SetErrorString(
381  "The ObjC Exception breakpoint doesn't support extra options.");
382  return error;
383 }
384 
385 llvm::Optional<CompilerType>
387  CompilerType class_type;
388  bool is_pointer_type = false;
389 
390  if (TypeSystemClang::IsObjCObjectPointerType(base_type, &class_type))
391  is_pointer_type = true;
393  class_type = base_type;
394  else
395  return llvm::None;
396 
397  if (!class_type)
398  return llvm::None;
399 
400  ConstString class_name(class_type.GetTypeName());
401  if (!class_name)
402  return llvm::None;
403 
404  TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name);
405  if (!complete_objc_class_type_sp)
406  return llvm::None;
407 
408  CompilerType complete_class(
409  complete_objc_class_type_sp->GetFullCompilerType());
410  if (complete_class.GetCompleteType()) {
411  if (is_pointer_type)
412  return complete_class.GetPointerType();
413  else
414  return complete_class;
415  }
416 
417  return llvm::None;
418 }
bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
A command line argument class.
Definition: Args.h:33
CompilerType GetCompilerType()
lldb::TypeSP GetTypeAtIndex(uint32_t idx)
Definition: TypeList.cpp:66
Defines a list of symbol context objects.
A class that represents a running process on the host machine.
static lldb::BreakpointPreconditionSP GetBreakpointExceptionPrecondition(lldb::LanguageType language, bool throw_bp)
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa)
virtual EncodingToTypeSP GetEncodingToType()
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
void Insert(_KeyType k, _ValueType v)
ISAToDescriptorMap::iterator ISAToDescriptorIterator
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
lldb::TypeSP LookupInCompleteClassCache(ConstString &name)
static bool IsObjCObjectPointerType(const CompilerType &type, CompilerType *target_type=nullptr)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
bool GetTypeBitSize(const CompilerType &compiler_type, uint64_t &size) override
virtual ObjCISA GetISA(ConstString name)
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
lldb::addr_t GetPointerValue(AddressType *address_type=nullptr)
uint32_t GetSize() const
Definition: TypeList.cpp:60
uint32_t GetSize() const
Get accessor for a symbol context list size.
virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, const char *ivar_name)
lldb::opaque_compiler_type_t GetOpaqueQualType() const
Definition: CompilerType.h:168
#define UINT32_MAX
Definition: lldb-defines.h:31
ClassDescriptorSP GetNonKVOClassDescriptor(ValueObject &in_value)
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
LanguageType
Programming language type.
bool IsPointerValid(lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs=false, bool allow_tagged=false, bool check_version_specific=false) const
static llvm::raw_ostream & error(Stream &strm)
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
A collection class for Module objects.
Definition: ModuleList.h:71
virtual ObjCISA GetParentClass(ObjCISA isa)
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:242
HashToISAMap::iterator HashToISAIterator
A plug-in interface definition class for debugging a process.
Definition: Process.h:362
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:232
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:331
static char ID
virtual CompilerType RealizeType(TypeSystemClang &ast_ctx, const char *name, bool for_expression)=0
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
#define LLDB_INVALID_IVAR_OFFSET
Definition: lldb-defines.h:87
TypeList FindTypes(ConstString name)
bool GetContextAtIndex(size_t idx, SymbolContext &sc) const
Get accessor for a symbol context at index idx.
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:900
void AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr)
#define LLDB_LOGF(log,...)
Definition: Log.h:249
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1210
uint64_t addr_t
Definition: lldb-types.h:83
bool EvaluatePrecondition(StoppointCallbackContext &context) override
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
Definition: ModuleList.cpp:452
A uniqued constant string class.
Definition: ConstString.h:40
void GetDescription(Stream &stream, lldb::DescriptionLevel level) override
lldb::ModuleSP module_sp
The Module for a given query.
lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, lldb::addr_t sel)
Definition: SBAddress.h:15
Represents a generic type in a programming language.
Definition: CompilerType.h:33
bool IsAllowedRuntimeValue(ConstString name) override
Check whether the name is "self" or "_cmd" and should show up in "frame variable".
ISAToDescriptorIterator GetDescriptorIterator(ConstString name)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
ConstString GetTypeName() const
virtual void UpdateISAToDescriptorMapIfNeeded()=0
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
std::shared_ptr< EncodingToType > EncodingToTypeSP
llvm::Optional< CompilerType > GetRuntimeType(CompilerType base_type) override
virtual ClassDescriptorSP GetClassDescriptorFromClassName(ConstString class_name)
static bool IsObjCObjectOrInterfaceType(const CompilerType &type)
std::pair< ISAToDescriptorIterator, ISAToDescriptorIterator > GetDescriptorIteratorPair(bool update_if_needed=true)
An error handling class.
Definition: Status.h:44
The implementation of lldb::Type&#39;s m_payload field for TypeSystemClang.