diff options
author | Christopher Ferris <cferris@google.com> | 2018-08-02 15:21:37 -0700 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-08-02 18:01:02 -0700 |
commit | 2786608743727506c8ab614905e4032e66db1427 (patch) | |
tree | 1f11e223b642620c78fe09170eb0b57c2b56ca39 /libunwindstack | |
parent | d52b17ff0a559334dd6791e5a9533e4cfdac9446 (diff) | |
download | system_core-2786608743727506c8ab614905e4032e66db1427.tar.gz system_core-2786608743727506c8ab614905e4032e66db1427.tar.bz2 system_core-2786608743727506c8ab614905e4032e66db1427.zip |
Fix incorrect left shifts.
Bug: 112142060
Test: New unit tests pass.
Change-Id: I0c47b22582f0bf75ab503364a337c7de4de3ec43
Diffstat (limited to 'libunwindstack')
-rw-r--r-- | libunwindstack/Android.bp | 1 | ||||
-rw-r--r-- | libunwindstack/RegsInfo.h | 20 | ||||
-rw-r--r-- | libunwindstack/tests/RegsInfoTest.cpp | 85 |
3 files changed, 97 insertions, 9 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index df5da650c..be2145d03 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 47825f534..e6dd33c1b 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 000000000..052b5bf05 --- /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(®s); + + 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, ®s[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(®s); + + 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, ®s[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(®s); + + 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, ®s[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 |