Skip to content

Commit

Permalink
[Expression Parser] Inhibit global lookups for symbols in the IR dyna…
Browse files Browse the repository at this point in the history
…mic checks

The IR dynamic checks are self-contained functions whose job is to

- verify that pointers referenced in an expression are valid at runtime; and
- verify that selectors sent to Objective-C objects by an expression are
  actually supported by that object.

These dynamic checks forward-declare all the functions they use and should not
require any external debug information. The way they ensure this is by marking
all the names they use with a dollar sign ($). The expression parser recognizes
such symbols and perform no lookups for them.

This patch fixes three issues surrounding the use of the dollar sign:

- to fix a MIPS issue, the name of the pointer checker was changed from
  starting with $ to starting with _$, but this was not properly ignored; and
- the Objective-C object checker used a temporary variable that did not start
  with $.
- the Objective-C object checker used an externally-defined struct (struct
  objc_selector) but didn't need to.

The patch also implements some cleanup in the area:

- it reformats the string containing the Objective-C object checker,
  which was mangled horribly when the code was transformed to a uniform width
  of 80 columns, and
- it factors out the logic for ignoring global $-symbols into common code
  shared between ClangASTSource and ClangExpressionDeclMap.

Differential Revision: https://reviews.llvm.org/D38153

llvm-svn: 314225
  • Loading branch information
scallanan committed Sep 26, 2017
1 parent b59abb2 commit 1b3c43b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 105 deletions.
34 changes: 20 additions & 14 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
Expand Up @@ -623,6 +623,25 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
}
}

bool ClangASTSource::IgnoreName(const ConstString name,
bool ignore_all_dollar_names) {
static const ConstString id_name("id");
static const ConstString Class_name("Class");

if (name == id_name || name == Class_name)
return true;

StringRef name_string_ref = name.GetStringRef();

// The ClangASTSource is not responsible for finding $-names.
if (name_string_ref.empty() ||
(ignore_all_dollar_names && name_string_ref.startswith("$")) ||
name_string_ref.startswith("_$"))
return true;

return false;
}

