Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

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

Issue 1418453011: [mips64] Support for mips n64 (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Fix accidentally removed lines from Makefile.am Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/processor/stackwalker.cc ('k') | src/processor/stackwalker_mips64_unittest.cc » ('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) 2013 Google Inc. 1 // Copyright (c) 2013 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 #include "processor/windows_frame_info.h" 46 #include "processor/windows_frame_info.h"
47 #include "google_breakpad/common/minidump_cpu_mips.h" 47 #include "google_breakpad/common/minidump_cpu_mips.h"
48 48
49 namespace google_breakpad { 49 namespace google_breakpad {
50 50
51 StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info, 51 StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info,
52 const MDRawContextMIPS* context, 52 const MDRawContextMIPS* context,
53 MemoryRegion* memory, 53 MemoryRegion* memory,
54 const CodeModules* modules, 54 const CodeModules* modules,
55 StackFrameSymbolizer* resolver_helper) 55 StackFrameSymbolizer* resolver_helper)
56 : Stackwalker(system_info, memory, modules, resolver_helper), 56 : Stackwalker(system_info, memory, modules, resolver_helper),
57 context_(context) { 57 context_(context) {
58 if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { 58 if (context_->context_flags & MD_CONTEXT_MIPS64 ) {
59 BPLOG(ERROR) << "Memory out of range for stackwalking: " 59 if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1)
60 << HexString(memory_->GetBase()) 60 > 0xffffffffffffffff) {
61 << "+" 61 BPLOG(ERROR) << "Memory out of range for stackwalking mips64: "
62 << HexString(memory_->GetSize()); 62 << HexString(memory_->GetBase())
63 memory_ = NULL; 63 << "+"
64 << HexString(memory_->GetSize());
65 memory_ = NULL;
66 }
67 } else {
68 if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1) > 0xffffffff) {
69 BPLOG(ERROR) << "Memory out of range for stackwalking mips32: "
70 << HexString(memory_->GetBase())
71 << "+"
72 << HexString(memory_->GetSize());
73 memory_ = NULL;
74 }
64 } 75 }
65 } 76 }
66 77
67 StackFrame* StackwalkerMIPS::GetContextFrame() { 78 StackFrame* StackwalkerMIPS::GetContextFrame() {
68 if (!context_) { 79 if (!context_) {
69 BPLOG(ERROR) << "Can't get context frame without context."; 80 BPLOG(ERROR) << "Can't get context frame without context.";
70 return NULL; 81 return NULL;
71 } 82 }
72 83
73 StackFrameMIPS* frame = new StackFrameMIPS(); 84 StackFrameMIPS* frame = new StackFrameMIPS();
(...skipping 15 matching lines...) Expand all
89 "$s4", "$s5", "$s6", "$s7", "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", 100 "$s4", "$s5", "$s6", "$s7", "$t8", "$t9", "$k0", "$k1", "$gp", "$sp",
90 "$fp", "$ra", NULL 101 "$fp", "$ra", NULL
91 // TODO(gordanac): add float point save registers 102 // TODO(gordanac): add float point save registers
92 }; 103 };
93 104
94 StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( 105 StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo(
95 const vector<StackFrame*>& frames, 106 const vector<StackFrame*>& frames,
96 CFIFrameInfo* cfi_frame_info) { 107 CFIFrameInfo* cfi_frame_info) {
97 StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back()); 108 StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
98 109
99 uint32_t sp = 0, pc = 0; 110 if (context_->context_flags & MD_CONTEXT_MIPS) {
111 uint32_t sp = 0, pc = 0;
100 112
101 // Populate a dictionary with the valid register values in last_frame. 113 // Populate a dictionary with the valid register values in last_frame.
102 CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers; 114 CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
103 // Use the STACK CFI data to recover the caller's register values. 115 // Use the STACK CFI data to recover the caller's register values.
104 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; 116 CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
105 117
106 for (int i = 0; kRegisterNames[i]; ++i) { 118 for (int i = 0; kRegisterNames[i]; ++i) {
107 caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; 119 caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
108 callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; 120 callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
121 }
122
123 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
124 &caller_registers)) {
125 return NULL;
126 }
127
128 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry =
129 caller_registers.find(".cfa");
130
131 if (entry != caller_registers.end()) {
132 sp = entry->second;
133 caller_registers["$sp"] = entry->second;
134 }
135
136 entry = caller_registers.find(".ra");
137 if (entry != caller_registers.end()) {
138 caller_registers["$ra"] = entry->second;
139 pc = entry->second - 2 * sizeof(pc);
140 }
141 caller_registers["$pc"] = pc;
142 // Construct a new stack frame given the values the CFI recovered.
143 scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
144
145 for (int i = 0; kRegisterNames[i]; ++i) {
146 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry =
147 caller_registers.find(kRegisterNames[i]);
148
149 if (caller_entry != caller_registers.end()) {
150 // The value of this register is recovered; fill the context with the
151 // value from caller_registers.
152 frame->context.iregs[i] = caller_entry->second;
153 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
154 } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
155 (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
156 (last_frame->context_validity &
157 StackFrameMIPS::RegisterValidFlag(i))) {
158 // If the STACK CFI data doesn't mention some callee-save register, and
159 // it is valid in the callee, assume the callee has not yet changed it.
160 // Calee-save registers according to the MIPS o32 ABI specification are:
161 // $s0 to $s7
162 // $sp, $s8
163 frame->context.iregs[i] = last_frame->context.iregs[i];
164 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
165 }
166 }
167
168 frame->context.epc = caller_registers["$pc"];
169 frame->instruction = caller_registers["$pc"];
170 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
171
172 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
173 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
174
175 frame->trust = StackFrame::FRAME_TRUST_CFI;
176
177 return frame.release();
178 } else {
179 uint64_t sp = 0, pc = 0;
180
181 // Populate a dictionary with the valid register values in last_frame.
182 CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
183 // Use the STACK CFI data to recover the caller's register values.
184 CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
185
186 for (int i = 0; kRegisterNames[i]; ++i) {
187 caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
188 callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
189 }
190
191 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
192 &caller_registers)) {
193 return NULL;
194 }
195
196 CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator entry =
197 caller_registers.find(".cfa");
198
199 if (entry != caller_registers.end()) {
200 sp = entry->second;
201 caller_registers["$sp"] = entry->second;
202 }
203
204 entry = caller_registers.find(".ra");
205 if (entry != caller_registers.end()) {
206 caller_registers["$ra"] = entry->second;
207 pc = entry->second - 2 * sizeof(pc);
208 }
209 caller_registers["$pc"] = pc;
210 // Construct a new stack frame given the values the CFI recovered.
211 scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
212
213 for (int i = 0; kRegisterNames[i]; ++i) {
214 CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator caller_entry =
215 caller_registers.find(kRegisterNames[i]);
216
217 if (caller_entry != caller_registers.end()) {
218 // The value of this register is recovered; fill the context with the
219 // value from caller_registers.
220 frame->context.iregs[i] = caller_entry->second;
221 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
222 } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
223 (i >= INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
224 (last_frame->context_validity &
225 StackFrameMIPS::RegisterValidFlag(i))) {
226 // If the STACK CFI data doesn't mention some callee-save register, and
227 // it is valid in the callee, assume the callee has not yet changed it.
228 // Calee-save registers according to the MIPS o32 ABI specification are:
229 // $s0 to $s7
230 // $sp, $s8
231 frame->context.iregs[i] = last_frame->context.iregs[i];
232 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
233 }
234 }
235
236 frame->context.epc = caller_registers["$pc"];
237 frame->instruction = caller_registers["$pc"];
238 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
239
240 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
241 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
242
243 frame->trust = StackFrame::FRAME_TRUST_CFI;
244
245 return frame.release();
109 } 246 }
110
111 if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
112 &caller_registers)) {
113 return NULL;
114 }
115
116 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry =
117 caller_registers.find(".cfa");
118
119 if (entry != caller_registers.end()) {
120 sp = entry->second;
121 caller_registers["$sp"] = entry->second;
122 }
123
124 entry = caller_registers.find(".ra");
125 if (entry != caller_registers.end()) {
126 caller_registers["$ra"] = entry->second;
127 pc = entry->second - 2 * sizeof(pc);
128 }
129 caller_registers["$pc"] = pc;
130 // Construct a new stack frame given the values the CFI recovered.
131 scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
132
133 for (int i = 0; kRegisterNames[i]; ++i) {
134 CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry =
135 caller_registers.find(kRegisterNames[i]);
136
137 if (caller_entry != caller_registers.end()) {
138 // The value of this register is recovered; fill the context with the
139 // value from caller_registers.
140 frame->context.iregs[i] = caller_entry->second;
141 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
142 } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
143 (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
144 (last_frame->context_validity &
145 StackFrameMIPS::RegisterValidFlag(i))) {
146 // If the STACK CFI data doesn't mention some callee-save register, and
147 // it is valid in the callee, assume the callee has not yet changed it.
148 // Calee-save registers according to the MIPS o32 ABI specification are:
149 // $s0 to $s7
150 // $sp, $s8
151 frame->context.iregs[i] = last_frame->context.iregs[i];
152 frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
153 }
154 }
155
156 frame->context.epc = caller_registers["$pc"];
157 frame->instruction = caller_registers["$pc"];
158 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
159
160 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
161 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
162
163 frame->trust = StackFrame::FRAME_TRUST_CFI;
164
165 return frame.release();
166 } 247 }
167 248
168 StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack, 249 StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack,
169 bool stack_scan_allowed) { 250 bool stack_scan_allowed) {
170 if (!memory_ || !stack) { 251 if (!memory_ || !stack) {
171 BPLOG(ERROR) << "Can't get caller frame without memory or stack"; 252 BPLOG(ERROR) << "Can't get caller frame without memory or stack";
172 return NULL; 253 return NULL;
173 } 254 }
174 255
175 const vector<StackFrame*>& frames = *stack->frames(); 256 const vector<StackFrame*>& frames = *stack->frames();
(...skipping 21 matching lines...) Expand all
197 return NULL; 278 return NULL;
198 } 279 }
199 280
200 // If the new stack pointer is at a lower address than the old, then 281 // If the new stack pointer is at a lower address than the old, then
201 // that's clearly incorrect. Treat this as end-of-stack to enforce 282 // that's clearly incorrect. Treat this as end-of-stack to enforce
202 // progress and avoid infinite loops. 283 // progress and avoid infinite loops.
203 if (new_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] <= 284 if (new_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] <=
204 last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]) { 285 last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]) {
205 return NULL; 286 return NULL;
206 } 287 }
207 288
208 return new_frame.release(); 289 return new_frame.release();
209 } 290 }
210 291
211 StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( 292 StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan(
212 const vector<StackFrame*>& frames) { 293 const vector<StackFrame*>& frames) {
213 const uint32_t kMaxFrameStackSize = 1024; 294 const uint32_t kMaxFrameStackSize = 1024;
214 const uint32_t kMinArgsOnStack = 4; 295 const uint32_t kMinArgsOnStack = 4;
215 296
216 StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back()); 297 StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
217 298
218 uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]; 299 if (context_->context_flags & MD_CONTEXT_MIPS) {
219 uint32_t caller_pc, caller_sp, caller_fp; 300 uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
301 uint32_t caller_pc, caller_sp, caller_fp;
220 302
221 // Return address cannot be obtained directly. 303 // Return address cannot be obtained directly.
222 // Force stackwalking. 304 // Force stackwalking.
223 305
224 // We cannot use frame pointer to get the return address. 306 // We cannot use frame pointer to get the return address.
225 // We'll scan the stack for a 307 // We'll scan the stack for a
226 // return address. This can happen if last_frame is executing code 308 // return address. This can happen if last_frame is executing code
227 // for a module for which we don't have symbols. 309 // for a module for which we don't have symbols.
228 int count = kMaxFrameStackSize / sizeof(caller_pc); 310 int count = kMaxFrameStackSize / sizeof(caller_pc);
229 311
230 if (frames.size() > 1) { 312 if (frames.size() > 1) {
231 // In case of mips32 ABI stack frame of a nonleaf function 313 // In case of mips32 ABI stack frame of a nonleaf function
232 // must have minimum stack frame assigned for 4 arguments (4 words). 314 // must have minimum stack frame assigned for 4 arguments (4 words).
233 // Move stack pointer for 4 words to avoid reporting non-existing frames 315 // Move stack pointer for 4 words to avoid reporting non-existing frames
234 // for all frames except the topmost one. 316 // for all frames except the topmost one.
235 // There is no way of knowing if topmost frame belongs to a leaf or 317 // There is no way of knowing if topmost frame belongs to a leaf or
236 // a nonleaf function. 318 // a nonleaf function.
237 last_sp += kMinArgsOnStack * sizeof(caller_pc); 319 last_sp += kMinArgsOnStack * sizeof(caller_pc);
238 // Adjust 'count' so that return address is scanned only in limits 320 // Adjust 'count' so that return address is scanned only in limits
239 // of one stack frame. 321 // of one stack frame.
240 count -= kMinArgsOnStack; 322 count -= kMinArgsOnStack;
241 } 323 }
242 324
243 do { 325 do {
244 // Scanning for return address from stack pointer of the last frame. 326 // Scanning for return address from stack pointer of the last frame.
245 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) { 327 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
246 // If we can't find an instruction pointer even with stack scanning, 328 // If we can't find an instruction pointer even with stack scanning,
247 // give up. 329 // give up.
248 BPLOG(ERROR) << " ScanForReturnAddress failed "; 330 BPLOG(ERROR) << " ScanForReturnAddress failed ";
249 return NULL; 331 return NULL;
250 } 332 }
251 // Get $fp stored in the stack frame. 333 // Get $fp stored in the stack frame.
252 if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc), 334 if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
253 &caller_fp)) { 335 &caller_fp)) {
254 BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ; 336 BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
337 return NULL;
338 }
339
340 count = count - (caller_sp - last_sp) / sizeof(caller_pc);
341 // Now scan the next address in the stack.
342 last_sp = caller_sp + sizeof(caller_pc);
343 } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
344
345 if (!count) {
346 BPLOG(INFO) << " No frame found " ;
255 return NULL; 347 return NULL;
256 } 348 }
257 349
258 count = count - (caller_sp - last_sp) / sizeof(caller_pc); 350 // ScanForReturnAddress found a reasonable return address. Advance
259 // Now scan the next address in the stack. 351 // $sp to the location above the one where the return address was
260 last_sp = caller_sp + sizeof(caller_pc); 352 // found.
261 } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0); 353 caller_sp += sizeof(caller_pc);
354 // caller_pc is actually containing $ra value;
355 // $pc is two instructions before $ra,
356 // so the caller_pc needs to be decremented accordingly.
357 caller_pc -= 2 * sizeof(caller_pc);
262 358
263 if (!count) { 359 // Create a new stack frame (ownership will be transferred to the caller)
264 BPLOG(INFO) << " No frame found " ; 360 // and fill it in.
265 return NULL; 361 StackFrameMIPS* frame = new StackFrameMIPS();
362 frame->trust = StackFrame::FRAME_TRUST_SCAN;
363 frame->context = last_frame->context;
364 frame->context.epc = caller_pc;
365 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
366 frame->instruction = caller_pc;
367
368 frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
369 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
370 frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
371 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
372
373 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
374 caller_pc + 2 * sizeof(caller_pc);
375 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
376
377 return frame;
378 } else {
379 uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
380 uint64_t caller_pc, caller_sp, caller_fp;
381
382 // Return address cannot be obtained directly.
383 // Force stackwalking.
384
385 // We cannot use frame pointer to get the return address.
386 // We'll scan the stack for a
387 // return address. This can happen if last_frame is executing code
388 // for a module for which we don't have symbols.
389 int count = kMaxFrameStackSize / sizeof(caller_pc);
390
391 do {
392 // Scanning for return address from stack pointer of the last frame.
393 if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
394 // If we can't find an instruction pointer even with stack scanning,
395 // give up.
396 BPLOG(ERROR) << " ScanForReturnAddress failed ";
397 return NULL;
398 }
399 // Get $fp stored in the stack frame.
400 if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
401 &caller_fp)) {
402 BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
403 return NULL;
404 }
405
406 count = count - (caller_sp - last_sp) / sizeof(caller_pc);
407 // Now scan the next address in the stack.
408 last_sp = caller_sp + sizeof(caller_pc);
409 } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
410
411 if (!count) {
412 BPLOG(INFO) << " No frame found " ;
413 return NULL;
414 }
415
416 // ScanForReturnAddress found a reasonable return address. Advance
417 // $sp to the location above the one where the return address was
418 // found.
419 caller_sp += sizeof(caller_pc);
420 // caller_pc is actually containing $ra value;
421 // $pc is two instructions before $ra,
422 // so the caller_pc needs to be decremented accordingly.
423 caller_pc -= 2 * sizeof(caller_pc);
424
425 // Create a new stack frame (ownership will be transferred to the caller)
426 // and fill it in.
427 StackFrameMIPS* frame = new StackFrameMIPS();
428 frame->trust = StackFrame::FRAME_TRUST_SCAN;
429 frame->context = last_frame->context;
430 frame->context.epc = caller_pc;
431 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
432 frame->instruction = caller_pc;
433
434 frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
435 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
436 frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
437 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
438
439 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
440 caller_pc + 2 * sizeof(caller_pc);
441 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
442
443 return frame;
266 } 444 }
267
268 // ScanForReturnAddress found a reasonable return address. Advance
269 // $sp to the location above the one where the return address was
270 // found.
271 caller_sp += sizeof(caller_pc);
272 // caller_pc is actually containing $ra value;
273 // $pc is two instructions before $ra,
274 // so the caller_pc needs to be decremented accordingly.
275 caller_pc -= 2 * sizeof(caller_pc);
276
277
278 // Create a new stack frame (ownership will be transferred to the caller)
279 // and fill it in.
280 StackFrameMIPS* frame = new StackFrameMIPS();
281 frame->trust = StackFrame::FRAME_TRUST_SCAN;
282 frame->context = last_frame->context;
283 frame->context.epc = caller_pc;
284 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
285 frame->instruction = caller_pc;
286
287 frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
288 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
289 frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
290 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
291
292 frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
293 caller_pc + 2 * sizeof(caller_pc);
294 frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
295
296 return frame;
297 } 445 }
298 446
299 } // namespace google_breakpad 447 } // namespace google_breakpad
300 448
OLDNEW
« no previous file with comments | « src/processor/stackwalker.cc ('k') | src/processor/stackwalker_mips64_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698