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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/processor/stackwalker.cc ('k') | src/processor/stackwalker_mips64_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/processor/stackwalker_mips.cc
diff --git a/src/processor/stackwalker_mips.cc b/src/processor/stackwalker_mips.cc
index 7db34219232363a48b7331bf92c31a44b3ee6903..db55d460c06d8ee666fe1a118e2abba1d7aee6df 100644
--- a/src/processor/stackwalker_mips.cc
+++ b/src/processor/stackwalker_mips.cc
@@ -53,14 +53,25 @@ StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
- : Stackwalker(system_info, memory, modules, resolver_helper),
- context_(context) {
- if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
- BPLOG(ERROR) << "Memory out of range for stackwalking: "
- << HexString(memory_->GetBase())
- << "+"
- << HexString(memory_->GetSize());
- memory_ = NULL;
+: Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context) {
+ if (context_->context_flags & MD_CONTEXT_MIPS64 ) {
+ if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1)
+ > 0xffffffffffffffff) {
+ BPLOG(ERROR) << "Memory out of range for stackwalking mips64: "
+ << HexString(memory_->GetBase())
+ << "+"
+ << HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
+ } else {
+ if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1) > 0xffffffff) {
+ BPLOG(ERROR) << "Memory out of range for stackwalking mips32: "
+ << HexString(memory_->GetBase())
+ << "+"
+ << HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
}
}
@@ -96,73 +107,143 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo(
CFIFrameInfo* cfi_frame_info) {
StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
- uint32_t sp = 0, pc = 0;
+ if (context_->context_flags & MD_CONTEXT_MIPS) {
+ uint32_t sp = 0, pc = 0;
- // Populate a dictionary with the valid register values in last_frame.
- CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
- // Use the STACK CFI data to recover the caller's register values.
- CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
- for (int i = 0; kRegisterNames[i]; ++i) {
- caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
- callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
- }
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ }
- if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
- &caller_registers)) {
- return NULL;
- }
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers)) {
+ return NULL;
+ }
- CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry =
- caller_registers.find(".cfa");
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry =
+ caller_registers.find(".cfa");
- if (entry != caller_registers.end()) {
- sp = entry->second;
- caller_registers["$sp"] = entry->second;
- }
+ if (entry != caller_registers.end()) {
+ sp = entry->second;
+ caller_registers["$sp"] = entry->second;
+ }
- entry = caller_registers.find(".ra");
- if (entry != caller_registers.end()) {
- caller_registers["$ra"] = entry->second;
- pc = entry->second - 2 * sizeof(pc);
- }
- caller_registers["$pc"] = pc;
- // Construct a new stack frame given the values the CFI recovered.
- scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
-
- for (int i = 0; kRegisterNames[i]; ++i) {
- CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry =
- caller_registers.find(kRegisterNames[i]);
-
- if (caller_entry != caller_registers.end()) {
- // The value of this register is recovered; fill the context with the
- // value from caller_registers.
- frame->context.iregs[i] = caller_entry->second;
- frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
- } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
- (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
- (last_frame->context_validity &
- StackFrameMIPS::RegisterValidFlag(i))) {
- // If the STACK CFI data doesn't mention some callee-save register, and
- // it is valid in the callee, assume the callee has not yet changed it.
- // Calee-save registers according to the MIPS o32 ABI specification are:
- // $s0 to $s7
- // $sp, $s8
- frame->context.iregs[i] = last_frame->context.iregs[i];
- frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ entry = caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ caller_registers["$ra"] = entry->second;
+ pc = entry->second - 2 * sizeof(pc);
}
- }
+ caller_registers["$pc"] = pc;
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry =
+ caller_registers.find(kRegisterNames[i]);
+
+ if (caller_entry != caller_registers.end()) {
+ // The value of this register is recovered; fill the context with the
+ // value from caller_registers.
+ frame->context.iregs[i] = caller_entry->second;
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
+ (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
+ (last_frame->context_validity &
+ StackFrameMIPS::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-save register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Calee-save registers according to the MIPS o32 ABI specification are:
+ // $s0 to $s7
+ // $sp, $s8
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ }
+ }
+
+ frame->context.epc = caller_registers["$pc"];
+ frame->instruction = caller_registers["$pc"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
- frame->context.epc = caller_registers["$pc"];
- frame->instruction = caller_registers["$pc"];
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
-
- frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
- frame->trust = StackFrame::FRAME_TRUST_CFI;
+ return frame.release();
+ } else {
+ uint64_t sp = 0, pc = 0;
+
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ }
- return frame.release();
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers)) {
+ return NULL;
+ }
+
+ CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator entry =
+ caller_registers.find(".cfa");
+
+ if (entry != caller_registers.end()) {
+ sp = entry->second;
+ caller_registers["$sp"] = entry->second;
+ }
+
+ entry = caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ caller_registers["$ra"] = entry->second;
+ pc = entry->second - 2 * sizeof(pc);
+ }
+ caller_registers["$pc"] = pc;
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator caller_entry =
+ caller_registers.find(kRegisterNames[i]);
+
+ if (caller_entry != caller_registers.end()) {
+ // The value of this register is recovered; fill the context with the
+ // value from caller_registers.
+ frame->context.iregs[i] = caller_entry->second;
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
+ (i >= INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
+ (last_frame->context_validity &
+ StackFrameMIPS::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-save register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Calee-save registers according to the MIPS o32 ABI specification are:
+ // $s0 to $s7
+ // $sp, $s8
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ }
+ }
+
+ frame->context.epc = caller_registers["$pc"];
+ frame->instruction = caller_registers["$pc"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+
+ return frame.release();
+ }
}
StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack,
@@ -204,7 +285,7 @@ StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack,
last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]) {
return NULL;
}
-
+
return new_frame.release();
}
@@ -215,19 +296,20 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan(
StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
- uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
- uint32_t caller_pc, caller_sp, caller_fp;
+ if (context_->context_flags & MD_CONTEXT_MIPS) {
+ uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
+ uint32_t caller_pc, caller_sp, caller_fp;
- // Return address cannot be obtained directly.
- // Force stackwalking.
+ // Return address cannot be obtained directly.
+ // Force stackwalking.
- // We cannot use frame pointer to get the return address.
- // We'll scan the stack for a
- // return address. This can happen if last_frame is executing code
- // for a module for which we don't have symbols.
- int count = kMaxFrameStackSize / sizeof(caller_pc);
+ // We cannot use frame pointer to get the return address.
+ // We'll scan the stack for a
+ // return address. This can happen if last_frame is executing code
+ // for a module for which we don't have symbols.
+ int count = kMaxFrameStackSize / sizeof(caller_pc);
- if (frames.size() > 1) {
+ if (frames.size() > 1) {
// In case of mips32 ABI stack frame of a nonleaf function
// must have minimum stack frame assigned for 4 arguments (4 words).
// Move stack pointer for 4 words to avoid reporting non-existing frames
@@ -235,65 +317,131 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan(
// There is no way of knowing if topmost frame belongs to a leaf or
// a nonleaf function.
last_sp += kMinArgsOnStack * sizeof(caller_pc);
- // Adjust 'count' so that return address is scanned only in limits
+ // Adjust 'count' so that return address is scanned only in limits
// of one stack frame.
count -= kMinArgsOnStack;
- }
+ }
- do {
- // Scanning for return address from stack pointer of the last frame.
- if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
- // If we can't find an instruction pointer even with stack scanning,
- // give up.
- BPLOG(ERROR) << " ScanForReturnAddress failed ";
+ do {
+ // Scanning for return address from stack pointer of the last frame.
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
+ // If we can't find an instruction pointer even with stack scanning,
+ // give up.
+ BPLOG(ERROR) << " ScanForReturnAddress failed ";
+ return NULL;
+ }
+ // Get $fp stored in the stack frame.
+ if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
+ &caller_fp)) {
+ BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
+ return NULL;
+ }
+
+ count = count - (caller_sp - last_sp) / sizeof(caller_pc);
+ // Now scan the next address in the stack.
+ last_sp = caller_sp + sizeof(caller_pc);
+ } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
+
+ if (!count) {
+ BPLOG(INFO) << " No frame found " ;
return NULL;
}
- // Get $fp stored in the stack frame.
- if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
- &caller_fp)) {
- BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
+
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // $sp to the location above the one where the return address was
+ // found.
+ caller_sp += sizeof(caller_pc);
+ // caller_pc is actually containing $ra value;
+ // $pc is two instructions before $ra,
+ // so the caller_pc needs to be decremented accordingly.
+ caller_pc -= 2 * sizeof(caller_pc);
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameMIPS* frame = new StackFrameMIPS();
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.epc = caller_pc;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+ frame->instruction = caller_pc;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
+ caller_pc + 2 * sizeof(caller_pc);
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ return frame;
+ } else {
+ uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
+ uint64_t caller_pc, caller_sp, caller_fp;
+
+ // Return address cannot be obtained directly.
+ // Force stackwalking.
+
+ // We cannot use frame pointer to get the return address.
+ // We'll scan the stack for a
+ // return address. This can happen if last_frame is executing code
+ // for a module for which we don't have symbols.
+ int count = kMaxFrameStackSize / sizeof(caller_pc);
+
+ do {
+ // Scanning for return address from stack pointer of the last frame.
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
+ // If we can't find an instruction pointer even with stack scanning,
+ // give up.
+ BPLOG(ERROR) << " ScanForReturnAddress failed ";
+ return NULL;
+ }
+ // Get $fp stored in the stack frame.
+ if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
+ &caller_fp)) {
+ BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
+ return NULL;
+ }
+
+ count = count - (caller_sp - last_sp) / sizeof(caller_pc);
+ // Now scan the next address in the stack.
+ last_sp = caller_sp + sizeof(caller_pc);
+ } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
+
+ if (!count) {
+ BPLOG(INFO) << " No frame found " ;
return NULL;
}
- count = count - (caller_sp - last_sp) / sizeof(caller_pc);
- // Now scan the next address in the stack.
- last_sp = caller_sp + sizeof(caller_pc);
- } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
-
- if (!count) {
- BPLOG(INFO) << " No frame found " ;
- return NULL;
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // $sp to the location above the one where the return address was
+ // found.
+ caller_sp += sizeof(caller_pc);
+ // caller_pc is actually containing $ra value;
+ // $pc is two instructions before $ra,
+ // so the caller_pc needs to be decremented accordingly.
+ caller_pc -= 2 * sizeof(caller_pc);
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameMIPS* frame = new StackFrameMIPS();
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.epc = caller_pc;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+ frame->instruction = caller_pc;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
+ caller_pc + 2 * sizeof(caller_pc);
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ return frame;
}
-
- // ScanForReturnAddress found a reasonable return address. Advance
- // $sp to the location above the one where the return address was
- // found.
- caller_sp += sizeof(caller_pc);
- // caller_pc is actually containing $ra value;
- // $pc is two instructions before $ra,
- // so the caller_pc needs to be decremented accordingly.
- caller_pc -= 2 * sizeof(caller_pc);
-
-
- // Create a new stack frame (ownership will be transferred to the caller)
- // and fill it in.
- StackFrameMIPS* frame = new StackFrameMIPS();
- frame->trust = StackFrame::FRAME_TRUST_SCAN;
- frame->context = last_frame->context;
- frame->context.epc = caller_pc;
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
- frame->instruction = caller_pc;
-
- frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
- frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
-
- frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
- caller_pc + 2 * sizeof(caller_pc);
- frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
-
- return frame;
}
} // namespace google_breakpad
« 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