Skip to content

Commit 1db0f0c

Browse files
committedMay 2, 2019
Hide runtime support values such as clang's __vla_expr from frame variable
by respecting the "artificial" attribute on variables. Function arguments that are artificial and useful to end-users are being whitelisted by the language runtime. <rdar://problem/45322477> Differential Revision: https://reviews.llvm.org/D61451 llvm-svn: 359841
1 parent bf29238 commit 1db0f0c

File tree

10 files changed

+146
-4
lines changed

10 files changed

+146
-4
lines changed
 

‎lldb/include/lldb/Target/CPPLanguageRuntime.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class CPPLanguageRuntime : public LanguageRuntime {
6363
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
6464
bool stop_others);
6565

66+
bool IsRuntimeSupportValue(ValueObject &valobj) override;
6667
protected:
6768
// Classes that inherit from CPPLanguageRuntime can see and modify these
6869
CPPLanguageRuntime(Process *process);

‎lldb/include/lldb/Target/LanguageRuntime.h

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ class LanguageRuntime : public PluginInterface {
143143
return false;
144144
}
145145

146+
/// Identify whether a value is a language implementation detaul
147+
/// that should be hidden from the user interface by default.
146148
virtual bool IsRuntimeSupportValue(ValueObject &valobj) { return false; }
147149

148150
virtual void ModulesDidLoad(const ModuleList &module_list) {}

‎lldb/include/lldb/Target/ObjCLanguageRuntime.h

+5
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ class ObjCLanguageRuntime : public LanguageRuntime {
292292
bool GetTypeBitSize(const CompilerType &compiler_type,
293293
uint64_t &size) override;
294294

295+
/// Check whether the name is "self" or "_cmd" and should show up in
296+
/// "frame variable".
297+
static bool IsWhitelistedRuntimeValue(ConstString name);
298+
bool IsRuntimeSupportValue(ValueObject &valobj) override;
299+
295300
protected:
296301
// Classes that inherit from ObjCLanguageRuntime can see and modify these
297302
ObjCLanguageRuntime(Process *process);

‎lldb/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@ def test_vla(self):
1414
_, process, _, _ = lldbutil.run_to_source_breakpoint(
1515
self, "break here", lldb.SBFileSpec('main.c'))
1616

17+
# Make sure no helper expressions show up in frame variable.
18+
var_opts = lldb.SBVariablesOptions()
19+
var_opts.SetIncludeArguments(False)
20+
var_opts.SetIncludeLocals(True)
21+
var_opts.SetInScopeOnly(True)
22+
var_opts.SetIncludeStatics(False)
23+
var_opts.SetIncludeRuntimeSupportValues(False)
24+
var_opts.SetUseDynamic(lldb.eDynamicCanRunTarget)
25+
all_locals = self.frame().GetVariables(var_opts)
26+
self.assertEqual(len(all_locals), 1)
27+
1728
def test(a, array):
1829
for i in range(a):
1930
self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)])
2031
self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)])
21-
self.expect("frame var vla", substrs=array)
22-
self.expect("expr vla", error=True, substrs=["incomplete"])
32+
self.expect("fr v vla", substrs=array)
33+
self.expect("expr vla", error=True, substrs=["incomplete"])
2334

