Skip to content

Commit

Permalink
Hide runtime support values such as clang's __vla_expr from frame var…
Browse files Browse the repository at this point in the history
…iable

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
  • Loading branch information
adrian-prantl authored and MrSidims committed May 24, 2019
1 parent a85a832 commit c19d7fb
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 4 deletions.
1 change: 1 addition & 0 deletions lldb/include/lldb/Target/CPPLanguageRuntime.h
Expand Up @@ -63,6 +63,7 @@ class CPPLanguageRuntime : public LanguageRuntime {
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);
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Target/LanguageRuntime.h
Expand Up @@ -143,6 +143,8 @@ class LanguageRuntime : public PluginInterface {
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) {}
Expand Down
5 changes: 5 additions & 0 deletions lldb/include/lldb/Target/ObjCLanguageRuntime.h
Expand Up @@ -292,6 +292,11 @@ class ObjCLanguageRuntime : public LanguageRuntime {
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);
Expand Down
15 changes: 13 additions & 2 deletions lldb/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py
Expand Up @@ -14,12 +14,23 @@ def test_vla(self):
_, 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()
Expand Down
@@ -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;
}
4 changes: 3 additions & 1 deletion lldb/source/Symbol/ClangASTContext.cpp
Expand Up @@ -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;
Expand Down
22 changes: 21 additions & 1 deletion lldb/source/Target/CPPLanguageRuntime.cpp
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"

#include <string.h>

Expand All @@ -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"
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions lldb/source/Target/ObjCLanguageRuntime.cpp
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down

0 comments on commit c19d7fb

Please sign in to comment.