Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3)

Side by Side Diff: src/processor/stackwalker_arm.cc

Issue 314001: Use frame pointer to walk ARM stack on iOS. (Closed) Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: '' Created 13 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/processor/stackwalker.cc ('k') | src/processor/stackwalker_arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/processor/stackwalker.cc ('k') | src/processor/stackwalker_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1004:630ec63f810e-tainted