2435
test(2, ["int []", "[0] = 2, [1] = 1"])
2536
process.Continue()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
LEVEL = ../../../make
2+
3+
OBJCXX_SOURCES := main.mm
4+
LDFLAGS = $(CFLAGS) -lobjc -framework Foundation
5+
6+
include $(LEVEL)/Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestObjCXXHideRuntimeSupportValues(TestBase):
10+
11+
mydir = TestBase.compute_mydir(__file__)
12+
13+
def setUp(self):
14+
TestBase.setUp(self)
15+
16+
def test_hide_runtime_support_values(self):
17+
self.build()
18+
_, process, _, _ = lldbutil.run_to_source_breakpoint(
19+
self, 'break here', lldb.SBFileSpec('main.mm'))
20+
21+
var_opts = lldb.SBVariablesOptions()
22+
var_opts.SetIncludeArguments(True)
23+
var_opts.SetIncludeLocals(True)
24+
var_opts.SetInScopeOnly(True)
25+
var_opts.SetIncludeStatics(False)
26+
var_opts.SetIncludeRuntimeSupportValues(False)
27+
var_opts.SetUseDynamic(lldb.eDynamicCanRunTarget)
28+
values = self.frame().GetVariables(var_opts)
29+
30+
def shows_var(name):
31+
for value in values:
32+
if value.name == name:
33+
return True
34+
return False
35+
# ObjC method.
36+
values = self.frame().GetVariables(var_opts)
37+
self.assertFalse(shows_var("this"))
38+
self.assertTrue(shows_var("self"))
39+
self.assertTrue(shows_var("_cmd"))
40+
self.assertTrue(shows_var("c"))
41+
42+
process.Continue()
43+
# C++ method.
44+
values = self.frame().GetVariables(var_opts)
45+
self.assertTrue(shows_var("this"))
46+
self.assertFalse(shows_var("self"))
47+
self.assertFalse(shows_var("_cmd"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#import <Foundation/Foundation.h>
2+
3+
void baz() {}
4+
5+
struct MyClass {
6+
void bar() {
7+
baz(); // break here
8+
}
9+
};
10+
11+
@interface MyObject : NSObject {}
12+
- (void)foo;
13+
@end
14+
15+
@implementation MyObject
16+
- (void)foo {
17+
MyClass c;
18+
c.bar(); // break here
19+
}
20+
@end
21+
22+
int main (int argc, char const *argv[]) {
23+
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
24+
id obj = [MyObject new];
25+
[obj foo];
26+
[pool release];
27+
return 0;
28+
}

‎lldb/source/Symbol/ClangASTContext.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -4257,9 +4257,11 @@ ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
42574257
if (qual_type->isAnyPointerType()) {
42584258
if (qual_type->isObjCObjectPointerType())
42594259
return lldb::eLanguageTypeObjC;
4260+
if (qual_type->getPointeeCXXRecordDecl())
4261+
return lldb::eLanguageTypeC_plus_plus;
42604262

42614263
clang::QualType pointee_type(qual_type->getPointeeType());
4262-
if (pointee_type->getPointeeCXXRecordDecl() != nullptr)
4264+
if (pointee_type->getPointeeCXXRecordDecl())
42634265
return lldb::eLanguageTypeC_plus_plus;
42644266
if (pointee_type->isObjCObjectOrInterfaceType())
42654267
return lldb::eLanguageTypeObjC;

‎lldb/source/Target/CPPLanguageRuntime.cpp

+21-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Target/CPPLanguageRuntime.h"
10+
#include "lldb/Target/ObjCLanguageRuntime.h"
1011

1112
#include <string.h>
1213

@@ -15,6 +16,7 @@
1516
#include "llvm/ADT/StringRef.h"
1617

1718
#include "lldb/Symbol/Block.h"
19+
#include "lldb/Symbol/Variable.h"
1820
#include "lldb/Symbol/VariableList.h"
1921

2022
#include "lldb/Core/PluginManager.h"
@@ -31,12 +33,30 @@
3133
using namespace lldb;
3234
using namespace lldb_private;
3335

36+
static ConstString g_this = ConstString("this");
37+
3438
// Destructor
3539
CPPLanguageRuntime::~CPPLanguageRuntime() {}
3640

3741
CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
3842
: LanguageRuntime(process) {}
3943

44+
bool CPPLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
45+
// All runtime support values have to be marked as artificial by the
46+
// compiler. But not all artificial variables should be hidden from
47+
// the user.
48+
if (!valobj.GetVariable())
49+
return false;
50+
if (!valobj.GetVariable()->IsArtificial())
51+
return false;
52+
53+
// Whitelist "this" and since there is no ObjC++ runtime, any ObjC names.
54+
ConstString name = valobj.GetName();
55+
if (name == g_this)
56+
return false;
57+
return !ObjCLanguageRuntime::IsWhitelistedRuntimeValue(name);
58+
}
59+
4060
bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
4161
ValueObject &object) {
4262
// C++ has no generic way to do this.
@@ -317,7 +337,7 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
317337
StackFrameSP frame = thread.GetStackFrameAtIndex(0);
318338

319339
if (frame) {
320-
ValueObjectSP value_sp = frame->FindVariable(ConstString("this"));
340+
ValueObjectSP value_sp = frame->FindVariable(g_this);
321341

322342
CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
323343
FindLibCppStdFunctionCallableInfo(value_sp);

‎lldb/source/Target/ObjCLanguageRuntime.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "lldb/Symbol/SymbolFile.h"
1717
#include "lldb/Symbol/Type.h"
1818
#include "lldb/Symbol/TypeList.h"
19+
#include "lldb/Symbol/Variable.h"
1920
#include "lldb/Target/ObjCLanguageRuntime.h"
2021
#include "lldb/Target/Target.h"
2122
#include "lldb/Utility/Log.h"
@@ -37,6 +38,25 @@ ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
3738
m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
3839
m_negative_complete_class_cache() {}
3940

41+
bool ObjCLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) {
42+
static ConstString g_self = ConstString("self");
43+
static ConstString g_cmd = ConstString("_cmd");
44+
return name == g_self || name == g_cmd;
45+
}
46+
47+
bool ObjCLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
48+
// All runtime support values have to be marked as artificial by the
49+
// compiler. But not all artificial variables should be hidden from
50+
// the user.
51+
if (!valobj.GetVariable())
52+
return false;
53+
if (!valobj.GetVariable()->IsArtificial())
54+
return false;
55+
56+
// Whitelist "self" and "_cmd".
57+
return !IsWhitelistedRuntimeValue(valobj.GetName());
58+
}
59+
4060
bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
4161
const ClassDescriptorSP &descriptor_sp,
4262
const char *class_name) {

0 commit comments

Comments
 (0)
Please sign in to comment.