diff options
author | Sebastien Hertz <shertz@google.com> | 2014-06-13 14:49:27 +0200 |
---|---|---|
committer | Sebastien Hertz <shertz@google.com> | 2014-06-17 11:13:03 +0200 |
commit | aa9b3aee1e06f922e4518713f9b3dff00a0b2597 (patch) | |
tree | 992b4565732a728dd901ed8a2f29c9246de328b7 /runtime/stack.cc | |
parent | bc72903b909f5147b8cb207f3e5d02a8ef85e4e7 (diff) | |
download | art-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.zip art-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.tar.gz art-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.tar.bz2 |
Fix access to FP registers when visiting stack
Adds GetFPR and SetFPR to Context class so we can read from and write to
floating-point registers during stack visit. They return a boolean flag
indicating whether the read/write is successful. This allows the debugger to
return the JDWP error ABSENT_INFORMATION when we can't read/write a register.
We also update GetGPR and SetGPR for consistency. We keep a default GetGPR
implementation asserting the read was successful using a CHECK so we don't
silently fail.
Adds missing JDWP object tags for StackFrame.SetValues to avoid crash when
setting corresponding objects (thread, thread group, class object or class
loader). Also returns JDWP error INVALID_OBJECT (when the given object id is
invalid) instead of crashing with an unimplemented message.
Bug: 15433097
Change-Id: I70843c9280e694aec1eae5cf6f2dc155cb9ea10e
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r-- | runtime/stack.cc | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc index 7e922c5..8d242cd 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -142,7 +142,8 @@ size_t StackVisitor::GetNativePcOffset() const { return GetMethod()->NativePcOffset(cur_quick_frame_pc_); } -uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind) const { +bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, + uint32_t* val) const { if (cur_quick_frame_ != NULL) { DCHECK(context_ != NULL); // You can't reliably read registers without a context. DCHECK(m == GetMethod()); @@ -155,19 +156,26 @@ uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) { bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg); uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask(); - return GetGPR(vmap_table.ComputeRegister(spill_mask, vmap_offset, kind)); + uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind); + if (is_float) { + return GetFPR(reg, val); + } else { + return GetGPR(reg, val); + } } else { const DexFile::CodeItem* code_item = m->GetCodeItem(); DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions? - return *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(), + *val = *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(), frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg); + return true; } } else { - return cur_shadow_frame_->GetVReg(vreg); + *val = cur_shadow_frame_->GetVReg(vreg); + return true; } } -void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, +bool StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) { if (cur_quick_frame_ != NULL) { DCHECK(context_ != NULL); // You can't reliably write registers without a context. @@ -181,8 +189,12 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) { bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg); uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask(); - const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kReferenceVReg); - SetGPR(reg, new_value); + const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind); + if (is_float) { + return SetFPR(reg, new_value); + } else { + return SetGPR(reg, new_value); + } } else { const DexFile::CodeItem* code_item = m->GetCodeItem(); DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions? @@ -190,9 +202,11 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val frame_info.FrameSizeInBytes(), vreg, kRuntimeISA); byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset; *reinterpret_cast<uint32_t*>(vreg_addr) = new_value; + return true; } } else { - return cur_shadow_frame_->SetVReg(vreg, new_value); + cur_shadow_frame_->SetVReg(vreg, new_value); + return true; } } @@ -201,14 +215,24 @@ uintptr_t* StackVisitor::GetGPRAddress(uint32_t reg) const { return context_->GetGPRAddress(reg); } -uintptr_t StackVisitor::GetGPR(uint32_t reg) const { +bool StackVisitor::GetGPR(uint32_t reg, uintptr_t* val) const { + DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine"; + return context_->GetGPR(reg, val); +} + +bool StackVisitor::SetGPR(uint32_t reg, uintptr_t value) { + DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine"; + return context_->SetGPR(reg, value); +} + +bool StackVisitor::GetFPR(uint32_t reg, uintptr_t* val) const { DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine"; - return context_->GetGPR(reg); + return context_->GetFPR(reg, val); } -void StackVisitor::SetGPR(uint32_t reg, uintptr_t value) { +bool StackVisitor::SetFPR(uint32_t reg, uintptr_t value) { DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine"; - context_->SetGPR(reg, value); + return context_->SetFPR(reg, value); } uintptr_t StackVisitor::GetReturnPc() const { |