Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright (c) 2010 Google Inc. | 1 // Copyright (c) 2010 Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 15 matching lines...) Expand all Loading... | |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 // stackwalker_arm.cc: arm-specific stackwalker. | 30 // stackwalker_arm.cc: arm-specific stackwalker. |
31 // | 31 // |
32 // See stackwalker_arm.h for documentation. | 32 // See stackwalker_arm.h for documentation. |
33 // | 33 // |
34 // Author: Mark Mentovai, Ted Mielczarek, Jim Blandy | 34 // Author: Mark Mentovai, Ted Mielczarek, Jim Blandy |
35 | 35 |
36 | |
37 #include "google_breakpad/processor/call_stack.h" | 36 #include "google_breakpad/processor/call_stack.h" |
38 #include "google_breakpad/processor/memory_region.h" | 37 #include "google_breakpad/processor/memory_region.h" |
39 #include "google_breakpad/processor/source_line_resolver_interface.h" | 38 #include "google_breakpad/processor/source_line_resolver_interface.h" |
40 #include "google_breakpad/processor/stack_frame_cpu.h" | 39 #include "google_breakpad/processor/stack_frame_cpu.h" |
41 #include "processor/cfi_frame_info.h" | 40 #include "processor/cfi_frame_info.h" |
42 #include "processor/logging.h" | 41 #include "processor/logging.h" |
43 #include "processor/scoped_ptr.h" | 42 #include "processor/scoped_ptr.h" |
44 #include "processor/stackwalker_arm.h" | 43 #include "processor/stackwalker_arm.h" |
45 | 44 |
46 namespace google_breakpad { | 45 namespace google_breakpad { |
47 | 46 |
48 | 47 |
49 StackwalkerARM::StackwalkerARM(const SystemInfo *system_info, | 48 StackwalkerARM::StackwalkerARM(const SystemInfo *system_info, |
50 const MDRawContextARM *context, | 49 const MDRawContextARM *context, |
50 int fp_register, | |
51 MemoryRegion *memory, | 51 MemoryRegion *memory, |
52 const CodeModules *modules, | 52 const CodeModules *modules, |
53 SymbolSupplier *supplier, | 53 SymbolSupplier *supplier, |
54 SourceLineResolverInterface *resolver) | 54 SourceLineResolverInterface *resolver) |
55 : Stackwalker(system_info, memory, modules, supplier, resolver), | 55 : Stackwalker(system_info, memory, modules, supplier, resolver), |
56 context_(context), | 56 context_(context), fp_register_(fp_register), |
57 context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { } | 57 context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { } |
58 | 58 |
59 | 59 |
60 StackFrame* StackwalkerARM::GetContextFrame() { | 60 StackFrame* StackwalkerARM::GetContextFrame() { |
61 if (!context_ || !memory_) { | 61 if (!context_ || !memory_) { |
62 BPLOG(ERROR) << "Can't get context frame without context or memory"; | 62 BPLOG(ERROR) << "Can't get context frame without context or memory"; |
63 return NULL; | 63 return NULL; |
64 } | 64 } |
65 | 65 |
66 StackFrameARM *frame = new StackFrameARM(); | 66 StackFrameARM *frame = new StackFrameARM(); |
67 | 67 |
68 // The instruction pointer is stored directly in a register (r15), so pull it | 68 // The instruction pointer is stored directly in a register (r15), so pull it |
69 // straight out of the CPU context structure. | 69 // straight out of the CPU context structure. |
70 frame->context = *context_; | 70 frame->context = *context_; |
71 frame->context_validity = context_frame_validity_; | 71 frame->context_validity = context_frame_validity_; |
72 frame->trust = StackFrame::FRAME_TRUST_CONTEXT; | 72 frame->trust = StackFrame::FRAME_TRUST_CONTEXT; |
73 frame->instruction = frame->context.iregs[15]; | 73 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC]; |
74 | 74 |
75 return frame; | 75 return frame; |
76 } | 76 } |
77 | 77 |
78 StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( | 78 StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( |
79 const vector<StackFrame *> &frames, | 79 const vector<StackFrame *> &frames, |
80 CFIFrameInfo *cfi_frame_info) { | 80 CFIFrameInfo *cfi_frame_info) { |
81 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); | 81 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); |
82 | 82 |
83 static const char *register_names[] = { | 83 static const char *register_names[] = { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 | 147 |
148 frame->trust = StackFrame::FRAME_TRUST_CFI; | 148 frame->trust = StackFrame::FRAME_TRUST_CFI; |
149 return frame.release(); | 149 return frame.release(); |
150 } | 150 } |
151 | 151 |
152 StackFrameARM *StackwalkerARM::GetCallerByStackScan( | 152 StackFrameARM *StackwalkerARM::GetCallerByStackScan( |
153 const vector<StackFrame *> &frames) { | 153 const vector<StackFrame *> &frames) { |
154 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); | 154 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); |
155 u_int32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]; | 155 u_int32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]; |
156 u_int32_t caller_sp, caller_pc; | 156 u_int32_t caller_sp, caller_pc; |
157 | 157 |
158 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc)) { | 158 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc)) { |
159 // No plausible return address was found. | 159 // No plausible return address was found. |
160 return NULL; | 160 return NULL; |
161 } | 161 } |
162 | 162 |
163 // ScanForReturnAddress found a reasonable return address. Advance | 163 // ScanForReturnAddress found a reasonable return address. Advance |
164 // %sp to the location above the one where the return address was | 164 // %sp to the location above the one where the return address was |
165 // found. | 165 // found. |
166 caller_sp += 4; | 166 caller_sp += 4; |
167 | 167 |
168 // Create a new stack frame (ownership will be transferred to the caller) | 168 // Create a new stack frame (ownership will be transferred to the caller) |
169 // and fill it in. | 169 // and fill it in. |
170 StackFrameARM *frame = new StackFrameARM(); | 170 StackFrameARM *frame = new StackFrameARM(); |
171 | 171 |
172 frame->trust = StackFrame::FRAME_TRUST_SCAN; | 172 frame->trust = StackFrame::FRAME_TRUST_SCAN; |
173 frame->context = last_frame->context; | 173 frame->context = last_frame->context; |
174 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = caller_pc; | 174 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = caller_pc; |
175 frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp; | 175 frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp; |
176 frame->context_validity = StackFrameARM::CONTEXT_VALID_PC | | 176 frame->context_validity = StackFrameARM::CONTEXT_VALID_PC | |
177 StackFrameARM::CONTEXT_VALID_SP; | 177 StackFrameARM::CONTEXT_VALID_SP; |
178 | 178 |
179 return frame; | 179 return frame; |
180 } | 180 } |
181 | 181 |
182 StackFrameARM *StackwalkerARM::GetCallerByFramePointer( | |
183 const vector<StackFrame *> &frames) { | |
184 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); | |
185 | |
186 if (last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR] == 0) { | |
187 StackFrameARM *frame = new StackFrameARM(); | |
Mark Mentovai
2011/10/14 16:34:31
This is what you encounter at the end of a walk, r
| |
188 frame->trust = StackFrame::FRAME_TRUST_FP; | |
189 frame->context = last_frame->context; | |
190 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = 0; | |
191 return frame; | |
192 } | |
193 | |
194 u_int32_t last_fp = last_frame->context.iregs[fp_register_]; | |
195 u_int32_t caller_fp; | |
196 if (!memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { | |
197 BPLOG(ERROR) << "Unable to read caller_fp from last_fp"; | |
198 return NULL; | |
199 } | |
200 | |
201 u_int32_t caller_lr; | |
Mark Mentovai
2011/10/14 16:34:31
Don’t declare this ’til you use it (below), but I’
| |
202 if (caller_fp == 0) { | |
203 // This is the last frame. We do not care about anything but giving back a | |
204 // correct pc and lr. | |
205 StackFrameARM *frame = new StackFrameARM(); | |
206 frame->trust = StackFrame::FRAME_TRUST_FP; | |
207 frame->context = last_frame->context; | |
208 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = | |
209 last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR]; | |
210 frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = 0; | |
211 frame->context_validity = StackFrameARM::CONTEXT_VALID_PC; | |
212 return frame; | |
213 } | |
214 | |
215 if (!memory_->GetMemoryAtAddress(caller_fp + 4, &caller_lr)) { | |
Mark Mentovai
2011/10/14 16:34:31
Is this right?
In the context frame, we take the
qsr
2011/10/17 12:30:36
Done.
| |
216 BPLOG(ERROR) << "Unable to read caller_lr from caller_fp"; | |
217 return NULL; | |
218 } | |
219 | |
220 u_int32_t caller_sp = caller_fp + 8; | |
221 | |
222 // Create a new stack frame (ownership will be transferred to the caller) | |
223 // and fill it in. | |
224 StackFrameARM *frame = new StackFrameARM(); | |
225 | |
226 frame->trust = StackFrame::FRAME_TRUST_FP; | |
227 frame->context = last_frame->context; | |
228 frame->context.iregs[fp_register_] = caller_fp; | |
229 frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp; | |
230 frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = | |
231 last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR]; | |
232 frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = caller_lr; | |
233 frame->context_validity = StackFrameARM::CONTEXT_VALID_PC | | |
234 StackFrameARM::CONTEXT_VALID_LR | | |
235 StackFrameARM::CONTEXT_VALID_SP; | |
Mark Mentovai
2011/10/14 16:34:31
FP is valid too, right? For all of these, actually
qsr
2011/10/17 07:28:28
Yes, but setting it breaks the code, because the C
qsr
2011/10/17 12:30:36
Done.
| |
236 return frame; | |
237 } | |
238 | |
182 StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) { | 239 StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) { |
183 if (!memory_ || !stack) { | 240 if (!memory_ || !stack) { |
184 BPLOG(ERROR) << "Can't get caller frame without memory or stack"; | 241 BPLOG(ERROR) << "Can't get caller frame without memory or stack"; |
185 return NULL; | 242 return NULL; |
186 } | 243 } |
187 | 244 |
188 const vector<StackFrame *> &frames = *stack->frames(); | 245 const vector<StackFrame *> &frames = *stack->frames(); |
189 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); | 246 StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); |
190 scoped_ptr<StackFrameARM> frame; | 247 scoped_ptr<StackFrameARM> frame; |
191 | 248 |
192 // See if there is DWARF call frame information covering this address. | 249 // See if there is DWARF call frame information covering this address. |
193 scoped_ptr<CFIFrameInfo> cfi_frame_info( | 250 scoped_ptr<CFIFrameInfo> cfi_frame_info( |
194 resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL); | 251 resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL); |
195 if (cfi_frame_info.get()) | 252 if (cfi_frame_info.get()) |
196 frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); | 253 frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); |
197 | 254 |
198 // If CFI failed, or there wasn't CFI available, fall back | 255 // If CFI failed, or there wasn't CFI available, fall back |
199 // to stack scanning. | 256 // to stack scanning. |
200 if (!frame.get()) { | 257 if (!frame.get()) { |
201 frame.reset(GetCallerByStackScan(frames)); | 258 if (fp_register_ >= 0) |
259 frame.reset(GetCallerByFramePointer(frames)); | |
260 else | |
261 frame.reset(GetCallerByStackScan(frames)); | |
jimb
2011/10/14 17:17:23
If we have an fp_register, but GetCallerByFramePoi
qsr
2011/10/17 12:30:36
Done.
| |
202 } | 262 } |
203 | 263 |
204 // If nothing worked, tell the caller. | 264 // If nothing worked, tell the caller. |
205 if (!frame.get()) | 265 if (!frame.get()) |
206 return NULL; | 266 return NULL; |
207 | 267 |
208 | 268 |
209 // An instruction address of zero marks the end of the stack. | 269 // An instruction address of zero marks the end of the stack. |
210 if (frame->context.iregs[MD_CONTEXT_ARM_REG_PC] == 0) | 270 if (frame->context.iregs[MD_CONTEXT_ARM_REG_PC] == 0) |
211 return NULL; | 271 return NULL; |
212 | 272 |
213 // If the new stack pointer is at a lower address than the old, then | 273 // If the new stack pointer is at a lower address than the old, then |
214 // that's clearly incorrect. Treat this as end-of-stack to enforce | 274 // that's clearly incorrect. Treat this as end-of-stack to enforce |
215 // progress and avoid infinite loops. | 275 // progress and avoid infinite loops. |
216 if (frame->context.iregs[MD_CONTEXT_ARM_REG_SP] | 276 if (frame->context.iregs[MD_CONTEXT_ARM_REG_SP] |
217 < last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]) | 277 < last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]) |
218 return NULL; | 278 return NULL; |
219 | 279 |
220 // The new frame's context's PC is the return address, which is one | 280 // The new frame's context's PC is the return address, which is one |
221 // instruction past the instruction that caused us to arrive at the | 281 // instruction past the instruction that caused us to arrive at the |
222 // callee. Set new_frame->instruction to one less than the PC. This won't | 282 // callee. Set new_frame->instruction to one less than the PC. This won't |
223 // reference the beginning of the call instruction, but it's at least | 283 // reference the beginning of the call instruction, but it's at least |
224 // within it, which is sufficient to get the source line information to | 284 // within it, which is sufficient to get the source line information to |
225 // match up with the line that contains the function call. Callers that | 285 // match up with the line that contains the function call. Callers that |
226 // require the exact return address value may access | 286 // require the exact return address value may access |
227 // frame->context.iregs[MD_CONTEXT_ARM_REG_PC]. | 287 // frame->context.iregs[MD_CONTEXT_ARM_REG_PC]. |
228 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 1; | 288 frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 2; |
229 | 289 |
230 return frame.release(); | 290 return frame.release(); |
231 } | 291 } |
232 | 292 |
233 | 293 |
234 } // namespace google_breakpad | 294 } // namespace google_breakpad |
OLD | NEW |