Skip to content

Commit 1152cf1

Browse files
committed
[lldb][ValueObject] Move Objective-C specific lookups into ObjCLanguageRuntime
I'd like to upstream these lookups. It'd be more acceptable if this lived in the LanguageRuntime.
1 parent 39dcaca commit 1152cf1

File tree

9 files changed

+139
-80
lines changed

9 files changed

+139
-80
lines changed

lldb/include/lldb/ValueObject/ValueObject.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,9 +1104,6 @@ class ValueObject {
11041104

11051105
private:
11061106
virtual CompilerType MaybeCalculateCompleteType();
1107-
CompilerType LookupInRuntime(ConstString class_name, Process &process);
1108-
CompilerType LookupInModulesVendor(ConstString class_name, Target &process);
1109-
11101107
void UpdateChildrenAddressType() {
11111108
GetRoot()->DoUpdateChildrenAddressType(*this);
11121109
}

lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,46 @@ Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(
423423
return error;
424424
}
425425

426+
CompilerType ObjCLanguageRuntime::LookupInModulesVendor(ConstString class_name,
427+
Target &target) {
428+
assert(class_name);
429+
430+
auto *persistent_state = llvm::cast<ClangPersistentVariables>(
431+
target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
432+
if (!persistent_state)
433+
return {};
434+
435+
auto clang_modules_decl_vendor_sp =
436+
persistent_state->GetClangModulesDeclVendor();
437+
if (!clang_modules_decl_vendor_sp)
438+
return {};
439+
440+
auto types = clang_modules_decl_vendor_sp->FindTypes(
441+
class_name, /*max_matches*/ UINT32_MAX);
442+
if (types.empty())
443+
return {};
444+
445+
return types.front();
446+
}
447+
448+
CompilerType ObjCLanguageRuntime::LookupInRuntime(ConstString class_name) {
449+
auto *runtime_vendor = GetDeclVendor();
450+
if (!runtime_vendor)
451+
return {};
452+
453+
std::vector<CompilerDecl> compiler_decls;
454+
runtime_vendor->FindDecls(class_name, false, UINT32_MAX, compiler_decls);
455+
if (compiler_decls.empty())
456+
return {};
457+
458+
auto *ctx =
459+
llvm::dyn_cast<TypeSystemClang>(compiler_decls[0].GetTypeSystem());
460+
if (!ctx)
461+
return {};
462+
463+
return ctx->GetTypeForDecl(compiler_decls[0].GetOpaqueDecl());
464+
}
465+
426466
std::optional<CompilerType>
427467
ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) {
428468
CompilerType class_type;
@@ -442,14 +482,21 @@ ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) {
442482
if (!class_name)
443483
return std::nullopt;
444484

445-
TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name);
446-
if (!complete_objc_class_type_sp)
447-
return std::nullopt;
485+
if (TypeSP complete_objc_class_type_sp =
486+
LookupInCompleteClassCache(class_name)) {
487+
if (CompilerType complete_class =
488+
complete_objc_class_type_sp->GetFullCompilerType();
489+
complete_class.GetCompleteType())
490+
return is_pointer_type ? complete_class.GetPointerType() : complete_class;
491+
}
492+
493+
assert(m_process);
494+
if (CompilerType found =
495+
LookupInModulesVendor(class_name, m_process->GetTarget()))
496+
return is_pointer_type ? found.GetPointerType() : found;
448497

449-
if (CompilerType complete_class =
450-
complete_objc_class_type_sp->GetFullCompilerType();
451-
complete_class.GetCompleteType())
452-
return is_pointer_type ? complete_class.GetPointerType() : complete_class;
498+
if (CompilerType found = LookupInRuntime(class_name))
499+
return is_pointer_type ? found.GetPointerType() : found;
453500

454501
return std::nullopt;
455502
}

lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,10 @@ class ObjCLanguageRuntime : public LanguageRuntime {
465465

466466
ObjCLanguageRuntime(const ObjCLanguageRuntime &) = delete;
467467
const ObjCLanguageRuntime &operator=(const ObjCLanguageRuntime &) = delete;
468+
469+
private:
470+
CompilerType LookupInRuntime(ConstString class_name);
471+
CompilerType LookupInModulesVendor(ConstString class_name, Target &process);
468472
};
469473

470474
} // namespace lldb_private

lldb/source/ValueObject/ValueObject.cpp

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -249,51 +249,6 @@ void ValueObject::ClearDynamicTypeInformation() {
249249
SetSyntheticChildren(lldb::SyntheticChildrenSP());
250250
}
251251

