diff options
-rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolverName.h | 8 | ||||
-rw-r--r-- | lldb/include/lldb/lldb-enumerations.h | 20 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 2 | ||||
-rw-r--r-- | lldb/scripts/build-llvm.pl | 2 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverName.cpp | 95 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.cpp | 25 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 34 |
7 files changed, 153 insertions, 33 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h index 4cfd2458dd6..9d5e68ecc07 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h @@ -63,6 +63,14 @@ public: protected: ConstString m_func_name; + // "m_basename_filter" is used to filter results after searching for + // "m_func_name" first. This is used when we are asked to set a breakpoint + // at "foo::bar::baz" (C++ function in namespace or in a class). For + // "foo::bar::baz" we will place "baz" into m_func_name and search for all + // matching basename and methods that match "baz", then we will filter the + // results by checking if the demangled name contains "m_basename_filter" + // which would be set to "foo::bar::baz". + std::string m_basename_filter; uint32_t m_func_name_type_mask; // See FunctionNameType ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class. RegularExpression m_regex; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index c3f7f39a2a7..3f5553eab74 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -412,15 +412,17 @@ typedef enum ArchitectureType typedef enum FunctionNameType { eFunctionNameTypeNone = 0u, - eFunctionNameTypeFull = (1u << 1),// The function name. - // For C this is the same as just the name of the function - // For C++ this is the demangled version of the mangled name. - // For ObjC this is the full function signature with the + or - // - and the square brackets and the class and selector - eFunctionNameTypeBase = (1u << 2),// The function name only, no namespaces or arguments and no class - // methods or selectors will be searched. - eFunctionNameTypeMethod = (1u << 3),// Find function by method name (C++) with no namespace or arguments - eFunctionNameTypeSelector = (1u << 4) // Find function by selector name (ObjC) names + eFunctionNameTypeAuto = (1u << 1), // Automatically figure out which FunctionNameType + // bits to set based on the function name. + eFunctionNameTypeFull = (1u << 2), // The function name. + // For C this is the same as just the name of the function + // For C++ this is the demangled version of the mangled name. + // For ObjC this is the full function signature with the + or + // - and the square brackets and the class and selector + eFunctionNameTypeBase = (1u << 3), // The function name only, no namespaces or arguments and no class + // methods or selectors will be searched. + eFunctionNameTypeMethod = (1u << 4), // Find function by method name (C++) with no namespace or arguments + eFunctionNameTypeSelector = (1u << 5), // Find function by selector name (ObjC) names } FunctionNameType; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 0d7a9e58bd3..516bb859d2f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -2964,7 +2964,7 @@ "$(LLVM_BUILD_DIR)", ); LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; - LLVM_CONFIGURATION = Release; + LLVM_CONFIGURATION = "Debug+Asserts"; OTHER_CFLAGS = ( "-DFOR_DYLD=0", "-DSUPPORT_REMOTE_UNWINDING", diff --git a/lldb/scripts/build-llvm.pl b/lldb/scripts/build-llvm.pl index 86b3d9f4984..a9db7648b68 100644 --- a/lldb/scripts/build-llvm.pl +++ b/lldb/scripts/build-llvm.pl @@ -91,7 +91,7 @@ if (-l $llvm_dstroot) # LLVM in the "lldb" root is a symlink which indicates we are using a # standard LLVM build directory where everything is built into the # same folder - create_single_llvm_arhive_for_arch ($llvm_dstroot, 0); + create_single_llvm_arhive_for_arch ($llvm_dstroot, 1); my $llvm_dstroot_archive = "$llvm_dstroot/$llvm_clang_basename"; push @llvm_clang_slices, $llvm_dstroot_archive; create_dstroot_file ($llvm_clang_basename, $llvm_clang_dirname, \@llvm_clang_slices, $llvm_clang_basename); diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index f25910de565..5431db0c230 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -29,12 +29,54 @@ BreakpointResolverName::BreakpointResolverName Breakpoint::MatchType type ) : BreakpointResolver (bkpt), - m_func_name (func_name), + m_func_name (), + m_basename_filter (), m_func_name_type_mask (func_name_type_mask), m_class_name (), m_regex (), m_match_type (type) { + if (func_name_type_mask == eFunctionNameTypeAuto) + { + if ((::strchr (func_name, '(' ) != NULL) || + (::strstr (func_name, "-[") == func_name) || + (::strstr (func_name, "+[") == func_name)) + { + // We have a name that contains an open parens, or starts with + // "+[" or "-[", so this looks like a complete function prototype + m_func_name_type_mask = eFunctionNameTypeFull; + } + else + { + // We don't have a full function name, but we might have a partial + // function basename with namespaces or classes + if (::strstr (func_name, "::") != NULL) + { + // Keep the full name in "m_basename_filter" + m_basename_filter = func_name; + // Now set "m_func_name" to just the function basename + m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2); + // We have a name with a double colon which means we have a + // function name that is a C++ method or a function in a C++ + // namespace + m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod; + } + else if (::strstr (func_name, ":") != NULL) + { + // Single colon => selector + m_func_name_type_mask = eFunctionNameTypeSelector; + } + else + { + // just a basename by default + m_func_name_type_mask = eFunctionNameTypeBase; + } + } + } + + if (!m_func_name) + m_func_name.SetCString(func_name); + if (m_match_type == Breakpoint::Regexp) { if (!m_regex.Compile (m_func_name.AsCString())) @@ -137,6 +179,53 @@ BreakpointResolverName::SearchCallback break; } + if (!m_basename_filter.empty()) + { + // Filter out any matches whose names don't contain the basename filter + const char *basename_filter = m_basename_filter.c_str(); + if (func_list.GetSize()) + { + bool remove = false; + for (i = 0; i < func_list.GetSize(); remove = false) + { + if (func_list.GetContextAtIndex(i, sc) == false) + remove = true; + else if (sc.function == NULL) + remove = true; + else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL) + remove = true; + + if (remove) + { + func_list.RemoveContextAtIndex(i); + continue; + } + i++; + } + } + + if (sym_list.GetSize()) + { + bool remove = false; + for (i = 0; i < sym_list.GetSize(); remove = false) + { + if (sym_list.GetContextAtIndex(i, sc) == false) + remove = true; + else if (sc.symbol == NULL) + remove = true; + else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL) + remove = true; + + if (remove) + { + sym_list.RemoveContextAtIndex(i); + continue; + } + i++; + } + } + } + // Remove any duplicates between the funcion list and the symbol list if (func_list.GetSize()) { @@ -242,8 +331,10 @@ BreakpointResolverName::GetDescription (Stream *s) { if (m_match_type == Breakpoint::Regexp) s->Printf("regex = '%s'", m_regex.GetText()); - else + else if (m_basename_filter.empty()) s->Printf("name = '%s'", m_func_name.AsCString()); + else + s->Printf("name = '%s'", m_basename_filter.c_str()); } void diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index e7cf0a8bb95..a9d1615dfca 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -104,7 +104,7 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = "Set the breakpoint by address, at the specified address."}, { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, - "Set the breakpoint by function name - for C++ this means namespaces and arguments will be ignored." }, + "Set the breakpoint by function name." }, { LLDB_OPT_SET_4, true, "fullname", 'F', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguemnts, and " @@ -119,6 +119,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_7, true, "func-regex", 'r', required_argument, NULL, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." }, + { LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, + "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored)." }, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -157,11 +160,16 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, cons m_line_num = Args::StringToUInt32 (option_arg, 0); break; - case 'n': + case 'b': m_func_name = option_arg; m_func_name_type_mask |= eFunctionNameTypeBase; break; + case 'n': + m_func_name = option_arg; + m_func_name_type_mask |= eFunctionNameTypeAuto; + break; + case 'F': m_func_name = option_arg; m_func_name_type_mask |= eFunctionNameTypeFull; @@ -391,17 +399,8 @@ CommandObjectBreakpointSet::Execute uint32_t name_type_mask = m_options.m_func_name_type_mask; if (name_type_mask == 0) - { - - if (m_options.m_func_name.find('(') != std::string::npos || - m_options.m_func_name.find("-[") == 0 || - m_options.m_func_name.find("+[") == 0) - name_type_mask |= eFunctionNameTypeFull; - else - name_type_mask |= eFunctionNameTypeBase; - } - - + name_type_mask = eFunctionNameTypeAuto; + if (use_module) { for (int i = 0; i < num_modules; ++i) diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index e741cc099ee..ed16d0c5685 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -3099,7 +3099,22 @@ ClangASTContext::CompleteTagDeclarationDefinition (clang_type_t clang_type) unsigned NumPositiveBits = 1; unsigned NumNegativeBits = 0; - enum_decl->completeDefinition(enum_decl->getIntegerType(), enum_decl->getIntegerType(), NumPositiveBits, NumNegativeBits); + ASTContext *ast_context = getASTContext(); + + QualType promotion_qual_type; + // If the enum integer type is less than an integer in bit width, + // then we must promote it to an integer size. + if (ast_context->getTypeSize(enum_decl->getIntegerType()) < ast_context->getTypeSize(ast_context->IntTy)) + { + if (enum_decl->getIntegerType()->isSignedIntegerType()) + promotion_qual_type = ast_context->IntTy; + else + promotion_qual_type = ast_context->UnsignedIntTy; + } + else + promotion_qual_type = enum_decl->getIntegerType(); + + enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); return true; } } @@ -3117,12 +3132,17 @@ ClangASTContext::CreateEnumerationType (const Declaration &decl, const char *nam // like maybe filling in the SourceLocation with it... ASTContext *ast_context = getASTContext(); assert (ast_context != NULL); - EnumDecl *enum_decl = EnumDecl::Create(*ast_context, - ast_context->getTranslationUnitDecl(), - SourceLocation(), - name && name[0] ? &ast_context->Idents.get(name) : NULL, - SourceLocation(), - NULL); + + // TODO: ask about these... +// const bool IsScoped = false; +// const bool IsFixed = false; + + EnumDecl *enum_decl = EnumDecl::Create (*ast_context, + ast_context->getTranslationUnitDecl(), + SourceLocation(), + name && name[0] ? &ast_context->Idents.get(name) : NULL, + SourceLocation(), + NULL); //IsScoped, IsFixed); if (enum_decl) { // TODO: check if we should be setting the promotion type too? |