forked from OSchip/llvm-project
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
This commit is contained in:
parent
bf29238e1a
commit
1db0f0ca98
|
@ -63,6 +63,7 @@ public:
|
|||
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
|
||||
bool stop_others);
|
||||
|
||||
bool IsRuntimeSupportValue(ValueObject &valobj) override;
|
||||
protected:
|
||||
// Classes that inherit from CPPLanguageRuntime can see and modify these
|
||||
CPPLanguageRuntime(Process *process);
|
||||
|
|
|
@ -143,6 +143,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Identify whether a value is a language implementation detaul
|
||||
/// that should be hidden from the user interface by default.
|
||||
virtual bool IsRuntimeSupportValue(ValueObject &valobj) { return false; }
|
||||
|
||||
virtual void ModulesDidLoad(const ModuleList &module_list) {}
|
||||
|
|
|
@ -292,6 +292,11 @@ public:
|
|||
bool GetTypeBitSize(const CompilerType &compiler_type,
|
||||
uint64_t &size) override;
|
||||
|
||||
/// Check whether the name is "self" or "_cmd" and should show up in
|
||||
/// "frame variable".
|
||||
static bool IsWhitelistedRuntimeValue(ConstString name);
|
||||
bool IsRuntimeSupportValue(ValueObject &valobj) override;
|
||||
|
||||
protected:
|
||||
// Classes that inherit from ObjCLanguageRuntime can see and modify these
|
||||
ObjCLanguageRuntime(Process *process);
|
||||
|
|
|
@ -14,12 +14,23 @@ class TestVLA(TestBase):
|
|||
_, process, _, _ = lldbutil.run_to_source_breakpoint(
|
||||
self, "break here", lldb.SBFileSpec('main.c'))
|
||||
|
||||
# Make sure no helper expressions show up in frame variable.
|
||||
var_opts = lldb.SBVariablesOptions()
|
||||
var_opts.SetIncludeArguments(False)
|
||||
var_opts.SetIncludeLocals(True)
|
||||
var_opts.SetInScopeOnly(True)
|
||||
var_opts.SetIncludeStatics(False)
|
||||
var_opts.SetIncludeRuntimeSupportValues(False)
|
||||
var_opts.SetUseDynamic(lldb.eDynamicCanRunTarget)
|
||||
all_locals = self.frame().GetVariables(var_opts)
|
||||
self.assertEqual(len(all_locals), 1)
|
||||
|
||||
def test(a, array):
|
||||
for i in range(a):
|
||||
self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)])
|
||||
self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)])
|
||||
self.expect("frame var vla", substrs=array)
|
||||
self.expect("expr vla", error=True, substrs=["incomplete"])
|
||||
self.expect("fr v vla", substrs=array)
|
||||
self.expect("expr vla", error=True, substrs=["incomplete"])
|
||||
|
||||
test(2, ["int []", "[0] = 2, [1] = 1"])
|
||||
process.Continue()
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
OBJCXX_SOURCES := main.mm
|
||||
LDFLAGS = $(CFLAGS) -lobjc -framework Foundation
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,47 @@
|
|||
import lldb
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test.decorators import *
|
||||
import lldbsuite.test.lldbutil as lldbutil
|
||||
import os
|
||||
import unittest2
|
||||
|
||||
|
||||
class TestObjCXXHideRuntimeSupportValues(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def setUp(self):
|
||||
TestBase.setUp(self)
|
||||
|
||||
def test_hide_runtime_support_values(self):
|
||||
self.build()
|
||||
_, process, _, _ = lldbutil.run_to_source_breakpoint(
|
||||
self, 'break here', lldb.SBFileSpec('main.mm'))
|
||||
|
||||
var_opts = lldb.SBVariablesOptions()
|
||||
var_opts.SetIncludeArguments(True)
|
||||
var_opts.SetIncludeLocals(True)
|
||||
var_opts.SetInScopeOnly(True)
|
||||
var_opts.SetIncludeStatics(False)
|
||||
var_opts.SetIncludeRuntimeSupportValues(False)
|
||||
var_opts.SetUseDynamic(lldb.eDynamicCanRunTarget)
|
||||
values = self.frame().GetVariables(var_opts)
|
||||
|
||||
def shows_var(name):
|
||||
for value in values:
|
||||
if value.name == name:
|
||||
return True
|
||||
return False
|
||||
# ObjC method.
|
||||
values = self.frame().GetVariables(var_opts)
|
||||
self.assertFalse(shows_var("this"))
|
||||
self.assertTrue(shows_var("self"))
|
||||
self.assertTrue(shows_var("_cmd"))
|
||||
self.assertTrue(shows_var("c"))
|
||||
|
||||
process.Continue()
|
||||
# C++ method.
|
||||
values = self.frame().GetVariables(var_opts)
|
||||
self.assertTrue(shows_var("this"))
|
||||
self.assertFalse(shows_var("self"))
|
||||
self.assertFalse(shows_var("_cmd"))
|
|
@ -0,0 +1,28 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
void baz() {}
|
||||
|
||||
struct MyClass {
|
||||
void bar() {
|
||||
baz(); // break here
|
||||
}
|
||||
};
|
||||
|
||||
@interface MyObject : NSObject {}
|
||||
- (void)foo;
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
- (void)foo {
|
||||
MyClass c;
|
||||
c.bar(); // break here
|
||||
}
|
||||
@end
|
||||
|
||||
int main (int argc, char const *argv[]) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
id obj = [MyObject new];
|
||||
[obj foo];
|
||||
[pool release];
|
||||
return 0;
|
||||
}
|
|
@ -4257,9 +4257,11 @@ ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
|
|||
if (qual_type->isAnyPointerType()) {
|
||||
if (qual_type->isObjCObjectPointerType())
|
||||
return lldb::eLanguageTypeObjC;
|
||||
if (qual_type->getPointeeCXXRecordDecl())
|
||||
return lldb::eLanguageTypeC_plus_plus;
|
||||
|
||||
clang::QualType pointee_type(qual_type->getPointeeType());
|
||||
if (pointee_type->getPointeeCXXRecordDecl() != nullptr)
|
||||
if (pointee_type->getPointeeCXXRecordDecl())
|
||||
return lldb::eLanguageTypeC_plus_plus;
|
||||
if (pointee_type->isObjCObjectOrInterfaceType())
|
||||
return lldb::eLanguageTypeObjC;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Target/CPPLanguageRuntime.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -15,6 +16,7 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include "lldb/Symbol/Block.h"
|
||||
#include "lldb/Symbol/Variable.h"
|
||||
#include "lldb/Symbol/VariableList.h"
|
||||
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
|
@ -31,12 +33,30 @@
|
|||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
static ConstString g_this = ConstString("this");
|
||||
|
||||
// Destructor
|
||||
CPPLanguageRuntime::~CPPLanguageRuntime() {}
|
||||
|
||||
CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
|
||||
: LanguageRuntime(process) {}
|
||||
|
||||
bool CPPLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
|
||||
// All runtime support values have to be marked as artificial by the
|
||||
// compiler. But not all artificial variables should be hidden from
|
||||
// the user.
|
||||
if (!valobj.GetVariable())
|
||||
return false;
|
||||
if (!valobj.GetVariable()->IsArtificial())
|
||||
return false;
|
||||
|
||||
// Whitelist "this" and since there is no ObjC++ runtime, any ObjC names.
|
||||
ConstString name = valobj.GetName();
|
||||
if (name == g_this)
|
||||
return false;
|
||||
return !ObjCLanguageRuntime::IsWhitelistedRuntimeValue(name);
|
||||
}
|
||||
|
||||
bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
|
||||
ValueObject &object) {
|
||||
// C++ has no generic way to do this.
|
||||
|
@ -317,7 +337,7 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
|
|||
StackFrameSP frame = thread.GetStackFrameAtIndex(0);
|
||||
|
||||
if (frame) {
|
||||
ValueObjectSP value_sp = frame->FindVariable(ConstString("this"));
|
||||
ValueObjectSP value_sp = frame->FindVariable(g_this);
|
||||
|
||||
CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
|
||||
FindLibCppStdFunctionCallableInfo(value_sp);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "lldb/Symbol/SymbolFile.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Symbol/TypeList.h"
|
||||
#include "lldb/Symbol/Variable.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Utility/Log.h"
|
||||
|
@ -37,6 +38,25 @@ ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
|
|||
m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
|
||||
m_negative_complete_class_cache() {}
|
||||
|
||||
bool ObjCLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) {
|
||||
static ConstString g_self = ConstString("self");
|
||||
static ConstString g_cmd = ConstString("_cmd");
|
||||
return name == g_self || name == g_cmd;
|
||||
}
|
||||
|
||||
bool ObjCLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
|
||||
// All runtime support values have to be marked as artificial by the
|
||||
// compiler. But not all artificial variables should be hidden from
|
||||
// the user.
|
||||
if (!valobj.GetVariable())
|
||||
return false;
|
||||
if (!valobj.GetVariable()->IsArtificial())
|
||||
return false;
|
||||
|
||||
// Whitelist "self" and "_cmd".
|
||||
return !IsWhitelistedRuntimeValue(valobj.GetName());
|
||||
}
|
||||
|
||||
bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
|
||||
const ClassDescriptorSP &descriptor_sp,
|
||||
const char *class_name) {
|
||||
|
|
Loading…
Reference in New Issue