From 0bcb2902ec21393d71c94e63aa6733cb5311a0cc Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Tue, 17 Jun 2014 15:52:45 +0200 Subject: Revert "Revert "Fix access to FP registers when visiting stack"" This reverts commit 8ebd94ab2e0d9867a7d384f00fa4cab24235216f. Fixes StackVisitor::GetVReg to read register value in a uintptr_t local and cast it into uint32_t pointer argument. Bug: 15433097 Change-Id: I4e13ed5446e823e9ec50fbc378b16be5b17b2294 --- runtime/arch/arm/context_arm.cc | 39 ++++-- runtime/arch/arm/context_arm.h | 46 +++++-- runtime/arch/arm64/context_arm64.cc | 113 +++++++++------- runtime/arch/arm64/context_arm64.h | 46 +++++-- runtime/arch/context.h | 28 ++-- runtime/arch/mips/context_mips.cc | 37 +++-- runtime/arch/mips/context_mips.h | 46 +++++-- runtime/arch/x86/context_x86.cc | 20 +-- runtime/arch/x86/context_x86.h | 39 ++++-- runtime/arch/x86_64/context_x86_64.cc | 25 +++- runtime/arch/x86_64/context_x86_64.h | 42 ++++-- runtime/debugger.cc | 246 +++++++++++++++++++++------------- runtime/stack.cc | 52 +++++-- runtime/stack.h | 19 ++- 14 files changed, 540 insertions(+), 258 deletions(-) diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc index 6a337b3..96ffc93 100644 --- a/runtime/arch/arm/context_arm.cc +++ b/runtime/arch/arm/context_arm.cc @@ -25,14 +25,14 @@ namespace art { namespace arm { -static const uint32_t gZero = 0; +static constexpr uint32_t gZero = 0; void ArmContext::Reset() { for (size_t i = 0; i < kNumberOfCoreRegisters; i++) { - gprs_[i] = NULL; + gprs_[i] = nullptr; } for (size_t i = 0; i < kNumberOfSRegisters; i++) { - fprs_[i] = NULL; + fprs_[i] = nullptr; } gprs_[SP] = &sp_; gprs_[PC] = &pc_; @@ -69,31 +69,46 @@ void ArmContext::FillCalleeSaves(const StackVisitor& fr) { } } -void ArmContext::SetGPR(uint32_t reg, uintptr_t value) { +bool ArmContext::SetGPR(uint32_t reg, uintptr_t value) { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); DCHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. - DCHECK(gprs_[reg] != NULL); - *gprs_[reg] = value; + if (gprs_[reg] != nullptr) { + *gprs_[reg] = value; + return true; + } else { + return false; + } +} + +bool ArmContext::SetFPR(uint32_t reg, uintptr_t value) { + DCHECK_LT(reg, static_cast(kNumberOfSRegisters)); + DCHECK_NE(fprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. + if (fprs_[reg] != nullptr) { + *fprs_[reg] = value; + return true; + } else { + return false; + } } void ArmContext::SmashCallerSaves() { // This needs to be 0 because we want a null/zero return value. gprs_[R0] = const_cast(&gZero); gprs_[R1] = const_cast(&gZero); - gprs_[R2] = NULL; - gprs_[R3] = NULL; + gprs_[R2] = nullptr; + gprs_[R3] = nullptr; } extern "C" void art_quick_do_long_jump(uint32_t*, uint32_t*); void ArmContext::DoLongJump() { - uintptr_t gprs[16]; - uint32_t fprs[32]; + uintptr_t gprs[kNumberOfCoreRegisters]; + uint32_t fprs[kNumberOfSRegisters]; for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) { - gprs[i] = gprs_[i] != NULL ? *gprs_[i] : ArmContext::kBadGprBase + i; + gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : ArmContext::kBadGprBase + i; } for (size_t i = 0; i < kNumberOfSRegisters; ++i) { - fprs[i] = fprs_[i] != NULL ? *fprs_[i] : ArmContext::kBadGprBase + i; + fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : ArmContext::kBadFprBase + i; } DCHECK_EQ(reinterpret_cast(Thread::Current()), gprs[TR]); art_quick_do_long_jump(gprs, fprs); diff --git a/runtime/arch/arm/context_arm.h b/runtime/arch/arm/context_arm.h index 2ccce8d..e894f16 100644 --- a/runtime/arch/arm/context_arm.h +++ b/runtime/arch/arm/context_arm.h @@ -32,31 +32,53 @@ class ArmContext : public Context { virtual ~ArmContext() {} - virtual void Reset(); + void Reset() OVERRIDE; - virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FillCalleeSaves(const StackVisitor& fr) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - virtual void SetSP(uintptr_t new_sp) { - SetGPR(SP, new_sp); + void SetSP(uintptr_t new_sp) OVERRIDE { + bool success = SetGPR(SP, new_sp); + CHECK(success) << "Failed to set SP register"; } - virtual void SetPC(uintptr_t new_pc) { - SetGPR(PC, new_pc); + void SetPC(uintptr_t new_pc) OVERRIDE { + bool success = SetGPR(PC, new_pc); + CHECK(success) << "Failed to set PC register"; } - virtual uintptr_t* GetGPRAddress(uint32_t reg) { + uintptr_t* GetGPRAddress(uint32_t reg) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); return gprs_[reg]; } - virtual uintptr_t GetGPR(uint32_t reg) { + bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); - return *gprs_[reg]; + if (gprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *gprs_[reg]; + return true; + } } - virtual void SetGPR(uint32_t reg, uintptr_t value); - virtual void SmashCallerSaves(); - virtual void DoLongJump(); + bool SetGPR(uint32_t reg, uintptr_t value) OVERRIDE; + + bool GetFPR(uint32_t reg, uintptr_t* val) OVERRIDE { + DCHECK_LT(reg, static_cast(kNumberOfSRegisters)); + if (fprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *fprs_[reg]; + return true; + } + } + + bool SetFPR(uint32_t reg, uintptr_t value) OVERRIDE; + + void SmashCallerSaves() OVERRIDE; + void DoLongJump() OVERRIDE; private: // Pointers to register locations, initialized to NULL or the specific registers below. diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc index 09e8b59..3eb92c8 100644 --- a/runtime/arch/arm64/context_arm64.cc +++ b/runtime/arch/arm64/context_arm64.cc @@ -28,14 +28,14 @@ namespace art { namespace arm64 { -static const uint64_t gZero = 0; +static constexpr uint64_t gZero = 0; void Arm64Context::Reset() { for (size_t i = 0; i < kNumberOfCoreRegisters; i++) { - gprs_[i] = NULL; + gprs_[i] = nullptr; } for (size_t i = 0; i < kNumberOfDRegisters; i++) { - fprs_[i] = NULL; + fprs_[i] = nullptr; } gprs_[SP] = &sp_; gprs_[LR] = &pc_; @@ -73,73 +73,88 @@ void Arm64Context::FillCalleeSaves(const StackVisitor& fr) { } } -void Arm64Context::SetGPR(uint32_t reg, uintptr_t value) { +bool Arm64Context::SetGPR(uint32_t reg, uintptr_t value) { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); DCHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. - DCHECK(gprs_[reg] != NULL); - *gprs_[reg] = value; + if (gprs_[reg] != nullptr) { + *gprs_[reg] = value; + return true; + } else { + return false; + } +} + +bool Arm64Context::SetFPR(uint32_t reg, uintptr_t value) { + DCHECK_LT(reg, static_cast(kNumberOfDRegisters)); + DCHECK_NE(fprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. + if (fprs_[reg] != nullptr) { + *fprs_[reg] = value; + return true; + } else { + return false; + } } void Arm64Context::SmashCallerSaves() { // This needs to be 0 because we want a null/zero return value. gprs_[X0] = const_cast(&gZero); - gprs_[X1] = NULL; - gprs_[X2] = NULL; - gprs_[X3] = NULL; - gprs_[X4] = NULL; - gprs_[X5] = NULL; - gprs_[X6] = NULL; - gprs_[X7] = NULL; - gprs_[X8] = NULL; - gprs_[X9] = NULL; - gprs_[X10] = NULL; - gprs_[X11] = NULL; - gprs_[X12] = NULL; - gprs_[X13] = NULL; - gprs_[X14] = NULL; - gprs_[X15] = NULL; + gprs_[X1] = nullptr; + gprs_[X2] = nullptr; + gprs_[X3] = nullptr; + gprs_[X4] = nullptr; + gprs_[X5] = nullptr; + gprs_[X6] = nullptr; + gprs_[X7] = nullptr; + gprs_[X8] = nullptr; + gprs_[X9] = nullptr; + gprs_[X10] = nullptr; + gprs_[X11] = nullptr; + gprs_[X12] = nullptr; + gprs_[X13] = nullptr; + gprs_[X14] = nullptr; + gprs_[X15] = nullptr; // d0-d7, d16-d31 are caller-saved; d8-d15 are callee-saved. - fprs_[D0] = NULL; - fprs_[D1] = NULL; - fprs_[D2] = NULL; - fprs_[D3] = NULL; - fprs_[D4] = NULL; - fprs_[D5] = NULL; - fprs_[D6] = NULL; - fprs_[D7] = NULL; - - fprs_[D16] = NULL; - fprs_[D17] = NULL; - fprs_[D18] = NULL; - fprs_[D19] = NULL; - fprs_[D20] = NULL; - fprs_[D21] = NULL; - fprs_[D22] = NULL; - fprs_[D23] = NULL; - fprs_[D24] = NULL; - fprs_[D25] = NULL; - fprs_[D26] = NULL; - fprs_[D27] = NULL; - fprs_[D28] = NULL; - fprs_[D29] = NULL; - fprs_[D30] = NULL; - fprs_[D31] = NULL; + fprs_[D0] = nullptr; + fprs_[D1] = nullptr; + fprs_[D2] = nullptr; + fprs_[D3] = nullptr; + fprs_[D4] = nullptr; + fprs_[D5] = nullptr; + fprs_[D6] = nullptr; + fprs_[D7] = nullptr; + + fprs_[D16] = nullptr; + fprs_[D17] = nullptr; + fprs_[D18] = nullptr; + fprs_[D19] = nullptr; + fprs_[D20] = nullptr; + fprs_[D21] = nullptr; + fprs_[D22] = nullptr; + fprs_[D23] = nullptr; + fprs_[D24] = nullptr; + fprs_[D25] = nullptr; + fprs_[D26] = nullptr; + fprs_[D27] = nullptr; + fprs_[D28] = nullptr; + fprs_[D29] = nullptr; + fprs_[D30] = nullptr; + fprs_[D31] = nullptr; } extern "C" void art_quick_do_long_jump(uint64_t*, uint64_t*); void Arm64Context::DoLongJump() { uint64_t gprs[32]; - uint64_t fprs[32]; + uint64_t fprs[kNumberOfDRegisters]; // Do not use kNumberOfCoreRegisters, as this is with the distinction of SP and XZR for (size_t i = 0; i < 32; ++i) { - gprs[i] = gprs_[i] != NULL ? *gprs_[i] : Arm64Context::kBadGprBase + i; + gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : Arm64Context::kBadGprBase + i; } for (size_t i = 0; i < kNumberOfDRegisters; ++i) { - fprs[i] = fprs_[i] != NULL ? *fprs_[i] : Arm64Context::kBadGprBase + i; + fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadGprBase + i; } DCHECK_EQ(reinterpret_cast(Thread::Current()), gprs[TR]); art_quick_do_long_jump(gprs, fprs); diff --git a/runtime/arch/arm64/context_arm64.h b/runtime/arch/arm64/context_arm64.h index d40e291..1f69869 100644 --- a/runtime/arch/arm64/context_arm64.h +++ b/runtime/arch/arm64/context_arm64.h @@ -32,31 +32,53 @@ class Arm64Context : public Context { ~Arm64Context() {} - void Reset(); + void Reset() OVERRIDE; - void FillCalleeSaves(const StackVisitor& fr); + void FillCalleeSaves(const StackVisitor& fr) OVERRIDE; - void SetSP(uintptr_t new_sp) { - SetGPR(SP, new_sp); + void SetSP(uintptr_t new_sp) OVERRIDE { + bool success = SetGPR(SP, new_sp); + CHECK(success) << "Failed to set SP register"; } - void SetPC(uintptr_t new_lr) { - SetGPR(LR, new_lr); + void SetPC(uintptr_t new_lr) OVERRIDE { + bool success = SetGPR(LR, new_lr); + CHECK(success) << "Failed to set LR register"; } - virtual uintptr_t* GetGPRAddress(uint32_t reg) { + uintptr_t* GetGPRAddress(uint32_t reg) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); return gprs_[reg]; } - uintptr_t GetGPR(uint32_t reg) { + bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); - return *gprs_[reg]; + if (gprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *gprs_[reg]; + return true; + } } - void SetGPR(uint32_t reg, uintptr_t value); - void SmashCallerSaves(); - void DoLongJump(); + bool SetGPR(uint32_t reg, uintptr_t value) OVERRIDE; + + bool GetFPR(uint32_t reg, uintptr_t* val) OVERRIDE { + DCHECK_LT(reg, static_cast(kNumberOfDRegisters)); + if (fprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *fprs_[reg]; + return true; + } + } + + bool SetFPR(uint32_t reg, uintptr_t value) OVERRIDE; + + void SmashCallerSaves() OVERRIDE; + void DoLongJump() OVERRIDE; private: // Pointers to register locations, initialized to NULL or the specific registers below. diff --git a/runtime/arch/context.h b/runtime/arch/context.h index f7b7835..20a84dd 100644 --- a/runtime/arch/context.h +++ b/runtime/arch/context.h @@ -38,30 +38,40 @@ class Context { // Re-initializes the registers for context re-use. virtual void Reset() = 0; - // Read values from callee saves in the given frame. The frame also holds + // Reads values from callee saves in the given frame. The frame also holds // the method that holds the layout. virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0; - // Set the stack pointer value + // Sets the stack pointer value. virtual void SetSP(uintptr_t new_sp) = 0; - // Set the program counter value + // Sets the program counter value. virtual void SetPC(uintptr_t new_pc) = 0; // Gets the given GPRs address. virtual uintptr_t* GetGPRAddress(uint32_t reg) = 0; - // Read the given GPR - virtual uintptr_t GetGPR(uint32_t reg) = 0; + // Reads the given GPR. Returns true if we successfully read the register and + // set its value into 'val', returns false otherwise. + virtual bool GetGPR(uint32_t reg, uintptr_t* val) = 0; - // Set the given GPR. - virtual void SetGPR(uint32_t reg, uintptr_t value) = 0; + // Sets the given GPR. Returns true if we successfully write the given value + // into the register, returns false otherwise. + virtual bool SetGPR(uint32_t reg, uintptr_t value) = 0; - // Smash the caller save registers. If we're throwing, we don't want to return bogus values. + // Reads the given FPR. Returns true if we successfully read the register and + // set its value into 'val', returns false otherwise. + virtual bool GetFPR(uint32_t reg, uintptr_t* val) = 0; + + // Sets the given FPR. Returns true if we successfully write the given value + // into the register, returns false otherwise. + virtual bool SetFPR(uint32_t reg, uintptr_t value) = 0; + + // Smashes the caller save registers. If we're throwing, we don't want to return bogus values. virtual void SmashCallerSaves() = 0; - // Switch execution of the executing context to this context + // Switches execution of the executing context to this context virtual void DoLongJump() = 0; protected: diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc index ad28891..789dbbb 100644 --- a/runtime/arch/mips/context_mips.cc +++ b/runtime/arch/mips/context_mips.cc @@ -24,14 +24,14 @@ namespace art { namespace mips { -static const uint32_t gZero = 0; +static constexpr uint32_t gZero = 0; void MipsContext::Reset() { for (size_t i = 0; i < kNumberOfCoreRegisters; i++) { - gprs_[i] = NULL; + gprs_[i] = nullptr; } for (size_t i = 0; i < kNumberOfFRegisters; i++) { - fprs_[i] = NULL; + fprs_[i] = nullptr; } gprs_[SP] = &sp_; gprs_[RA] = &ra_; @@ -68,20 +68,35 @@ void MipsContext::FillCalleeSaves(const StackVisitor& fr) { } } -void MipsContext::SetGPR(uint32_t reg, uintptr_t value) { +bool MipsContext::SetGPR(uint32_t reg, uintptr_t value) { CHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); CHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. - CHECK(gprs_[reg] != NULL); - *gprs_[reg] = value; + if (gprs_[reg] != nullptr) { + *gprs_[reg] = value; + return true; + } else { + return false; + } +} + +bool MipsContext::SetFPR(uint32_t reg, uintptr_t value) { + CHECK_LT(reg, static_cast(kNumberOfFRegisters)); + CHECK_NE(fprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. + if (fprs_[reg] != nullptr) { + *fprs_[reg] = value; + return true; + } else { + return false; + } } void MipsContext::SmashCallerSaves() { // This needs to be 0 because we want a null/zero return value. gprs_[V0] = const_cast(&gZero); gprs_[V1] = const_cast(&gZero); - gprs_[A1] = NULL; - gprs_[A2] = NULL; - gprs_[A3] = NULL; + gprs_[A1] = nullptr; + gprs_[A2] = nullptr; + gprs_[A3] = nullptr; } extern "C" void art_quick_do_long_jump(uint32_t*, uint32_t*); @@ -90,10 +105,10 @@ void MipsContext::DoLongJump() { uintptr_t gprs[kNumberOfCoreRegisters]; uint32_t fprs[kNumberOfFRegisters]; for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) { - gprs[i] = gprs_[i] != NULL ? *gprs_[i] : MipsContext::kBadGprBase + i; + gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : MipsContext::kBadGprBase + i; } for (size_t i = 0; i < kNumberOfFRegisters; ++i) { - fprs[i] = fprs_[i] != NULL ? *fprs_[i] : MipsContext::kBadGprBase + i; + fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadGprBase + i; } art_quick_do_long_jump(gprs, fprs); } diff --git a/runtime/arch/mips/context_mips.h b/runtime/arch/mips/context_mips.h index d5f27ae..f2ee335 100644 --- a/runtime/arch/mips/context_mips.h +++ b/runtime/arch/mips/context_mips.h @@ -31,31 +31,53 @@ class MipsContext : public Context { } virtual ~MipsContext() {} - virtual void Reset(); + void Reset() OVERRIDE; - virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FillCalleeSaves(const StackVisitor& fr) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - virtual void SetSP(uintptr_t new_sp) { - SetGPR(SP, new_sp); + void SetSP(uintptr_t new_sp) OVERRIDE { + bool success = SetGPR(SP, new_sp); + CHECK(success) << "Failed to set SP register"; } - virtual void SetPC(uintptr_t new_pc) { - SetGPR(RA, new_pc); + void SetPC(uintptr_t new_pc) OVERRIDE { + bool success = SetGPR(RA, new_pc); + CHECK(success) << "Failed to set RA register"; } - virtual uintptr_t* GetGPRAddress(uint32_t reg) { + uintptr_t* GetGPRAddress(uint32_t reg) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); return gprs_[reg]; } - virtual uintptr_t GetGPR(uint32_t reg) { + bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE { CHECK_LT(reg, static_cast(kNumberOfCoreRegisters)); - return *gprs_[reg]; + if (gprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *gprs_[reg]; + return true; + } } - virtual void SetGPR(uint32_t reg, uintptr_t value); - virtual void SmashCallerSaves(); - virtual void DoLongJump(); + bool SetGPR(uint32_t reg, uintptr_t value) OVERRIDE; + + bool GetFPR(uint32_t reg, uintptr_t* val) OVERRIDE { + CHECK_LT(reg, static_cast(kNumberOfFRegisters)); + if (fprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *fprs_[reg]; + return true; + } + } + + bool SetFPR(uint32_t reg, uintptr_t value) OVERRIDE; + + void SmashCallerSaves() OVERRIDE; + void DoLongJump() OVERRIDE; private: // Pointers to registers in the stack, initialized to NULL except for the special cases below. diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc index 8c98d91..37049cf 100644 --- a/runtime/arch/x86/context_x86.cc +++ b/runtime/arch/x86/context_x86.cc @@ -24,11 +24,11 @@ namespace art { namespace x86 { -static const uintptr_t gZero = 0; +static constexpr uintptr_t gZero = 0; void X86Context::Reset() { for (size_t i = 0; i < kNumberOfCpuRegisters; i++) { - gprs_[i] = NULL; + gprs_[i] = nullptr; } gprs_[ESP] = &esp_; // Initialize registers with easy to spot debug values. @@ -57,15 +57,19 @@ void X86Context::SmashCallerSaves() { // This needs to be 0 because we want a null/zero return value. gprs_[EAX] = const_cast(&gZero); gprs_[EDX] = const_cast(&gZero); - gprs_[ECX] = NULL; - gprs_[EBX] = NULL; + gprs_[ECX] = nullptr; + gprs_[EBX] = nullptr; } -void X86Context::SetGPR(uint32_t reg, uintptr_t value) { +bool X86Context::SetGPR(uint32_t reg, uintptr_t value) { CHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); CHECK_NE(gprs_[reg], &gZero); - CHECK(gprs_[reg] != NULL); - *gprs_[reg] = value; + if (gprs_[reg] != nullptr) { + *gprs_[reg] = value; + return true; + } else { + return false; + } } void X86Context::DoLongJump() { @@ -74,7 +78,7 @@ void X86Context::DoLongJump() { // the top for the stack pointer that doesn't get popped in a pop-all. volatile uintptr_t gprs[kNumberOfCpuRegisters + 1]; for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { - gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != NULL ? *gprs_[i] : X86Context::kBadGprBase + i; + gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != nullptr ? *gprs_[i] : X86Context::kBadGprBase + i; } // We want to load the stack pointer one slot below so that the ret will pop eip. uintptr_t esp = gprs[kNumberOfCpuRegisters - ESP - 1] - kWordSize; diff --git a/runtime/arch/x86/context_x86.h b/runtime/arch/x86/context_x86.h index 1c51026..a350b25 100644 --- a/runtime/arch/x86/context_x86.h +++ b/runtime/arch/x86/context_x86.h @@ -31,32 +31,49 @@ class X86Context : public Context { } virtual ~X86Context() {} - virtual void Reset(); + void Reset() OVERRIDE; - virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FillCalleeSaves(const StackVisitor& fr) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - virtual void SetSP(uintptr_t new_sp) { - SetGPR(ESP, new_sp); + void SetSP(uintptr_t new_sp) OVERRIDE { + bool success = SetGPR(ESP, new_sp); + CHECK(success) << "Failed to set ESP register"; } - virtual void SetPC(uintptr_t new_pc) { + void SetPC(uintptr_t new_pc) OVERRIDE { eip_ = new_pc; } - virtual uintptr_t* GetGPRAddress(uint32_t reg) { + uintptr_t* GetGPRAddress(uint32_t reg) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); return gprs_[reg]; } - virtual uintptr_t GetGPR(uint32_t reg) { + bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); - return *gprs_[reg]; + if (gprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *gprs_[reg]; + return true; + } } - virtual void SetGPR(uint32_t reg, uintptr_t value); + bool SetGPR(uint32_t reg, uintptr_t value) OVERRIDE; - virtual void SmashCallerSaves(); - virtual void DoLongJump(); + bool GetFPR(uint32_t reg, uintptr_t* val) OVERRIDE { + LOG(FATAL) << "Floating-point registers are all caller save in X86"; + return false; + } + + bool SetFPR(uint32_t reg, uintptr_t value) OVERRIDE { + LOG(FATAL) << "Floating-point registers are all caller save in X86"; + return false; + } + + void SmashCallerSaves() OVERRIDE; + void DoLongJump() OVERRIDE; private: // Pointers to register locations, floating point registers are all caller save. Values are diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc index 810ef94..0ccbd27 100644 --- a/runtime/arch/x86_64/context_x86_64.cc +++ b/runtime/arch/x86_64/context_x86_64.cc @@ -24,7 +24,7 @@ namespace art { namespace x86_64 { -static const uintptr_t gZero = 0; +static constexpr uintptr_t gZero = 0; void X86_64Context::Reset() { for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { @@ -80,11 +80,26 @@ void X86_64Context::SmashCallerSaves() { gprs_[R11] = nullptr; } -void X86_64Context::SetGPR(uint32_t reg, uintptr_t value) { +bool X86_64Context::SetGPR(uint32_t reg, uintptr_t value) { CHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); CHECK_NE(gprs_[reg], &gZero); - CHECK(gprs_[reg] != NULL); - *gprs_[reg] = value; + if (gprs_[reg] != nullptr) { + *gprs_[reg] = value; + return true; + } else { + return false; + } +} + +bool X86_64Context::SetFPR(uint32_t reg, uintptr_t value) { + CHECK_LT(reg, static_cast(kNumberOfFloatRegisters)); + CHECK_NE(fprs_[reg], &gZero); + if (fprs_[reg] != nullptr) { + *fprs_[reg] = value; + return true; + } else { + return false; + } } void X86_64Context::DoLongJump() { @@ -93,7 +108,7 @@ void X86_64Context::DoLongJump() { // the top for the stack pointer that doesn't get popped in a pop-all. volatile uintptr_t gprs[kNumberOfCpuRegisters + 1]; for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) { - gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != NULL ? *gprs_[i] : X86_64Context::kBadGprBase + i; + gprs[kNumberOfCpuRegisters - i - 1] = gprs_[i] != nullptr ? *gprs_[i] : X86_64Context::kBadGprBase + i; } // We want to load the stack pointer one slot below so that the ret will pop eip. uintptr_t rsp = gprs[kNumberOfCpuRegisters - RSP - 1] - kWordSize; diff --git a/runtime/arch/x86_64/context_x86_64.h b/runtime/arch/x86_64/context_x86_64.h index 055df61..902c3b9 100644 --- a/runtime/arch/x86_64/context_x86_64.h +++ b/runtime/arch/x86_64/context_x86_64.h @@ -31,32 +31,52 @@ class X86_64Context : public Context { } virtual ~X86_64Context() {} - virtual void Reset(); + void Reset() OVERRIDE; - virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FillCalleeSaves(const StackVisitor& fr) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - virtual void SetSP(uintptr_t new_sp) { - SetGPR(RSP, new_sp); + void SetSP(uintptr_t new_sp) OVERRIDE { + bool success = SetGPR(RSP, new_sp); + CHECK(success) << "Failed to set RSP register"; } - virtual void SetPC(uintptr_t new_pc) { + void SetPC(uintptr_t new_pc) OVERRIDE { rip_ = new_pc; } - virtual uintptr_t* GetGPRAddress(uint32_t reg) { + uintptr_t* GetGPRAddress(uint32_t reg) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); return gprs_[reg]; } - virtual uintptr_t GetGPR(uint32_t reg) { + bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE { DCHECK_LT(reg, static_cast(kNumberOfCpuRegisters)); - return *gprs_[reg]; + if (gprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *gprs_[reg]; + return true; + } } - virtual void SetGPR(uint32_t reg, uintptr_t value); + bool SetGPR(uint32_t reg, uintptr_t value) OVERRIDE; - virtual void SmashCallerSaves(); - virtual void DoLongJump(); + bool GetFPR(uint32_t reg, uintptr_t* val) OVERRIDE { + DCHECK_LT(reg, static_cast(kNumberOfFloatRegisters)); + if (fprs_[reg] == nullptr) { + return false; + } else { + DCHECK(val != nullptr); + *val = *fprs_[reg]; + return true; + } + } + + bool SetFPR(uint32_t reg, uintptr_t value) OVERRIDE; + + void SmashCallerSaves() OVERRIDE; + void DoLongJump() OVERRIDE; private: // Pointers to register locations. Values are initialized to NULL or the special registers below. diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 50e9624..f19c353 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -2346,100 +2346,125 @@ JDWP::JdwpError Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame return false; } uint16_t reg = DemangleSlot(slot_, m); - + constexpr JDWP::JdwpError kFailureErrorCode = JDWP::ERR_ABSENT_INFORMATION; switch (tag_) { - case JDWP::JT_BOOLEAN: - { + case JDWP::JT_BOOLEAN: { CHECK_EQ(width_, 1U); - uint32_t intVal = GetVReg(m, reg, kIntVReg); - VLOG(jdwp) << "get boolean local " << reg << " = " << intVal; - JDWP::Set1(buf_+1, intVal != 0); + uint32_t intVal; + if (GetVReg(m, reg, kIntVReg, &intVal)) { + VLOG(jdwp) << "get boolean local " << reg << " = " << intVal; + JDWP::Set1(buf_+1, intVal != 0); + } else { + VLOG(jdwp) << "failed to get boolean local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - case JDWP::JT_BYTE: - { + case JDWP::JT_BYTE: { CHECK_EQ(width_, 1U); - uint32_t intVal = GetVReg(m, reg, kIntVReg); - VLOG(jdwp) << "get byte local " << reg << " = " << intVal; - JDWP::Set1(buf_+1, intVal); + uint32_t intVal; + if (GetVReg(m, reg, kIntVReg, &intVal)) { + VLOG(jdwp) << "get byte local " << reg << " = " << intVal; + JDWP::Set1(buf_+1, intVal); + } else { + VLOG(jdwp) << "failed to get byte local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - case JDWP::JT_SHORT: - case JDWP::JT_CHAR: - { + case JDWP::JT_SHORT: + case JDWP::JT_CHAR: { CHECK_EQ(width_, 2U); - uint32_t intVal = GetVReg(m, reg, kIntVReg); - VLOG(jdwp) << "get short/char local " << reg << " = " << intVal; - JDWP::Set2BE(buf_+1, intVal); + uint32_t intVal; + if (GetVReg(m, reg, kIntVReg, &intVal)) { + VLOG(jdwp) << "get short/char local " << reg << " = " << intVal; + JDWP::Set2BE(buf_+1, intVal); + } else { + VLOG(jdwp) << "failed to get short/char local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - case JDWP::JT_INT: - { + case JDWP::JT_INT: { CHECK_EQ(width_, 4U); - uint32_t intVal = GetVReg(m, reg, kIntVReg); - VLOG(jdwp) << "get int local " << reg << " = " << intVal; - JDWP::Set4BE(buf_+1, intVal); + uint32_t intVal; + if (GetVReg(m, reg, kIntVReg, &intVal)) { + VLOG(jdwp) << "get int local " << reg << " = " << intVal; + JDWP::Set4BE(buf_+1, intVal); + } else { + VLOG(jdwp) << "failed to get int local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - case JDWP::JT_FLOAT: - { + case JDWP::JT_FLOAT: { CHECK_EQ(width_, 4U); - uint32_t intVal = GetVReg(m, reg, kFloatVReg); - VLOG(jdwp) << "get int/float local " << reg << " = " << intVal; - JDWP::Set4BE(buf_+1, intVal); - } - break; - case JDWP::JT_ARRAY: - { - CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - mirror::Object* o = reinterpret_cast(GetVReg(m, reg, kReferenceVReg)); - VLOG(jdwp) << "get array local " << reg << " = " << o; - if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { - LOG(FATAL) << "Register " << reg << " expected to hold array: " << o; + uint32_t intVal; + if (GetVReg(m, reg, kFloatVReg, &intVal)) { + VLOG(jdwp) << "get float local " << reg << " = " << intVal; + JDWP::Set4BE(buf_+1, intVal); + } else { + VLOG(jdwp) << "failed to get float local " << reg; + error_ = kFailureErrorCode; } - JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); + break; } - break; - case JDWP::JT_CLASS_LOADER: - case JDWP::JT_CLASS_OBJECT: - case JDWP::JT_OBJECT: - case JDWP::JT_STRING: - case JDWP::JT_THREAD: - case JDWP::JT_THREAD_GROUP: - { + case JDWP::JT_ARRAY: + case JDWP::JT_CLASS_LOADER: + case JDWP::JT_CLASS_OBJECT: + case JDWP::JT_OBJECT: + case JDWP::JT_STRING: + case JDWP::JT_THREAD: + case JDWP::JT_THREAD_GROUP: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - mirror::Object* o = reinterpret_cast(GetVReg(m, reg, kReferenceVReg)); - VLOG(jdwp) << "get object local " << reg << " = " << o; - if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { - LOG(FATAL) << "Register " << reg << " expected to hold object: " << o; + uint32_t intVal; + if (GetVReg(m, reg, kReferenceVReg, &intVal)) { + mirror::Object* o = reinterpret_cast(intVal); + VLOG(jdwp) << "get " << tag_ << " object local " << reg << " = " << o; + if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { + LOG(FATAL) << "Register " << reg << " expected to hold " << tag_ << " object: " << o; + } + tag_ = TagFromObject(soa_, o); + JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); + } else { + VLOG(jdwp) << "failed to get " << tag_ << " object local " << reg; + error_ = kFailureErrorCode; } - tag_ = TagFromObject(soa_, o); - JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); + break; } - break; - case JDWP::JT_DOUBLE: - { + case JDWP::JT_DOUBLE: { CHECK_EQ(width_, 8U); - uint32_t lo = GetVReg(m, reg, kDoubleLoVReg); - uint64_t hi = GetVReg(m, reg + 1, kDoubleHiVReg); - uint64_t longVal = (hi << 32) | lo; - VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal; - JDWP::Set8BE(buf_+1, longVal); + uint32_t lo; + uint32_t hi; + if (GetVReg(m, reg, kDoubleLoVReg, &lo) && GetVReg(m, reg + 1, kDoubleHiVReg, &hi)) { + uint64_t longVal = (static_cast(hi) << 32) | lo; + VLOG(jdwp) << "get double local " << reg << " = " + << hi << ":" << lo << " = " << longVal; + JDWP::Set8BE(buf_+1, longVal); + } else { + VLOG(jdwp) << "failed to get double local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - case JDWP::JT_LONG: - { + case JDWP::JT_LONG: { CHECK_EQ(width_, 8U); - uint32_t lo = GetVReg(m, reg, kLongLoVReg); - uint64_t hi = GetVReg(m, reg + 1, kLongHiVReg); - uint64_t longVal = (hi << 32) | lo; - VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal; - JDWP::Set8BE(buf_+1, longVal); + uint32_t lo; + uint32_t hi; + if (GetVReg(m, reg, kLongLoVReg, &lo) && GetVReg(m, reg + 1, kLongHiVReg, &hi)) { + uint64_t longVal = (static_cast(hi) << 32) | lo; + VLOG(jdwp) << "get long local " << reg << " = " + << hi << ":" << lo << " = " << longVal; + JDWP::Set8BE(buf_+1, longVal); + } else { + VLOG(jdwp) << "failed to get long local " << reg; + error_ = kFailureErrorCode; + } + break; } - break; - default: - LOG(FATAL) << "Unknown tag " << tag_; - break; + default: + LOG(FATAL) << "Unknown tag " << tag_; + break; } // Prepend tag, which may have been updated. @@ -2495,48 +2520,89 @@ JDWP::JdwpError Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame return false; } uint16_t reg = DemangleSlot(slot_, m); - + constexpr JDWP::JdwpError kFailureErrorCode = JDWP::ERR_ABSENT_INFORMATION; switch (tag_) { case JDWP::JT_BOOLEAN: case JDWP::JT_BYTE: CHECK_EQ(width_, 1U); - SetVReg(m, reg, static_cast(value_), kIntVReg); + if (!SetVReg(m, reg, static_cast(value_), kIntVReg)) { + VLOG(jdwp) << "failed to set boolean/byte local " << reg << " = " + << static_cast(value_); + error_ = kFailureErrorCode; + } break; case JDWP::JT_SHORT: case JDWP::JT_CHAR: CHECK_EQ(width_, 2U); - SetVReg(m, reg, static_cast(value_), kIntVReg); + if (!SetVReg(m, reg, static_cast(value_), kIntVReg)) { + VLOG(jdwp) << "failed to set short/char local " << reg << " = " + << static_cast(value_); + error_ = kFailureErrorCode; + } break; case JDWP::JT_INT: CHECK_EQ(width_, 4U); - SetVReg(m, reg, static_cast(value_), kIntVReg); + if (!SetVReg(m, reg, static_cast(value_), kIntVReg)) { + VLOG(jdwp) << "failed to set int local " << reg << " = " + << static_cast(value_); + error_ = kFailureErrorCode; + } break; case JDWP::JT_FLOAT: CHECK_EQ(width_, 4U); - SetVReg(m, reg, static_cast(value_), kFloatVReg); + if (!SetVReg(m, reg, static_cast(value_), kFloatVReg)) { + VLOG(jdwp) << "failed to set float local " << reg << " = " + << static_cast(value_); + error_ = kFailureErrorCode; + } break; case JDWP::JT_ARRAY: + case JDWP::JT_CLASS_LOADER: + case JDWP::JT_CLASS_OBJECT: case JDWP::JT_OBJECT: case JDWP::JT_STRING: - { + case JDWP::JT_THREAD: + case JDWP::JT_THREAD_GROUP: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); mirror::Object* o = gRegistry->Get(static_cast(value_)); if (o == ObjectRegistry::kInvalidObject) { - UNIMPLEMENTED(FATAL) << "return an error code when given an invalid object to store"; + VLOG(jdwp) << tag_ << " object " << o << " is an invalid object"; + error_ = JDWP::ERR_INVALID_OBJECT; + } else if (!SetVReg(m, reg, static_cast(reinterpret_cast(o)), + kReferenceVReg)) { + VLOG(jdwp) << "failed to set " << tag_ << " object local " << reg << " = " << o; + error_ = kFailureErrorCode; } - SetVReg(m, reg, static_cast(reinterpret_cast(o)), kReferenceVReg); + break; } - break; - case JDWP::JT_DOUBLE: + case JDWP::JT_DOUBLE: { CHECK_EQ(width_, 8U); - SetVReg(m, reg, static_cast(value_), kDoubleLoVReg); - SetVReg(m, reg + 1, static_cast(value_ >> 32), kDoubleHiVReg); + const uint32_t lo = static_cast(value_); + const uint32_t hi = static_cast(value_ >> 32); + bool success = SetVReg(m, reg, lo, kDoubleLoVReg); + success &= SetVReg(m, reg + 1, hi, kDoubleHiVReg); + if (!success) { + uint64_t longVal = (static_cast(hi) << 32) | lo; + VLOG(jdwp) << "failed to set double local " << reg << " = " + << hi << ":" << lo << " = " << longVal; + error_ = kFailureErrorCode; + } break; - case JDWP::JT_LONG: + } + case JDWP::JT_LONG: { CHECK_EQ(width_, 8U); - SetVReg(m, reg, static_cast(value_), kLongLoVReg); - SetVReg(m, reg + 1, static_cast(value_ >> 32), kLongHiVReg); + const uint32_t lo = static_cast(value_); + const uint32_t hi = static_cast(value_ >> 32); + bool success = SetVReg(m, reg, lo, kLongLoVReg); + success &= SetVReg(m, reg + 1, hi, kLongHiVReg); + if (!success) { + uint64_t longVal = (static_cast(hi) << 32) | lo; + VLOG(jdwp) << "failed to set double local " << reg << " = " + << hi << ":" << lo << " = " << longVal; + error_ = kFailureErrorCode; + } break; + } default: LOG(FATAL) << "Unknown tag " << tag_; break; diff --git a/runtime/stack.cc b/runtime/stack.cc index 7e922c5..132ac3e 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,30 @@ 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); + uintptr_t ptr_val; + bool success = false; + if (is_float) { + success = GetFPR(reg, &ptr_val); + } else { + success = GetGPR(reg, &ptr_val); + } + *val = ptr_val; + return success; } 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 +193,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 +206,11 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val frame_info.FrameSizeInBytes(), vreg, kRuntimeISA); byte* vreg_addr = reinterpret_cast(GetCurrentQuickFrame()) + offset; *reinterpret_cast(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 +219,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 { diff --git a/runtime/stack.h b/runtime/stack.h index 1991115..9402cdd 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -561,15 +561,21 @@ class StackVisitor { bool GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint32_t GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind) const + bool GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) + uint32_t GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uint32_t val; + bool success = GetVReg(m, vreg, kind, &val); + CHECK(success) << "Failed to read vreg " << vreg << " of kind " << kind; + return val; + } + + bool SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); uintptr_t* GetGPRAddress(uint32_t reg) const; - uintptr_t GetGPR(uint32_t reg) const; - void SetGPR(uint32_t reg, uintptr_t value); // This is a fast-path for getting/setting values in a quick frame. uint32_t* GetVRegAddr(StackReference* cur_quick_frame, @@ -700,6 +706,11 @@ class StackVisitor { StackVisitor(Thread* thread, Context* context, size_t num_frames) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool GetGPR(uint32_t reg, uintptr_t* val) const; + bool SetGPR(uint32_t reg, uintptr_t value); + bool GetFPR(uint32_t reg, uintptr_t* val) const; + bool SetFPR(uint32_t reg, uintptr_t value); + instrumentation::InstrumentationStackFrame& GetInstrumentationStackFrame(uint32_t depth) const; void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -- cgit v1.1