aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2012-11-06 01:14:52 +0000
committerJim Ingham <jingham@apple.com>2012-11-06 01:14:52 +0000
commitc2a2e13ea585be51d6278aabe35a3fe324954414 (patch)
treef4452093fcd319aafc2904387a9a06121b25a7c4
parentf270fa9682d748c1be1aea1993fd8d2408639f4c (diff)
downloadlldb-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.xcscheme2
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp95
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: