LLDB  mainline
NSException.cpp
Go to the documentation of this file.
1 //===-- NSException.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 
9 #include "clang/AST/DeclCXX.h"
10 
11 #include "Cocoa.h"
12 
13 #include "lldb/Core/ValueObject.h"
19 #include "lldb/Target/Target.h"
21 #include "lldb/Utility/Endian.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/Stream.h"
24 
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 using namespace lldb_private::formatters;
30 
31 static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
32  ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp,
33  ValueObjectSP *reserved_sp) {
34  ProcessSP process_sp(valobj.GetProcessSP());
35  if (!process_sp)
36  return false;
37 
39 
40  CompilerType valobj_type(valobj.GetCompilerType());
41  Flags type_flags(valobj_type.GetTypeInfo());
42  if (type_flags.AllClear(eTypeHasValue)) {
43  if (valobj.IsBaseClass() && valobj.GetParent())
45  } else {
47  }
48 
49  if (ptr == LLDB_INVALID_ADDRESS)
50  return false;
51  size_t ptr_size = process_sp->GetAddressByteSize();
52 
53  Status error;
54  auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error);
55  if (error.Fail() || name == LLDB_INVALID_ADDRESS)
56  return false;
57  auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error);
58  if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
59  return false;
60  auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error);
61  if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS)
62  return false;
63  auto reserved = process_sp->ReadPointerFromMemory(ptr + 4 * ptr_size, error);
64  if (error.Fail() || reserved == LLDB_INVALID_ADDRESS)
65  return false;
66 
67  InferiorSizedWord name_isw(name, *process_sp);
68  InferiorSizedWord reason_isw(reason, *process_sp);
69  InferiorSizedWord userinfo_isw(userinfo, *process_sp);
70  InferiorSizedWord reserved_isw(reserved, *process_sp);
71 
72  CompilerType voidstar = process_sp->GetTarget()
73  .GetScratchClangASTContext()
74  ->GetBasicType(lldb::eBasicTypeVoid)
75  .GetPointerType();
76 
77  if (name_sp)
78  *name_sp = ValueObject::CreateValueObjectFromData(
79  "name", name_isw.GetAsData(process_sp->GetByteOrder()),
80  valobj.GetExecutionContextRef(), voidstar);
81  if (reason_sp)
82  *reason_sp = ValueObject::CreateValueObjectFromData(
83  "reason", reason_isw.GetAsData(process_sp->GetByteOrder()),
84  valobj.GetExecutionContextRef(), voidstar);
85  if (userinfo_sp)
86  *userinfo_sp = ValueObject::CreateValueObjectFromData(
87  "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()),
88  valobj.GetExecutionContextRef(), voidstar);
89  if (reserved_sp)
90  *reserved_sp = ValueObject::CreateValueObjectFromData(
91  "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()),
92  valobj.GetExecutionContextRef(), voidstar);
93 
94  return true;
95 }
96 
98  ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
99  lldb::ValueObjectSP name_sp;
100  lldb::ValueObjectSP reason_sp;
101  if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr, nullptr))
102  return false;
103 
104  if (!name_sp || !reason_sp)
105  return false;
106 
107  StreamString name_str_summary;
108  StreamString reason_str_summary;
109  if (NSStringSummaryProvider(*name_sp, name_str_summary, options) &&
110  NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
111  !name_str_summary.Empty() && !reason_str_summary.Empty()) {
112  stream.Printf("name: %s - reason: %s", name_str_summary.GetData(),
113  reason_str_summary.GetData());
114  return true;
115  } else
116  return false;
117 }
118 
120 public:
121  NSExceptionSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
122  : SyntheticChildrenFrontEnd(*valobj_sp) {}
123 
124  ~NSExceptionSyntheticFrontEnd() override = default;
125 
126  size_t CalculateNumChildren() override {
127  return 4;
128  }
129 
130  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
131  switch (idx) {
132  case 0: return m_name_sp;
133  case 1: return m_reason_sp;
134  case 2: return m_userinfo_sp;
135  case 3: return m_reserved_sp;
136  }
137  return lldb::ValueObjectSP();
138  }
139 
140  bool Update() override {
141  m_name_sp.reset();
142  m_reason_sp.reset();
143  m_userinfo_sp.reset();
144  m_reserved_sp.reset();
145 
146  return ExtractFields(m_backend, &m_name_sp, &m_reason_sp, &m_userinfo_sp,
147  &m_reserved_sp);
148  }
149 
150  bool MightHaveChildren() override { return true; }
151 
152  size_t GetIndexOfChildWithName(ConstString name) override {
153  // NSException has 4 members:
154  // NSString *name;
155  // NSString *reason;
156  // NSDictionary *userInfo;
157  // id reserved;
158  static ConstString g___name("name");
159  static ConstString g___reason("reason");
160  static ConstString g___userInfo("userInfo");
161  static ConstString g___reserved("reserved");
162  if (name == g___name) return 0;
163  if (name == g___reason) return 1;
164  if (name == g___userInfo) return 2;
165  if (name == g___reserved) return 3;
166  return UINT32_MAX;
167  }
168 
169 private:
170  ValueObjectSP m_name_sp;
171  ValueObjectSP m_reason_sp;
172  ValueObjectSP m_userinfo_sp;
173  ValueObjectSP m_reserved_sp;
174 };
175 
178  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
179  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
180  if (!process_sp)
181  return nullptr;
182  ObjCLanguageRuntime *runtime =
183  (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
185  if (!runtime)
186  return nullptr;
187 
189  runtime->GetClassDescriptor(*valobj_sp.get()));
190 
191  if (!descriptor.get() || !descriptor->IsValid())
192  return nullptr;
193 
194  const char *class_name = descriptor->GetClassName().GetCString();
195 
196  if (!class_name || !*class_name)
197  return nullptr;
198 
199  if (!strcmp(class_name, "NSException"))
200  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
201  else if (!strcmp(class_name, "NSCFException"))
202  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
203  else if (!strcmp(class_name, "__NSCFException"))
204  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
205 
206  return nullptr;
207 }
virtual bool IsBaseClass()
Definition: ValueObject.h:413
CompilerType GetCompilerType()
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t GetIndexOfChildWithName(ConstString name) override
NSExceptionSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
const char * GetData() const
Definition: StreamString.h:43
static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp, ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp, ValueObjectSP *reserved_sp)
Definition: NSException.cpp:31
#define UINT32_MAX
Definition: lldb-defines.h:31
virtual ValueObject * GetParent()
Definition: ValueObject.h:771
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:53
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:353
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
CompilerType GetPointerType() const
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSException.cpp:97
DataExtractor GetAsData(lldb::ByteOrder byte_order=lldb::eByteOrderInvalid) const
A class to manage flags.
Definition: Flags.h:22
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:361
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
Definition: SBAddress.h:15
bool MightHaveChildren() override
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
size_t CalculateNumChildren() override
An error handling class.
Definition: Status.h:44