|
8 | 8 |
|
9 | 9 | #include "lldb/Target/ThreadPlanShouldStopHere.h" |
10 | 10 | #include "lldb/Symbol/Symbol.h" |
| 11 | +#include "lldb/Target/LanguageRuntime.h" |
11 | 12 | #include "lldb/Target/RegisterContext.h" |
12 | 13 | #include "lldb/Target/Thread.h" |
13 | 14 | #include "lldb/Utility/LLDBLog.h" |
@@ -76,6 +77,19 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( |
76 | 77 | } |
77 | 78 | } |
78 | 79 |
|
| 80 | + // Check whether the frame we are in is a language runtime thunk, only for |
| 81 | + // step out: |
| 82 | + if (operation == eFrameCompareOlder) { |
| 83 | + if (Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol) { |
| 84 | + ProcessSP process_sp(current_plan->GetThread().GetProcess()); |
| 85 | + for (auto *runtime : process_sp->GetLanguageRuntimes()) { |
| 86 | + if (runtime->IsSymbolARuntimeThunk(*symbol)) { |
| 87 | + should_stop_here = false; |
| 88 | + break; |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + } |
79 | 93 | // Always avoid code with line number 0. |
80 | 94 | // FIXME: At present the ShouldStop and the StepFromHere calculate this |
81 | 95 | // independently. If this ever |
@@ -109,18 +123,35 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( |
109 | 123 |
|
110 | 124 | if (sc.line_entry.line == 0) { |
111 | 125 | AddressRange range = sc.line_entry.range; |
112 | | - |
113 | | - // If the whole function is marked line 0 just step out, that's easier & |
114 | | - // faster than continuing to step through it. |
115 | 126 | bool just_step_out = false; |
116 | | - if (sc.symbol && sc.symbol->ValueIsAddress()) { |
117 | | - Address symbol_end = sc.symbol->GetAddress(); |
118 | | - symbol_end.Slide(sc.symbol->GetByteSize() - 1); |
119 | | - if (range.ContainsFileAddress(sc.symbol->GetAddress()) && |
120 | | - range.ContainsFileAddress(symbol_end)) { |
121 | | - LLDB_LOGF(log, "Stopped in a function with only line 0 lines, just " |
122 | | - "stepping out."); |
123 | | - just_step_out = true; |
| 127 | + if (sc.symbol) { |
| 128 | + ProcessSP process_sp(current_plan->GetThread().GetProcess()); |
| 129 | + |
| 130 | + // If this is a runtime thunk, step through it, rather than stepping out |
| 131 | + // because it's marked line 0. |
| 132 | + bool is_thunk = false; |
| 133 | + for (auto *runtime : process_sp->GetLanguageRuntimes()) { |
| 134 | + if (runtime->IsSymbolARuntimeThunk(*sc.symbol)) { |
| 135 | + LLDB_LOGF(log, "In runtime thunk %s - stepping out.", |
| 136 | + sc.symbol->GetName().GetCString()); |
| 137 | + is_thunk = true; |
| 138 | + break; |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + // If the whole function is marked line 0 just step out, that's easier & |
| 143 | + // faster than continuing to step through it. |
| 144 | + // FIXME: This assumes that the function is a single line range. It could |
| 145 | + // be a series of contiguous line 0 ranges. Check for that too. |
| 146 | + if (!is_thunk && sc.symbol->ValueIsAddress()) { |
| 147 | + Address symbol_end = sc.symbol->GetAddress(); |
| 148 | + symbol_end.Slide(sc.symbol->GetByteSize() - 1); |
| 149 | + if (range.ContainsFileAddress(sc.symbol->GetAddress()) && |
| 150 | + range.ContainsFileAddress(symbol_end)) { |
| 151 | + LLDB_LOGF(log, "Stopped in a function with only line 0 lines, just " |
| 152 | + "stepping out."); |
| 153 | + just_step_out = true; |
| 154 | + } |
124 | 155 | } |
125 | 156 | } |
126 | 157 | if (!just_step_out) { |
|
0 commit comments