Author: jingham Date: Tue Feb 9 21:25:24 2016 New Revision: 260352 URL: http://llvm.org/viewvc/llvm-project?rev=260352&view=rev Log: This is an idea to make "thread step-in --target" work for the common case where you have:
1 -> foo (bar(), 2 baz(), 3 lala()); 4 You are sitting on line 1, and want to step into foo, but not bar, baz & lala. Unfortunately there are line table entries for lines 1-3, and lldb doesn't know anything about the nesting of statement in these lines. So we'll have to use the user's intelligence... This patch adds: (lldb) thread step-in -t foo --end-line 4 That tells lldb to keep stepping in till line 4, but stop if you step into foo. I think I would remember to use this when faced with some of the long gnarly call sequences in lldb. But there might be ways I haven't thought of to make it more convenient. Jason suggests having "end" as a special token for --end-line which just means keep going to the end of the function, I really want to get into this thing... There should be an SB API and tests, which will come if this seems useful. Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=260352&r1=260351&r2=260352&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectThread.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectThread.cpp Tue Feb 9 21:25:24 2016 @@ -386,7 +386,7 @@ public: { m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_step_count == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); + error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg); break; } break; @@ -403,6 +403,16 @@ public: } break; + case 'e': + { + uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (tmp_end_line == UINT32_MAX) + error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg); + else + m_end_line = tmp_end_line; + break; + } + break; case 'r': { m_avoid_regexp.clear(); @@ -441,6 +451,7 @@ public: m_step_in_target.clear(); m_class_name.clear(); m_step_count = 1; + m_end_line = LLDB_INVALID_LINE_NUMBER; } const OptionDefinition* @@ -461,6 +472,7 @@ public: std::string m_step_in_target; std::string m_class_name; uint32_t m_step_count; + uint32_t m_end_line; }; CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, @@ -559,6 +571,14 @@ protected: } } + if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER + && m_step_type != eStepTypeInto) + { + result.AppendErrorWithFormat("end line option is only valid for step into"); + result.SetStatus(eReturnStatusFailed); + return false; + } + const bool abort_other_plans = false; const lldb::RunMode stop_other_threads = m_options.m_run_mode; @@ -586,8 +606,70 @@ protected: if (frame->HasDebugInformation ()) { + AddressRange range = frame->GetSymbolContext(eSymbolContextEverything).line_entry.range; + if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) + { + SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); + if (sc.line_entry.line > m_options.m_end_line) + { + result.AppendErrorWithFormat("end line option %d must be after the current line: %d", + m_options.m_end_line, + sc.line_entry.line); + result.SetStatus(eReturnStatusFailed); + return false; + } + + CompileUnit *cu = sc.comp_unit; + uint32_t line_index = 0; + bool found = false; + while (1) + { + LineEntry this_line; + line_index = cu->FindLineEntry(line_index, sc.line_entry.line, nullptr, false, &this_line); + if (line_index == UINT32_MAX) + break; + if (LineEntry::Compare(this_line, sc.line_entry) == 0) + { + found = true; + break; + } + } + LineEntry end_entry; + if (!found) + { + // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit. + result.AppendErrorWithFormat("Can't find the current line entry in the CompUnit - can't process " + "the end-line option"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + line_index = cu->FindLineEntry(line_index, m_options.m_end_line, nullptr, false, &end_entry); + if (line_index == UINT32_MAX) + { + result.AppendErrorWithFormat("could not find a line table entry corresponding " + "to end line number %d", + m_options.m_end_line); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Block *func_block = sc.GetFunctionBlock(); + if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX) + { + result.AppendErrorWithFormat("end line number %d is not contained within the current function.", + m_options.m_end_line); + result.SetStatus(eReturnStatusFailed); + return false; + } + + lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() + - range.GetBaseAddress().GetFileAddress(); + range.SetByteSize(range_size); + } + new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, - frame->GetSymbolContext(eSymbolContextEverything).line_entry, + range, frame->GetSymbolContext(eSymbolContextEverything), m_options.m_step_in_target.c_str(), stop_other_threads, @@ -737,6 +819,7 @@ CommandObjectThreadStepWithTypeAndScope: { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, +{ LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over."}, { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits