LLDB mainline
GNUstepObjCRuntime.cpp
Go to the documentation of this file.
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
10
12
13#include "lldb/Core/Module.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
27
29
32 GetPluginNameStatic(), "GNUstep Objective-C Language Runtime - libobjc2",
34}
35
38}
39
40static 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
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);
62 return true;
63 }
64 return false;
65}
66
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();
81 return nullptr;
82
83 if (TT.isOSBinFormatELF()) {
84 SymbolContextList eh_pers;
85 RegularExpression regex("__gnustep_objc[x]*_personality_v[0-9]+");
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
101
103 : ObjCLanguageRuntime(process), m_objc_module_sp(nullptr) {
105}
106
108 ValueObject &valobj) {
109 // TODO: ObjC has a generic way to do this
110 return false;
111}
113 Stream &strm, Value &value, ExecutionContextScope *exe_scope) {
114 // TODO: ObjC has a generic way to do this
115 return false;
116}
117
119 static constexpr bool check_cxx = false;
120 static constexpr bool check_objc = true;
121 return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx,
122 check_objc);
123}
124
126 ValueObject &in_value, DynamicValueType use_dynamic,
127 TypeAndOrName &class_type_or_name, Address &address,
128 Value::ValueType &value_type) {
129 return false;
130}
131
134 ValueObject &static_value) {
135 CompilerType static_type(static_value.GetCompilerType());
136 Flags static_type_flags(static_type.GetTypeInfo());
137
138 TypeAndOrName ret(type_and_or_name);
139 if (type_and_or_name.HasType()) {
140 // The type will always be the type of the dynamic object. If our parent's
141 // type was a pointer, then our type should be a pointer to the type of the
142 // dynamic object. If a reference, then the original type should be
143 // okay...
144 CompilerType orig_type = type_and_or_name.GetCompilerType();
145 CompilerType corrected_type = orig_type;
146 if (static_type_flags.AllSet(eTypeIsPointer))
147 corrected_type = orig_type.GetPointerType();
148 ret.SetCompilerType(corrected_type);
149 } else {
150 // If we are here we need to adjust our dynamic type name to include the
151 // correct & or * symbol
152 std::string corrected_name(type_and_or_name.GetName().GetCString());
153 if (static_type_flags.AllSet(eTypeIsPointer))
154 corrected_name.append(" *");
155 // the parent type should be a correctly pointer'ed or referenc'ed type
156 ret.SetCompilerType(static_type);
157 ret.SetName(corrected_name.c_str());
158 }
159 return ret;
160}
161
164 bool catch_bp, bool throw_bp) {
165 BreakpointResolverSP resolver_sp;
166
167 if (throw_bp)
168 resolver_sp = std::make_shared<BreakpointResolverName>(
169 bkpt, "objc_exception_throw", eFunctionNameTypeBase,
171
172 return resolver_sp;
173}
174
175llvm::Expected<std::unique_ptr<UtilityFunction>>
177 ExecutionContext &exe_ctx) {
178 // TODO: This function is supposed to check whether an ObjC selector is
179 // present for an object. Might be implemented similar as in the Apple V2
180 // runtime.
181 const char *function_template = R"(
182 extern "C" void
183 %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {}
184 )";
185
186 char empty_function_code[2048];
187 int len = ::snprintf(empty_function_code, sizeof(empty_function_code),
188 function_template, name.c_str());
189
190 assert(len < (int)sizeof(empty_function_code));
192
193 return GetTargetRef().CreateUtilityFunction(empty_function_code, name,
194 eLanguageTypeC, exe_ctx);
195}
196
199 bool stop_others) {
200 // TODO: Implement this properly to avoid stepping into things like PLT stubs
201 return nullptr;
202}
203
205 // TODO: Support lazily named and dynamically loaded Objective-C classes
206}
207
209 const llvm::Triple &TT = GetTargetRef().GetArchitecture().GetTriple();
210 return CanModuleBeGNUstepObjCLibrary(module_sp, TT);
211}
212
214 assert(m_objc_module_sp == nullptr && "Check HasReadObjCLibrary() first");
215 m_objc_module_sp = module_sp;
216
217 // Right now we don't use this, but we might want to check for debugger
218 // runtime support symbols like 'gdb_object_getClass' in the future.
219 return true;
220}
221
223 ReadObjCLibraryIfNeeded(module_list);
224}
static bool ScanForGNUstepObjCLibraryCandidate(const ModuleList &modules, const llvm::Triple &TT)
static bool CanModuleBeGNUstepObjCLibrary(const ModuleSP &module_sp, const llvm::Triple &TT)
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
A section + offset based address class.
Definition: Address.h:62
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
bool IsPossibleDynamicType(CompilerType *target_type, bool check_cplusplus, bool check_objc) const
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
Definition: ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A file utility class.
Definition: FileSpec.h:56
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:240
A class to manage flags.
Definition: Flags.h:22
bool AllSet(ValueType mask) const
Test if all bits in mask are 1 in the current flags.
Definition: Flags.h:83
bool CouldHaveDynamicValue(ValueObject &in_value) override
bool GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override
bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) override
llvm::Expected< std::unique_ptr< UtilityFunction > > CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override
TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override
static lldb_private::LanguageRuntime * CreateInstance(Process *process, lldb::LanguageType language)
bool ReadObjCLibrary(const lldb::ModuleSP &module_sp) override
bool IsModuleObjCLibrary(const lldb::ModuleSP &module_sp) override
static llvm::StringRef GetPluginNameStatic()
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others) override
lldb::BreakpointResolverSP CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp, bool throw_bp) override
void ModulesDidLoad(const ModuleList &module_list) override
Called when modules have been loaded in the process.
A collection class for Module objects.
Definition: ModuleList.h:103
std::recursive_mutex & GetMutex() const
Definition: ModuleList.h:230
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
Definition: ModuleList.cpp:527
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
Definition: ModuleList.cpp:429
void FindSymbolsMatchingRegExAndType(const RegularExpression &regex, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
Definition: ModuleList.cpp:535
size_t GetSize() const
Gets the size of the module list.
Definition: ModuleList.cpp:638
void ReadObjCLibraryIfNeeded(const ModuleList &module_list)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1277
Target & GetTargetRef()
Definition: Runtime.h:23
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
Defines a list of symbol context objects.
uint32_t GetSize() const
Get accessor for a symbol context list size.
llvm::Expected< std::unique_ptr< UtilityFunction > > CreateUtilityFunction(std::string expression, std::string name, lldb::LanguageType language, ExecutionContext &exe_ctx)
Creates and installs a UtilityFunction for the given language.
Definition: Target.cpp:2567
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:981
const ArchSpec & GetArchitecture() const
Definition: Target.h:1023
Sometimes you can find the name of the type corresponding to an object, but we don't have debug infor...
Definition: Type.h:743
void SetName(ConstString type_name)
Definition: Type.cpp:883
CompilerType GetCompilerType() const
Definition: Type.h:757
ConstString GetName() const
Definition: Type.cpp:875
void SetCompilerType(CompilerType compiler_type)
Definition: Type.cpp:903
bool HasType() const
Definition: Type.h:775
CompilerType GetCompilerType()
Definition: ValueObject.h:352
ValueType
Type that describes Value::m_value.
Definition: Value.h:41
#define UNUSED_IF_ASSERT_DISABLED(x)
Definition: lldb-defines.h:140
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
Definition: lldb-forward.h:444
std::shared_ptr< lldb_private::BreakpointResolver > BreakpointResolverSP
Definition: lldb-forward.h:323
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
Definition: lldb-forward.h:316
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:368