summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-06-17 15:52:45 +0200
committerSebastien Hertz <shertz@google.com>2014-06-17 16:00:54 +0200
commit0bcb2902ec21393d71c94e63aa6733cb5311a0cc (patch)
tree10beb60b5a8d212afdf0e7e58c5dfcbee691be2e
parent838b38fa3b2fb4a64f8a316459d372020f6e8feb (diff)
downloadart-0bcb2902ec21393d71c94e63aa6733cb5311a0cc.zip
art-0bcb2902ec21393d71c94e63aa6733cb5311a0cc.tar.gz
art-0bcb2902ec21393d71c94e63aa6733cb5311a0cc.tar.bz2
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
-rw-r--r--runtime/arch/arm/context_arm.cc39
-rw-r--r--runtime/arch/arm/context_arm.h46
-rw-r--r--runtime/arch/arm64/context_arm64.cc113
-rw-r--r--runtime/arch/arm64/context_arm64.h46
-rw-r--r--runtime/arch/context.h28
-rw-r--r--runtime/arch/mips/context_mips.cc37
-rw-r--r--runtime/arch/mips/context_mips.h46
-rw-r--r--runtime/arch/x86/context_x86.cc20
-rw-r--r--runtime/arch/x86/context_x86.h39
-rw-r--r--runtime/arch/x86_64/context_x86_64.cc25
-rw-r--r--runtime/arch/x86_64/context_x86_64.h42
-rw-r--r--runtime/debugger.cc246
-rw-r--r--runtime/stack.cc52
-rw-r--r--runtime/stack.h19
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<uint32_t>(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<uint32_t>(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<uint32_t*>(&gZero);
gprs_[R1] = const_cast<uint32_t*>(&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<uintptr_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint64_t*>(&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<uintptr_t>(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<uint32_t>(kNumberOfCoreRegisters));
return gprs_[reg];
}
- uintptr_t GetGPR(uint32_t reg) {
+ bool GetGPR(uint32_t reg, uintptr_t* val) OVERRIDE {
DCHECK_LT(reg, static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t*>(&gZero);
gprs_[V1] = const_cast<uint32_t*>(&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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uintptr_t*>(&gZero);
gprs_[EDX] = const_cast<uintptr_t*>(&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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<mirror::Object*>(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<mirror::Object*>(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<mirror::Object*>(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<uint64_t>(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<uint64_t>(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<uint32_t>(value_), kIntVReg);
+ if (!SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg)) {
+ VLOG(jdwp) << "failed to set boolean/byte local " << reg << " = "
+ << static_cast<uint32_t>(value_);
+ error_ = kFailureErrorCode;
+ }
break;
case JDWP::JT_SHORT:
case JDWP::JT_CHAR:
CHECK_EQ(width_, 2U);
- SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg);
+ if (!SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg)) {
+ VLOG(jdwp) << "failed to set short/char local " << reg << " = "
+ << static_cast<uint32_t>(value_);
+ error_ = kFailureErrorCode;
+ }
break;
case JDWP::JT_INT:
CHECK_EQ(width_, 4U);
- SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg);
+ if (!SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg)) {
+ VLOG(jdwp) << "failed to set int local " << reg << " = "
+ << static_cast<uint32_t>(value_);
+ error_ = kFailureErrorCode;
+ }
break;
case JDWP::JT_FLOAT:
CHECK_EQ(width_, 4U);
- SetVReg(m, reg, static_cast<uint32_t>(value_), kFloatVReg);
+ if (!SetVReg(m, reg, static_cast<uint32_t>(value_), kFloatVReg)) {
+ VLOG(jdwp) << "failed to set float local " << reg << " = "
+ << static_cast<uint32_t>(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<mirror::Object*>(static_cast<JDWP::ObjectId>(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<uint32_t>(reinterpret_cast<uintptr_t>(o)),
+ kReferenceVReg)) {
+ VLOG(jdwp) << "failed to set " << tag_ << " object local " << reg << " = " << o;
+ error_ = kFailureErrorCode;
}
- SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)), kReferenceVReg);
+ break;
}
- break;
- case JDWP::JT_DOUBLE:
+ case JDWP::JT_DOUBLE: {
CHECK_EQ(width_, 8U);
- SetVReg(m, reg, static_cast<uint32_t>(value_), kDoubleLoVReg);
- SetVReg(m, reg + 1, static_cast<uint32_t>(value_ >> 32), kDoubleHiVReg);
+ const uint32_t lo = static_cast<uint32_t>(value_);
+ const uint32_t hi = static_cast<uint32_t>(value_ >> 32);
+ bool success = SetVReg(m, reg, lo, kDoubleLoVReg);
+ success &= SetVReg(m, reg + 1, hi, kDoubleHiVReg);
+ if (!success) {
+ uint64_t longVal = (static_cast<uint64_t>(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<uint32_t>(value_), kLongLoVReg);
- SetVReg(m, reg + 1, static_cast<uint32_t>(value_ >> 32), kLongHiVReg);
+ const uint32_t lo = static_cast<uint32_t>(value_);
+ const uint32_t hi = static_cast<uint32_t>(value_ >> 32);
+ bool success = SetVReg(m, reg, lo, kLongLoVReg);
+ success &= SetVReg(m, reg + 1, hi, kLongHiVReg);
+ if (!success) {
+ uint64_t longVal = (static_cast<uint64_t>(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<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 +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<mirror::ArtMethod>* 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_);