252-
CompilerType ValueObject::LookupInModulesVendor(ConstString class_name,
253-
Target &target) {
254-
assert(class_name);
255-
256-
auto *persistent_state = llvm::cast<ClangPersistentVariables>(
257-
target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
258-
if (!persistent_state)
259-
return {};
260-
261-
auto clang_modules_decl_vendor_sp =
262-
persistent_state->GetClangModulesDeclVendor();
263-
if (!clang_modules_decl_vendor_sp)
264-
return {};
265-
266-
auto types = clang_modules_decl_vendor_sp->FindTypes(
267-
class_name, /*max_matches*/ UINT32_MAX);
268-
if (types.empty())
269-
return {};
270-
271-
return types.front();
272-
}
273-
274-
CompilerType ValueObject::LookupInRuntime(ConstString class_name,
275-
Process &process) {
276-
auto *objc_language_runtime = ObjCLanguageRuntime::Get(process);
277-
if (!objc_language_runtime)
278-
return {};
279-
280-
auto *runtime_vendor = objc_language_runtime->GetDeclVendor();
281-
if (!runtime_vendor)
282-
return {};
283-
284-
std::vector<CompilerDecl> compiler_decls;
285-
runtime_vendor->FindDecls(class_name, false, UINT32_MAX, compiler_decls);
286-
if (compiler_decls.empty())
287-
return {};
288-
289-
auto *ctx =
290-
llvm::dyn_cast<TypeSystemClang>(compiler_decls[0].GetTypeSystem());
291-
if (!ctx)
292-
return {};
293-
294-
return ctx->GetTypeForDecl(compiler_decls[0].GetOpaqueDecl());
295-
}
296-
297252
CompilerType ValueObject::MaybeCalculateCompleteType() {
298253
CompilerType compiler_type(GetCompilerTypeImpl());
299254

@@ -322,31 +277,6 @@ CompilerType ValueObject::MaybeCalculateCompleteType() {
322277
}
323278
}
324279

325-
CompilerType class_type;
326-
bool is_pointer_type = false;
327-
if (TypeSystemClang::IsObjCObjectPointerType(compiler_type, &class_type))
328-
is_pointer_type = true;
329-
else if (TypeSystemClang::IsObjCObjectOrInterfaceType(compiler_type))
330-
class_type = compiler_type;
331-
else
332-
return compiler_type;
333-
334-
ConstString class_name(class_type.GetTypeName());
335-
if (!class_name)
336-
return compiler_type;
337-
338-
if (auto target_sp = GetTargetSP()) {
339-
if (CompilerType found = LookupInModulesVendor(class_name, *target_sp)) {
340-
m_override_type = is_pointer_type ? found.GetPointerType() : found;
341-
return m_override_type;
342-
}
343-
}
344-
345-
if (CompilerType found = LookupInRuntime(class_name, *process_sp)) {
346-
m_override_type = is_pointer_type ? found.GetPointerType() : found;
347-
return m_override_type;
348-
}
349-
350280
return compiler_type;
351281
}
352282

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
OBJC_SOURCES := main.m lib.m
2+
LD_EXTRAS = -framework Foundation
3+
4+
include Makefile.rules
5+
6+
lib.o: CFLAGS = $(CFLAGS_NO_DEBUG)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
7+
class TestIvarInFrameworkBase(TestBase):
8+
"""
9+
Tests whether LLDB's data inspection commands can correctly retrieve
10+
information about ivars from the Objective-C runtime.
11+
In this test-case we have a base class type for which we don't have access
12+
to the debug-info of the implementation (mimicking the scenario of subclassing
13+
a type from a system framework). LLDB won't be able to see the backing ivar for
14+
'fooProp' from just debug-info, but it will fall back on the runtime to get the
15+
necessary information.
16+
"""
17+
18+
def test_frame_var(self):
19+
self.build()
20+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m"))
21+
self.expect("frame variable *bar", substrs=["_fooProp = 10", "_barProp = 15"])
22+
23+
def test_expr(self):
24+
self.build()
25+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m"))
26+
self.expect_expr(
27+
"*bar",
28+
result_type="Bar",
29+
result_children=[
30+
ValueCheck(
31+
name="Foo",
32+
children=[
33+
ValueCheck(name="NSObject"),
34+
ValueCheck(name="_fooProp", value="10"),
35+
],
36+
),
37+
ValueCheck(name="_barProp", value="15"),
38+
],
39+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface Foo : NSObject
4+
@property int fooProp;
5+
- (id)init;
6+
@end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import "lib.h"
2+
3+
@implementation Foo
4+
- (id)init {
5+
self.fooProp = 10;
6+
return self;
7+
}
8+
@end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#import "lib.h"
2+
#include <stdio.h>
3+
4+
@interface Bar : Foo
5+
@property int barProp;
6+
- (id)init;
7+
@end
8+
9+
@implementation Bar
10+
11+
- (id)init {
12+
self = [super init];
13+
self.barProp = 15;
14+
return self;
15+
}
16+
@end
17+
18+
int main() {
19+
Bar *bar = [Bar new];
20+
puts("break here");
21+
return 0;
22+
}

0 commit comments

Comments
 (0)