LLDB  mainline
ObjCLanguageRuntime.cpp
Go to the documentation of this file.
1 //===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
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 "lldb/Core/MappedHash.h"
11 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Symbol/Type.h"
18 #include "lldb/Symbol/TypeList.h"
19 #include "lldb/Symbol/Variable.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 // Destructor
32 ObjCLanguageRuntime::~ObjCLanguageRuntime() {}
33 
34 ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
35  : LanguageRuntime(process), m_impl_cache(),
36  m_has_new_literals_and_indexing(eLazyBoolCalculate),
37  m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
38  m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
39  m_negative_complete_class_cache() {}
40 
42  static ConstString g_self = ConstString("self");
43  static ConstString g_cmd = ConstString("_cmd");
44  return name == g_self || name == g_cmd;
45 }
46 
48  // All runtime support values have to be marked as artificial by the
49  // compiler. But not all artificial variables should be hidden from
50  // the user.
51  if (!valobj.GetVariable())
52  return false;
53  if (!valobj.GetVariable()->IsArtificial())
54  return false;
55 
56  // Whitelist "self" and "_cmd".
57  return !IsWhitelistedRuntimeValue(valobj.GetName());
58 }
59 
61  const ClassDescriptorSP &descriptor_sp,
62  const char *class_name) {
63  if (isa != 0) {
64  m_isa_to_descriptor[isa] = descriptor_sp;
65  // class_name is assumed to be valid
66  m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
67  return true;
68  }
69  return false;
70 }
71 
73  lldb::addr_t selector,
74  lldb::addr_t impl_addr) {
76  if (log) {
77  log->Printf("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64
78  " implementation 0x%" PRIx64 ".",
79  class_addr, selector, impl_addr);
80  }
81  m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>(
82  ClassAndSel(class_addr, selector), impl_addr));
83 }
84 
86  lldb::addr_t selector) {
87  MsgImplMap::iterator pos, end = m_impl_cache.end();
88  pos = m_impl_cache.find(ClassAndSel(class_addr, selector));
89  if (pos != end)
90  return (*pos).second;
91  return LLDB_INVALID_ADDRESS;
92 }
93 
94 lldb::TypeSP
96  CompleteClassMap::iterator complete_class_iter =
97  m_complete_class_cache.find(name);
98 
99  if (complete_class_iter != m_complete_class_cache.end()) {
100  // Check the weak pointer to make sure the type hasn't been unloaded
101  TypeSP complete_type_sp(complete_class_iter->second.lock());
102 
103  if (complete_type_sp)
104  return complete_type_sp;
105  else
106  m_complete_class_cache.erase(name);
107  }
108 
109  if (m_negative_complete_class_cache.count(name) > 0)
110  return TypeSP();
111 
112  const ModuleList &modules = m_process->GetTarget().GetImages();
113 
114  SymbolContextList sc_list;
115  const size_t matching_symbols =
116  modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
117 
118  if (matching_symbols) {
119  SymbolContext sc;
120 
121  sc_list.GetContextAtIndex(0, sc);
122 
123  ModuleSP module_sp(sc.module_sp);
124 
125  if (!module_sp)
126  return TypeSP();
127 
128  const bool exact_match = true;
129  const uint32_t max_matches = UINT32_MAX;
130  TypeList types;
131 
132  llvm::DenseSet<SymbolFile *> searched_symbol_files;
133  const uint32_t num_types = module_sp->FindTypes(
134  name, exact_match, max_matches, searched_symbol_files, types);
135 
136  if (num_types) {
137  uint32_t i;
138  for (i = 0; i < num_types; ++i) {
139  TypeSP type_sp(types.GetTypeAtIndex(i));
140 
142  type_sp->GetForwardCompilerType())) {
143  if (type_sp->IsCompleteObjCClass()) {
144  m_complete_class_cache[name] = type_sp;
145  return type_sp;
146  }
147  }
148  }
149  }
150  }
151  m_negative_complete_class_cache.insert(name);
152  return TypeSP();
153 }
154 
156  const char *ivar_name) {
158 }
159 
161  lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
162  bool check_version_specific) const {
163  if (!value)
164  return allow_NULLs;
165  if ((value % 2) == 1 && allow_tagged)
166  return true;
167  if ((value % ptr_size) == 0)
168  return (check_version_specific ? CheckPointer(value, ptr_size) : true);
169  else
170  return false;
171 }
172 
175  ISAToDescriptorIterator pos = GetDescriptorIterator(name);
176  if (pos != m_isa_to_descriptor.end())
177  return pos->first;
178  return 0;
179 }
180 
181 ObjCLanguageRuntime::ISAToDescriptorIterator
183  ISAToDescriptorIterator end = m_isa_to_descriptor.end();
184 
185  if (name) {
187  if (m_hash_to_isa_map.empty()) {
188  // No name hashes were provided, we need to just linearly power through
189  // the names and find a match
190  for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
191  pos != end; ++pos) {
192  if (pos->second->GetClassName() == name)
193  return pos;
194  }
195  } else {
196  // Name hashes were provided, so use them to efficiently lookup name to
197  // isa/descriptor
198  const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
199  std::pair<HashToISAIterator, HashToISAIterator> range =
200  m_hash_to_isa_map.equal_range(name_hash);
201  for (HashToISAIterator range_pos = range.first; range_pos != range.second;
202  ++range_pos) {
203  ISAToDescriptorIterator pos =
204  m_isa_to_descriptor.find(range_pos->second);
205  if (pos != m_isa_to_descriptor.end()) {
206  if (pos->second->GetClassName() == name)
207  return pos;
208  }
209  }
210  }
211  }
212  return end;
213 }
214 
215 std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
216  ObjCLanguageRuntime::ISAToDescriptorIterator>
218  if (update_if_needed)
220 
221  return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
222  ObjCLanguageRuntime::ISAToDescriptorIterator>(
223  m_isa_to_descriptor.begin(), m_isa_to_descriptor.end());
224 }
225 
228  ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
229  if (objc_class_sp) {
230  ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
231  if (objc_super_class_sp)
232  return objc_super_class_sp->GetISA();
233  }
234  return 0;
235 }
236 
239  ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa));
240  if (objc_class_sp)
241  return objc_class_sp->GetClassName();
242  return ConstString();
243 }
244 
247  ConstString class_name) {
248  ISAToDescriptorIterator pos = GetDescriptorIterator(class_name);
249  if (pos != m_isa_to_descriptor.end())
250  return pos->second;
251  return ClassDescriptorSP();
252 }
253 
256  ClassDescriptorSP objc_class_sp;
257  // if we get an invalid VO (which might still happen when playing around with
258  // pointers returned by the expression parser, don't consider this a valid
259  // ObjC object)
260  if (valobj.GetCompilerType().IsValid()) {
261  addr_t isa_pointer = valobj.GetPointerValue();
262  if (isa_pointer != LLDB_INVALID_ADDRESS) {
263  ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
264 
265  Process *process = exe_ctx.GetProcessPtr();
266  if (process) {
267  Status error;
268  ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
269  if (isa != LLDB_INVALID_ADDRESS)
270  objc_class_sp = GetClassDescriptorFromISA(isa);
271  }
272  }
273  }
274  return objc_class_sp;
275 }
276 
280  GetClassDescriptor(valobj));
281  if (objc_class_sp) {
282  if (!objc_class_sp->IsKVO())
283  return objc_class_sp;
284 
285  ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
286  if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
287  return non_kvo_objc_class_sp;
288  }
289  return ClassDescriptorSP();
290 }
291 
294  if (isa) {
296  ObjCLanguageRuntime::ISAToDescriptorIterator pos =
297  m_isa_to_descriptor.find(isa);
298  if (pos != m_isa_to_descriptor.end())
299  return pos->second;
300  }
301  return ClassDescriptorSP();
302 }
303 
306  if (isa) {
307  ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
308  if (objc_class_sp && objc_class_sp->IsValid()) {
309  if (!objc_class_sp->IsKVO())
310  return objc_class_sp;
311 
312  ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
313  if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
314  return non_kvo_objc_class_sp;
315  }
316  }
317  return ClassDescriptorSP();
318 }
319 
322  bool for_expression) {
323  if (m_scratch_ast_ctx_up)
324  return RealizeType(*m_scratch_ast_ctx_up, name, for_expression);
325  return CompilerType();
326 }
327 
329  ClangASTContext &ast_ctx, const char *name, bool for_expression) {
330  clang::ASTContext *clang_ast = ast_ctx.getASTContext();
331  if (!clang_ast)
332  return CompilerType();
333  return RealizeType(*clang_ast, name, for_expression);
334 }
335 
337 
339  return nullptr;
340 }
341 
343  uint64_t &size) {
344  void *opaque_ptr = compiler_type.GetOpaqueQualType();
345  size = m_type_size_cache.Lookup(opaque_ptr);
346  // an ObjC object will at least have an ISA, so 0 is definitely not OK
347  if (size > 0)
348  return true;
349 
350  ClassDescriptorSP class_descriptor_sp =
352  if (!class_descriptor_sp)
353  return false;
354 
355  int32_t max_offset = INT32_MIN;
356  uint64_t sizeof_max = 0;
357  bool found = false;
358 
359  for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
360  const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
361  int32_t cur_offset = ivar.m_offset;
362  if (cur_offset > max_offset) {
363  max_offset = cur_offset;
364  sizeof_max = ivar.m_size;
365  found = true;
366  }
367  }
368 
369  size = 8 * (max_offset + sizeof_max);
370  if (found)
371  m_type_size_cache.Insert(opaque_ptr, size);
372 
373  return found;
374 }
375 
376 // Exception breakpoint Precondition class for ObjC:
378  const char *class_name) {
379  m_class_names.insert(class_name);
380 }
381 
383 
385  StoppointCallbackContext &context) {
386  return true;
387 }
388 
390  Stream &stream, lldb::DescriptionLevel level) {}
391 
393  Args &args) {
394  Status error;
395  if (args.GetArgumentCount() > 0)
396  error.SetErrorString(
397  "The ObjC Exception breakpoint doesn't support extra options.");
398  return error;
399 }
bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
A command line argument class.
Definition: Args.h:32
CompilerType GetCompilerType()
lldb::TypeSP GetTypeAtIndex(uint32_t idx)
Definition: TypeList.cpp:66
Defines a list of symbol context objects.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa)
virtual EncodingToTypeSP GetEncodingToType()
static bool IsWhitelistedRuntimeValue(ConstString name)
Check whether the name is "self" or "_cmd" and should show up in "frame variable".
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
clang::ASTContext * getASTContext()
void Insert(_KeyType k, _ValueType v)
ConstString GetName() const
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
lldb::TypeSP LookupInCompleteClassCache(ConstString &name)
"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)
static bool IsObjCObjectOrInterfaceType(const CompilerType &type)
lldb::addr_t GetPointerValue(AddressType *address_type=nullptr)
virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, const char *ivar_name)
lldb::opaque_compiler_type_t GetOpaqueQualType() const
Definition: CompilerType.h:165
#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
bool IsPointerValid(lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs=false, bool allow_tagged=false, bool check_version_specific=false) const
virtual lldb::VariableSP GetVariable()
Definition: ValueObject.h:801
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
A collection class for Module objects.
Definition: ModuleList.h:91
virtual ObjCISA GetParentClass(ObjCISA isa)
size_t FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list, bool append=false) const
Definition: ModuleList.cpp:457
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:233
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:353
#define LLDB_INVALID_IVAR_OFFSET
Definition: lldb-defines.h:87
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:899
void AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr)
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1194
bool IsRuntimeSupportValue(ValueObject &valobj) override
Identify whether a value is a language implementation detaul that should be hidden from the user inte...
virtual CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name, bool for_expression)
uint64_t addr_t
Definition: lldb-types.h:83
bool EvaluatePrecondition(StoppointCallbackContext &context) override
A uniqued constant string class.
Definition: ConstString.h:38
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
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 ConstString GetActualTypeName(ObjCISA isa)
virtual void UpdateISAToDescriptorMapIfNeeded()=0
#define LIBLLDB_LOG_STEP
Definition: Logging.h:21
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
std::shared_ptr< EncodingToType > EncodingToTypeSP
virtual ClassDescriptorSP GetClassDescriptorFromClassName(ConstString class_name)
std::pair< ISAToDescriptorIterator, ISAToDescriptorIterator > GetDescriptorIteratorPair(bool update_if_needed=true)
An error handling class.
Definition: Status.h:44