diff options
author | Jim Ingham <jingham@apple.com> | 2012-11-06 01:14:52 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2012-11-06 01:14:52 +0000 |
commit | c2a2e13ea585be51d6278aabe35a3fe324954414 (patch) | |
tree | f4452093fcd319aafc2904387a9a06121b25a7c4 | |
parent | f270fa9682d748c1be1aea1993fd8d2408639f4c (diff) | |
download | lldb-c2a2e13ea585be51d6278aabe35a3fe324954414.tar.gz |
Add a workaround to problems with the clang debug info for
inlined subroutine ranges.
<rdar://problem/12588579>
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@167430 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme | 2 | ||||
-rw-r--r-- | source/Target/ThreadPlanStepOverRange.cpp | 95 |
2 files changed, 96 insertions, 1 deletions
diff --git a/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme b/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme index 101410da8..4caf43413 100644 --- a/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme +++ b/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme @@ -84,7 +84,7 @@ <LaunchAction selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" + launchStyle = "1" useCustomWorkingDirectory = "NO" customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach" buildConfiguration = "Debug" diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp index e653e0623..ba21eda95 100644 --- a/source/Target/ThreadPlanStepOverRange.cpp +++ b/source/Target/ThreadPlanStepOverRange.cpp @@ -18,7 +18,9 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -173,6 +175,99 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) // stub, and then it will be straight-forward to step out. new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); } + else + { + // The current clang (at least through 424) doesn't always get the address range for the + // DW_TAG_inlined_subroutines right, so that when you leave the inlined range the line table says + // you are still in the source file of the inlining function. This is bad, because now you are missing + // the stack frame for the function containing the inlining, and if you sensibly do "finish" to get + // out of this function you will instead exit the containing function. + // To work around this, we check whether we are still in the source file we started in, and if not assume + // it is an error, and push a plan to get us out of this line and back to the containing file. + + if (m_addr_context.line_entry.IsValid()) + { + SymbolContext sc; + StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0); + sc = frame_sp->GetSymbolContext (eSymbolContextEverything); + if (sc.line_entry.IsValid()) + { + if (sc.line_entry.file != m_addr_context.line_entry.file + && sc.comp_unit == m_addr_context.comp_unit + && sc.function == m_addr_context.function) + { + // Okay, find the next occurance of this file in the line table: + LineTable *line_table = m_addr_context.comp_unit->GetLineTable(); + if (line_table) + { + Address cur_address = frame_sp->GetFrameCodeAddress(); + uint32_t entry_idx; + LineEntry line_entry; + if (line_table->FindLineEntryByAddress (cur_address, line_entry, &entry_idx)) + { + LineEntry next_line_entry; + bool step_past_remaining_inline = false; + if (entry_idx > 0) + { + // We require the the previous line entry and the current line entry come + // from the same file. + // The other requirement is that the previous line table entry be part of an + // inlined block, we don't want to step past cases where people have inlined + // some code fragment by using #include <source-fragment.c> directly. + LineEntry prev_line_entry; + if (line_table->GetLineEntryAtIndex(entry_idx - 1, prev_line_entry) + && prev_line_entry.file == line_entry.file) + { + SymbolContext prev_sc; + Address prev_address = prev_line_entry.range.GetBaseAddress(); + prev_address.CalculateSymbolContext(&prev_sc); + if (prev_sc.block) + { + Block *inlined_block = prev_sc.block->GetContainingInlinedBlock(); + if (inlined_block) + { + AddressRange inline_range; + inlined_block->GetRangeContainingAddress(prev_address, inline_range); + if (!inline_range.ContainsFileAddress(cur_address)) + { + + step_past_remaining_inline = true; + } + + } + } + } + } + + if (step_past_remaining_inline) + { + uint32_t look_ahead_step = 1; + while (line_table->GetLineEntryAtIndex(entry_idx + look_ahead_step, next_line_entry)) + { + // Make sure we haven't wandered out of the function we started from... + Address next_line_address = next_line_entry.range.GetBaseAddress(); + Function *next_line_function = next_line_address.CalculateSymbolContextFunction(); + if (next_line_function != m_addr_context.function) + break; + + if (next_line_entry.file == m_addr_context.line_entry.file) + { + const bool abort_other_plans = false; + const bool stop_other_threads = false; + new_plan = m_thread.QueueThreadPlanForRunToAddress(abort_other_plans, + next_line_address, + stop_other_threads); + break; + } + look_ahead_step++; + } + } + } + } + } + } + } + } } // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: |