void ClangASTSource::FindExternalVisibleDecls(
NameSearchContext &context, lldb::ModuleSP module_sp,
CompilerDeclContext &namespace_decl, unsigned int current_id) {
Expand All @@ -633,20 +652,7 @@ void ClangASTSource::FindExternalVisibleDecls(
SymbolContextList sc_list;

const ConstString name(context.m_decl_name.getAsString().c_str());

const char *name_unique_cstr = name.GetCString();

static ConstString id_name("id");
static ConstString Class_name("Class");

if (name == id_name || name == Class_name)
return;

if (name_unique_cstr == NULL)
return;

// The ClangASTSource is not responsible for finding $-names.
if (name_unique_cstr[0] == '$')
if (IgnoreName(name, true))
return;

if (module_sp && namespace_decl) {
Expand Down
16 changes: 16 additions & 0 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
Expand Up @@ -376,6 +376,22 @@ class ClangASTSource : public ClangExternalASTSourceCommon,
//------------------------------------------------------------------
CompilerType GuardedCopyType(const CompilerType &src_type);


//------------------------------------------------------------------
/// Returns true if a name should be ignored by name lookup.
///
/// @param[in] name
/// The name to be considered.
///
/// @param[in] ignore_all_dollar_nmmes
/// True if $-names of all sorts should be ignored.
///
/// @return
/// True if the name is one of a class of names that are ignored by
/// global lookup for performance reasons.
//------------------------------------------------------------------
bool IgnoreName(const ConstString name, bool ignore_all_dollar_names);

friend struct NameSearchContext;

bool m_import_in_progress;
Expand Down
Expand Up @@ -739,16 +739,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
SymbolContextList sc_list;

const ConstString name(context.m_decl_name.getAsString().c_str());

const char *name_unique_cstr = name.GetCString();

if (name_unique_cstr == NULL)
return;

static ConstString id_name("id");
static ConstString Class_name("Class");

if (name == id_name || name == Class_name)
if (IgnoreName(name, false))
return;

// Only look for functions by name out in our symbols if the function
Expand Down Expand Up @@ -809,7 +800,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
} while (0);
}

if (name_unique_cstr[0] == '$' && !namespace_decl) {
if (name.GetCString()[0] == '$' && !namespace_decl) {
static ConstString g_lldb_class_name("$__lldb_class");

if (name == g_lldb_class_name) {
Expand Down Expand Up @@ -1041,7 +1032,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
if (ast) {
clang::NamespaceDecl *namespace_decl =
ClangASTContext::GetUniqueNamespaceDeclaration(
m_ast_context, name_unique_cstr, nullptr);
m_ast_context, name.GetCString(), nullptr);
if (namespace_decl) {
context.AddNamedDecl(namespace_decl);
clang::DeclContext *clang_decl_ctx =
Expand All @@ -1056,7 +1047,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}

// any other $__lldb names should be weeded out now
if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1))
if (name.GetStringRef().startswith("$__lldb"))
return;

ExpressionVariableSP pvar_sp(
Expand Down
Expand Up @@ -811,85 +811,43 @@ UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) {

int len = 0;
if (m_has_object_getClass) {
len = ::snprintf(check_function_code, sizeof(check_function_code),
"extern \"C\" void *gdb_object_getClass(void *); "
" \n"
"extern \"C\" int printf(const char *format, ...); "
" \n"
"extern \"C\" void "
" \n"
"%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
" \n"
"{ "
" \n"
" if ($__lldb_arg_obj == (void *)0) "
" \n"
" return; // nil is ok "
" \n"
" if (!gdb_object_getClass($__lldb_arg_obj)) "
" \n"
" *((volatile int *)0) = 'ocgc'; "
" \n"
" else if ($__lldb_arg_selector != (void *)0) "
" \n"
" { "
" \n"
" signed char responds = (signed char) [(id) "
"$__lldb_arg_obj \n"
" "
"respondsToSelector: \n"
" (struct "
"objc_selector *) $__lldb_arg_selector]; \n"
" if (responds == (signed char) 0) "
" \n"
" *((volatile int *)0) = 'ocgc'; "
" \n"
" } "
" \n"
"} "
" \n",
name);
len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
extern "C" void *gdb_object_getClass(void *);
extern "C" int printf(const char *format, ...);
extern "C" void
%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
if ($__lldb_arg_obj == (void *)0)
return; // nil is ok
if (!gdb_object_getClass($__lldb_arg_obj)) {
*((volatile int *)0) = 'ocgc';
} else if ($__lldb_arg_selector != (void *)0) {
signed char $responds = (signed char)
[(id)$__lldb_arg_obj respondsToSelector:
(void *) $__lldb_arg_selector];
if ($responds == (signed char) 0)
*((volatile int *)0) = 'ocgc';
}
})", name);
} else {
len = ::snprintf(check_function_code, sizeof(check_function_code),
"extern \"C\" void *gdb_class_getClass(void *); "
" \n"
"extern \"C\" int printf(const char *format, ...); "
" \n"
"extern \"C\" void "
" \n"
"%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
" \n"
"{ "
" \n"
" if ($__lldb_arg_obj == (void *)0) "
" \n"
" return; // nil is ok "
" \n"
" void **$isa_ptr = (void **)$__lldb_arg_obj; "
" \n"
" if (*$isa_ptr == (void *)0 || "
"!gdb_class_getClass(*$isa_ptr)) \n"
" *((volatile int *)0) = 'ocgc'; "
" \n"
" else if ($__lldb_arg_selector != (void *)0) "
" \n"
" { "
" \n"
" signed char responds = (signed char) [(id) "
"$__lldb_arg_obj \n"
" "
"respondsToSelector: \n"
" (struct "
"objc_selector *) $__lldb_arg_selector]; \n"
" if (responds == (signed char) 0) "
" \n"
" *((volatile int *)0) = 'ocgc'; "
" \n"
" } "
" \n"
"} "
" \n",
name);
len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
extern "C" void *gdb_class_getClass(void *);
extern "C" int printf(const char *format, ...);
extern "C" void
%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
if ($__lldb_arg_obj == (void *)0)
return; // nil is ok
void **$isa_ptr = (void **)$__lldb_arg_obj;
if (*$isa_ptr == (void *)0 ||
!gdb_class_getClass(*$isa_ptr))
*((volatile int *)0) = 'ocgc';
else if ($__lldb_arg_selector != (void *)0) {
signed char $responds = (signed char)
[(id)$__lldb_arg_obj respondsToSelector:
(void *) $__lldb_arg_selector];
if ($responds == (signed char) 0)
*((volatile int *)0) = 'ocgc';
}
})", name);
}

assert(len < (int)sizeof(check_function_code));
Expand Down

0 comments on commit 1b3c43b

Please sign in to comment.