summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2018-08-02 15:21:37 -0700
committerChristopher Ferris <cferris@google.com>2018-08-02 18:01:02 -0700
commit7c33b3bece9606b4ea88772ee6c8454baec4f867 (patch)
tree62c31edce3f8f4d09e8535dd6738ca28fd9c6d02
parentfdbf49e578e046afdfa95a033417e8b9e2064b02 (diff)
downloadunwinding-7c33b3bece9606b4ea88772ee6c8454baec4f867.tar.gz
Fix incorrect left shifts.
Bug: 112142060 Test: New unit tests pass. Change-Id: I0c47b22582f0bf75ab503364a337c7de4de3ec43
-rw-r--r--libunwindstack/Android.bp1
-rw-r--r--libunwindstack/RegsInfo.h20
-rw-r--r--libunwindstack/tests/RegsInfoTest.cpp85
3 files changed, 97 insertions, 9 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index df5da65..be2145d 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -190,6 +190,7 @@ cc_test {
"tests/MemoryRangeTest.cpp",
"tests/MemoryRemoteTest.cpp",
"tests/MemoryTest.cpp",
+ "tests/RegsInfoTest.cpp",
"tests/RegsIterateTest.cpp",
"tests/RegsStepIfSignalHandlerTest.cpp",
"tests/RegsTest.cpp",
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index 47825f5..e6dd33c 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -25,11 +25,13 @@ namespace unwindstack {
template <typename AddressType>
struct RegsInfo {
+ static constexpr size_t MAX_REGISTERS = 64;
+
RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
RegsImpl<AddressType>* regs = nullptr;
uint64_t saved_reg_map = 0;
- AddressType saved_regs[64];
+ AddressType saved_regs[MAX_REGISTERS];
inline AddressType Get(uint32_t reg) {
if (IsSaved(reg)) {
@@ -39,23 +41,23 @@ struct RegsInfo {
}
inline AddressType* Save(uint32_t reg) {
- if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
- // This should never happen as since all currently supported
- // architectures have the total number of registers < 64.
+ if (reg > MAX_REGISTERS) {
+ // This should never happen since all currently supported
+ // architectures have < 64 total registers.
abort();
}
- saved_reg_map |= 1 << reg;
+ saved_reg_map |= 1ULL << reg;
saved_regs[reg] = (*regs)[reg];
return &(*regs)[reg];
}
inline bool IsSaved(uint32_t reg) {
- if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
- // This should never happen as since all currently supported
- // architectures have the total number of registers < 64.
+ if (reg > MAX_REGISTERS) {
+ // This should never happen since all currently supported
+ // architectures have < 64 total registers.
abort();
}
- return saved_reg_map & (1 << reg);
+ return saved_reg_map & (1ULL << reg);
}
inline uint16_t Total() { return regs->total_regs(); }
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
new file mode 100644
index 0000000..052b5bf
--- /dev/null
+++ b/libunwindstack/tests/RegsInfoTest.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Regs.h>
+
+#include "RegsFake.h"
+#include "RegsInfo.h"
+
+namespace unwindstack {
+
+TEST(RegsInfoTest, single_uint32_t) {
+ RegsImplFake<uint32_t> regs(10);
+ RegsInfo<uint32_t> info(&regs);
+
+ regs[1] = 0x100;
+ ASSERT_FALSE(info.IsSaved(1));
+ ASSERT_EQ(0x100U, info.Get(1));
+ ASSERT_EQ(10, info.Total());
+
+ uint32_t* value = info.Save(1);
+ ASSERT_EQ(value, &regs[1]);
+ regs[1] = 0x200;
+ ASSERT_TRUE(info.IsSaved(1));
+ ASSERT_EQ(0x100U, info.Get(1));
+ ASSERT_EQ(0x200U, regs[1]);
+}
+
+TEST(RegsInfoTest, single_uint64_t) {
+ RegsImplFake<uint64_t> regs(20);
+ RegsInfo<uint64_t> info(&regs);
+
+ regs[3] = 0x300;
+ ASSERT_FALSE(info.IsSaved(3));
+ ASSERT_EQ(0x300U, info.Get(3));
+ ASSERT_EQ(20, info.Total());
+
+ uint64_t* value = info.Save(3);
+ ASSERT_EQ(value, &regs[3]);
+ regs[3] = 0x400;
+ ASSERT_TRUE(info.IsSaved(3));
+ ASSERT_EQ(0x300U, info.Get(3));
+ ASSERT_EQ(0x400U, regs[3]);
+}
+
+TEST(RegsInfoTest, all) {
+ RegsImplFake<uint64_t> regs(64);
+ RegsInfo<uint64_t> info(&regs);
+
+ for (uint32_t i = 0; i < 64; i++) {
+ regs[i] = i * 0x100;
+ ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+ }
+
+ for (uint32_t i = 0; i < 64; i++) {
+ ASSERT_FALSE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+ uint64_t* reg = info.Save(i);
+ ASSERT_EQ(reg, &regs[i]) << "Reg " + std::to_string(i) + " failed.";
+ *reg = i * 0x1000 + 0x100;
+ ASSERT_EQ(i * 0x1000 + 0x100, regs[i]) << "Reg " + std::to_string(i) + " failed.";
+ }
+
+ for (uint32_t i = 0; i < 64; i++) {
+ ASSERT_TRUE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
+ ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
+ }
+}
+
+} // namespace unwindstack