LLDB  mainline
NSException.cpp
Go to the documentation of this file.
1 //===-- NSException.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 
9 #include "clang/AST/DeclCXX.h"
10 
11 #include "Cocoa.h"
12 
13 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/Endian.h"
20 #include "lldb/Utility/Status.h"
21 #include "lldb/Utility/Stream.h"
22 
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  auto *clang_ast_context =
73  ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
74  if (!clang_ast_context)
75  return false;
76 
77  CompilerType voidstar =
78  clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
79 
80  if (name_sp)
81  *name_sp = ValueObject::CreateValueObjectFromData(
82  "name", name_isw.GetAsData(process_sp->GetByteOrder()),
83  valobj.GetExecutionContextRef(), voidstar);
84  if (reason_sp)
85  *reason_sp = ValueObject::CreateValueObjectFromData(
86  "reason", reason_isw.GetAsData(process_sp->GetByteOrder()),
87  valobj.GetExecutionContextRef(), voidstar);
88  if (userinfo_sp)
89  *userinfo_sp = ValueObject::CreateValueObjectFromData(
90  "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()),
91  valobj.GetExecutionContextRef(), voidstar);
92  if (reserved_sp)
93  *reserved_sp = ValueObject::CreateValueObjectFromData(
94  "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()),
95  valobj.GetExecutionContextRef(), voidstar);
96 
97  return true;
98 }
99 
101  ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
102  lldb::ValueObjectSP reason_sp;
103  if (!ExtractFields(valobj, nullptr, &reason_sp, nullptr, nullptr))
104  return false;
105 
106  if (!reason_sp) {
107  stream.Printf("No reason");
108  return false;
109  }
110 
111  StreamString reason_str_summary;
112  if (NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
113  !reason_str_summary.Empty()) {
114  stream.Printf("%s", reason_str_summary.GetData());
115  return true;
116  } else
117  return false;
118 }
119 
121 public:
122  NSExceptionSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
123  : SyntheticChildrenFrontEnd(*valobj_sp) {}
124 
125  ~NSExceptionSyntheticFrontEnd() override = default;
126 
127  size_t CalculateNumChildren() override {
128  return 4;
129  }
130 
131  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
132  switch (idx) {
133  case 0: return m_name_sp;
134  case 1: return m_reason_sp;
135  case 2: return m_userinfo_sp;
136  case 3: return m_reserved_sp;
137  }
138  return lldb::ValueObjectSP();
139  }
140 
141  bool Update() override {
142  m_name_sp.reset();
143  m_reason_sp.reset();
144  m_userinfo_sp.reset();
145  m_reserved_sp.reset();
146 
147  return ExtractFields(m_backend, &m_name_sp, &m_reason_sp, &m_userinfo_sp,
148  &m_reserved_sp);
149  }
150 
151  bool MightHaveChildren() override { return true; }
152 
153  size_t GetIndexOfChildWithName(ConstString name) override {
154  // NSException has 4 members:
155  // NSString *name;
156  // NSString *reason;
157  // NSDictionary *userInfo;
158  // id reserved;
159  static ConstString g___name("name");
160  static ConstString g___reason("reason");
161  static ConstString g___userInfo("userInfo");
162  static ConstString g___reserved("reserved");
163  if (name == g___name) return 0;
164  if (name == g___reason) return 1;
165  if (name == g___userInfo) return 2;
166  if (name == g___reserved) return 3;
167  return UINT32_MAX;
168  }
169 
170 private:
171  ValueObjectSP m_name_sp;
172  ValueObjectSP m_reason_sp;
173  ValueObjectSP m_userinfo_sp;
174  ValueObjectSP m_reserved_sp;
175 };
176 
179  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
180  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
181  if (!process_sp)
182  return nullptr;
183  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
184  if (!runtime)
185  return nullptr;
186 
188  runtime->GetClassDescriptor(*valobj_sp.get()));
189 
190  if (!descriptor.get() || !descriptor->IsValid())
191  return nullptr;
192 
193  const char *class_name = descriptor->GetClassName().GetCString();
194 
195  if (!class_name || !*class_name)
196  return nullptr;
197 
198  if (!strcmp(class_name, "NSException"))
199  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
200  else if (!strcmp(class_name, "NSCFException"))
201  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
202  else if (!strcmp(class_name, "__NSCFException"))
203  return (new NSExceptionSyntheticFrontEnd(valobj_sp));
204 
205  return nullptr;
206 }
lldb_private::ValueObject::GetValueAsUnsigned
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
Definition: ValueObject.cpp:1090
lldb_private::ObjCLanguageRuntime
Definition: ObjCLanguageRuntime.h:34
NSExceptionSyntheticFrontEnd
Definition: NSException.cpp:120
lldb_private::ObjCLanguageRuntime::ClassDescriptorSP
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
Definition: ObjCLanguageRuntime.h:44
NSExceptionSyntheticFrontEnd::MightHaveChildren
bool MightHaveChildren() override
Definition: NSException.cpp:151
lldb_private::Flags::AllClear
bool AllClear(ValueType mask) const
Test if all bits in mask are clear.
Definition: Flags.h:103
lldb_private::Flags
Definition: Flags.h:22
lldb_private::SyntheticChildrenFrontEnd
Definition: TypeSynthetic.h:27
lldb_private::Stream
Definition: Stream.h:28
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
NSExceptionSyntheticFrontEnd::m_reason_sp
ValueObjectSP m_reason_sp
Definition: NSException.cpp:172
lldb_private::formatters::InferiorSizedWord
Definition: FormattersHelpers.h:65
ExtractFields
static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp, ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp, ValueObjectSP *reserved_sp)
Definition: NSException.cpp:31
NSExceptionSyntheticFrontEnd::CalculateNumChildren
size_t CalculateNumChildren() override
Definition: NSException.cpp:127
lldb_private::formatters::NSStringSummaryProvider
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:52
Target.h
lldb_private::ValueObject::GetProcessSP
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:338
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
TypeSystemClang.h
lldb_private::ValueObject::IsBaseClass
virtual bool IsBaseClass()
Definition: ValueObject.h:398
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
lldb_private::ObjCLanguageRuntime::GetClassDescriptor
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
Definition: ObjCLanguageRuntime.cpp:236
NSExceptionSyntheticFrontEnd::GetChildAtIndex
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: NSException.cpp:131
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StreamString
Definition: StreamString.h:23
lldb::eBasicTypeVoid
@ eBasicTypeVoid
Definition: lldb-enumerations.h:743
lldb_private::ValueObject::GetParent
virtual ValueObject * GetParent()
Definition: ValueObject.h:753
lldb_private::ValueObject::GetExecutionContextRef
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:330
lldb_private::StreamString::Empty
bool Empty() const
Definition: StreamString.cpp:36
ValueObject.h
ValueObjectConstResult.h
lldb_private::formatters::InferiorSizedWord::GetAsData
DataExtractor GetAsData(lldb::ByteOrder byte_order=lldb::eByteOrderInvalid) const
Definition: FormattersHelpers.h:167
ProcessStructReader.h
lldb_private::Status
Definition: Status.h:44
lldb_private::ValueObject
ValueObject:
Definition: ValueObject.h:105
lldb_private::CompilerType::GetPointerType
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
Definition: CompilerType.cpp:407
lldb_private::formatters::NSExceptionSyntheticFrontEndCreator
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
Definition: NSException.cpp:178
NSExceptionSyntheticFrontEnd::m_userinfo_sp
ValueObjectSP m_userinfo_sp
Definition: NSException.cpp:173
lldb_private::formatters::NSException_SummaryProvider
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSException.cpp:100
lldb_private::CompilerType::GetTypeInfo
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
Definition: CompilerType.cpp:290
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:31
NSExceptionSyntheticFrontEnd::GetIndexOfChildWithName
size_t GetIndexOfChildWithName(ConstString name) override
Definition: NSException.cpp:153
lldb_private::ValueObject::GetCompilerType
CompilerType GetCompilerType()
Definition: ValueObject.h:352
NSExceptionSyntheticFrontEnd::m_reserved_sp
ValueObjectSP m_reserved_sp
Definition: NSException.cpp:174
ObjCLanguageRuntime.h
NSExceptionSyntheticFrontEnd::m_name_sp
ValueObjectSP m_name_sp
Definition: NSException.cpp:171
lldb_private::TypeSummaryOptions
Definition: TypeSummary.h:26
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
Status.h
lldb_private::formatters
Definition: CXXFunctionPointer.h:15
NSString.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
NSExceptionSyntheticFrontEnd::NSExceptionSyntheticFrontEnd
NSExceptionSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: NSException.cpp:122
NSExceptionSyntheticFrontEnd::Update
bool Update() override
Definition: NSException.cpp:141
Stream.h
Cocoa.h
lldb_private::CXXSyntheticChildren
Definition: TypeSynthetic.h:358
FormattersHelpers.h
lldb
Definition: SBAddress.h:15
Endian.h
DataBufferHeap.h