Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp
39690 views
1
//===-- GNUstepObjCRuntime.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 "GNUstepObjCRuntime.h"
10
11
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12
13
#include "lldb/Core/Module.h"
14
#include "lldb/Core/PluginManager.h"
15
#include "lldb/Core/ValueObject.h"
16
#include "lldb/Expression/UtilityFunction.h"
17
#include "lldb/Target/ExecutionContext.h"
18
#include "lldb/Target/Process.h"
19
#include "lldb/Target/Target.h"
20
#include "lldb/Utility/ArchSpec.h"
21
#include "lldb/Utility/ConstString.h"
22
23
using namespace lldb;
24
using namespace lldb_private;
25
26
LLDB_PLUGIN_DEFINE(GNUstepObjCRuntime)
27
28
char GNUstepObjCRuntime::ID = 0;
29
30
void GNUstepObjCRuntime::Initialize() {
31
PluginManager::RegisterPlugin(
32
GetPluginNameStatic(), "GNUstep Objective-C Language Runtime - libobjc2",
33
CreateInstance);
34
}
35
36
void GNUstepObjCRuntime::Terminate() {
37
PluginManager::UnregisterPlugin(CreateInstance);
38
}
39
40
static bool CanModuleBeGNUstepObjCLibrary(const ModuleSP &module_sp,
41
const llvm::Triple &TT) {
42
if (!module_sp)
43
return false;
44
const FileSpec &module_file_spec = module_sp->GetFileSpec();
45
if (!module_file_spec)
46
return false;
47
llvm::StringRef filename = module_file_spec.GetFilename().GetStringRef();
48
if (TT.isOSBinFormatELF())
49
return filename.starts_with("libobjc.so");
50
if (TT.isOSWindows())
51
return filename == "objc.dll";
52
return false;
53
}
54
55
static bool ScanForGNUstepObjCLibraryCandidate(const ModuleList &modules,
56
const llvm::Triple &TT) {
57
std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
58
size_t num_modules = modules.GetSize();
59
for (size_t i = 0; i < num_modules; i++) {
60
auto mod = modules.GetModuleAtIndex(i);
61
if (CanModuleBeGNUstepObjCLibrary(mod, TT))
62
return true;
63
}
64
return false;
65
}
66
67
LanguageRuntime *GNUstepObjCRuntime::CreateInstance(Process *process,
68
LanguageType language) {
69
if (language != eLanguageTypeObjC)
70
return nullptr;
71
if (!process)
72
return nullptr;
73
74
Target &target = process->GetTarget();
75
const llvm::Triple &TT = target.GetArchitecture().GetTriple();
76
if (TT.getVendor() == llvm::Triple::VendorType::Apple)
77
return nullptr;
78
79
const ModuleList &images = target.GetImages();
80
if (!ScanForGNUstepObjCLibraryCandidate(images, TT))
81
return nullptr;
82
83
if (TT.isOSBinFormatELF()) {
84
SymbolContextList eh_pers;
85
RegularExpression regex("__gnustep_objc[x]*_personality_v[0-9]+");
86
images.FindSymbolsMatchingRegExAndType(regex, eSymbolTypeCode, eh_pers);
87
if (eh_pers.GetSize() == 0)
88
return nullptr;
89
} else if (TT.isOSWindows()) {
90
SymbolContextList objc_mandatory;
91
images.FindSymbolsWithNameAndType(ConstString("__objc_load"),
92
eSymbolTypeCode, objc_mandatory);
93
if (objc_mandatory.GetSize() == 0)
94
return nullptr;
95
}
96
97
return new GNUstepObjCRuntime(process);
98
}
99
100
GNUstepObjCRuntime::~GNUstepObjCRuntime() = default;
101
102
GNUstepObjCRuntime::GNUstepObjCRuntime(Process *process)
103
: ObjCLanguageRuntime(process), m_objc_module_sp(nullptr) {
104
ReadObjCLibraryIfNeeded(process->GetTarget().GetImages());
105
}
106
107
llvm::Error GNUstepObjCRuntime::GetObjectDescription(Stream &str,
108
ValueObject &valobj) {
109
return llvm::createStringError(
110
"LLDB's GNUStep runtime does not support object description");
111
}
112
113
llvm::Error
114
GNUstepObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
115
ExecutionContextScope *exe_scope) {
116
return llvm::createStringError(
117
"LLDB's GNUStep runtime does not support object description");
118
}
119
120
bool GNUstepObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
121
static constexpr bool check_cxx = false;
122
static constexpr bool check_objc = true;
123
return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx,
124
check_objc);
125
}
126
127
bool GNUstepObjCRuntime::GetDynamicTypeAndAddress(
128
ValueObject &in_value, DynamicValueType use_dynamic,
129
TypeAndOrName &class_type_or_name, Address &address,
130
Value::ValueType &value_type) {
131
return false;
132
}
133
134
TypeAndOrName
135
GNUstepObjCRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
136
ValueObject &static_value) {
137
CompilerType static_type(static_value.GetCompilerType());
138
Flags static_type_flags(static_type.GetTypeInfo());
139
140
TypeAndOrName ret(type_and_or_name);
141
if (type_and_or_name.HasType()) {
142
// The type will always be the type of the dynamic object. If our parent's
143
// type was a pointer, then our type should be a pointer to the type of the
144
// dynamic object. If a reference, then the original type should be
145
// okay...
146
CompilerType orig_type = type_and_or_name.GetCompilerType();
147
CompilerType corrected_type = orig_type;
148
if (static_type_flags.AllSet(eTypeIsPointer))
149
corrected_type = orig_type.GetPointerType();
150
ret.SetCompilerType(corrected_type);
151
} else {
152
// If we are here we need to adjust our dynamic type name to include the
153
// correct & or * symbol
154
std::string corrected_name(type_and_or_name.GetName().GetCString());
155
if (static_type_flags.AllSet(eTypeIsPointer))
156
corrected_name.append(" *");
157
// the parent type should be a correctly pointer'ed or referenc'ed type
158
ret.SetCompilerType(static_type);
159
ret.SetName(corrected_name.c_str());
160
}
161
return ret;
162
}
163
164
BreakpointResolverSP
165
GNUstepObjCRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,
166
bool catch_bp, bool throw_bp) {
167
BreakpointResolverSP resolver_sp;
168
169
if (throw_bp)
170
resolver_sp = std::make_shared<BreakpointResolverName>(
171
bkpt, "objc_exception_throw", eFunctionNameTypeBase,
172
eLanguageTypeUnknown, Breakpoint::Exact, 0, eLazyBoolNo);
173
174
return resolver_sp;
175
}
176
177
llvm::Expected<std::unique_ptr<UtilityFunction>>
178
GNUstepObjCRuntime::CreateObjectChecker(std::string name,
179
ExecutionContext &exe_ctx) {
180
// TODO: This function is supposed to check whether an ObjC selector is
181
// present for an object. Might be implemented similar as in the Apple V2
182
// runtime.
183
const char *function_template = R"(
184
extern "C" void
185
%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {}
186
)";
187
188
char empty_function_code[2048];
189
int len = ::snprintf(empty_function_code, sizeof(empty_function_code),
190
function_template, name.c_str());
191
192
assert(len < (int)sizeof(empty_function_code));
193
UNUSED_IF_ASSERT_DISABLED(len);
194
195
return GetTargetRef().CreateUtilityFunction(empty_function_code, name,
196
eLanguageTypeC, exe_ctx);
197
}
198
199
ThreadPlanSP
200
GNUstepObjCRuntime::GetStepThroughTrampolinePlan(Thread &thread,
201
bool stop_others) {
202
// TODO: Implement this properly to avoid stepping into things like PLT stubs
203
return nullptr;
204
}
205
206
void GNUstepObjCRuntime::UpdateISAToDescriptorMapIfNeeded() {
207
// TODO: Support lazily named and dynamically loaded Objective-C classes
208
}
209
210
bool GNUstepObjCRuntime::IsModuleObjCLibrary(const ModuleSP &module_sp) {
211
const llvm::Triple &TT = GetTargetRef().GetArchitecture().GetTriple();
212
return CanModuleBeGNUstepObjCLibrary(module_sp, TT);
213
}
214
215
bool GNUstepObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) {
216
assert(m_objc_module_sp == nullptr && "Check HasReadObjCLibrary() first");
217
m_objc_module_sp = module_sp;
218
219
// Right now we don't use this, but we might want to check for debugger
220
// runtime support symbols like 'gdb_object_getClass' in the future.
221
return true;
222
}
223
224
void GNUstepObjCRuntime::ModulesDidLoad(const ModuleList &module_list) {
225
ReadObjCLibraryIfNeeded(module_list);
226
}
227
228