platform_system_core/libunwindstack/tests/RegsIterateTest.cpp
Ryan Savitski 92237bad6a unwindstack: RegsArm64: fix harmless off by 1 + iterate GPRs contiguously
The memcpy should be for 31 GPRs, [x0, x30]. Currently it (accidentally)
also copies over the SP register (which ends up being harmless, as the
layouts match, and the value is reassigned again anyway).

Separately, I'm including an optional change for the iteration order,
since LR is the x30 GPR, it makes slightly more sense to print it
immediately after x29. However, this is a change in behaviour, so I can
undo the change if you think it's not worth it.

Tested: atest libunwindstack_unit_test
Change-Id: Ib6b81f8ee3a9a526bfabe4b09b327f083c855fb8
2020-01-24 19:50:45 +00:00

257 lines
8.8 KiB
C++

/*
* Copyright (C) 2017 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 <utility>
#include <type_traits>
#include <vector>
#include <gtest/gtest.h>
#include <unwindstack/Elf.h>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/MachineArm.h>
#include <unwindstack/MachineArm64.h>
#include <unwindstack/MachineMips.h>
#include <unwindstack/MachineMips64.h>
#include <unwindstack/MachineX86.h>
#include <unwindstack/MachineX86_64.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/RegsArm.h>
#include <unwindstack/RegsArm64.h>
#include <unwindstack/RegsMips.h>
#include <unwindstack/RegsMips64.h>
#include <unwindstack/RegsX86.h>
#include <unwindstack/RegsX86_64.h>
namespace unwindstack {
struct Register {
std::string expected_name;
uint64_t offset;
bool operator==(const Register& rhs) const {
return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset);
}
};
template<typename T>
class RegsIterateTest : public ::testing::Test {
};
template<typename RegsType>
std::vector<Register> ExpectedRegisters();
template<>
std::vector<Register> ExpectedRegisters<RegsArm>() {
std::vector<Register> result;
result.push_back({"r0", ARM_REG_R0});
result.push_back({"r1", ARM_REG_R1});
result.push_back({"r2", ARM_REG_R2});
result.push_back({"r3", ARM_REG_R3});
result.push_back({"r4", ARM_REG_R4});
result.push_back({"r5", ARM_REG_R5});
result.push_back({"r6", ARM_REG_R6});
result.push_back({"r7", ARM_REG_R7});
result.push_back({"r8", ARM_REG_R8});
result.push_back({"r9", ARM_REG_R9});
result.push_back({"r10", ARM_REG_R10});
result.push_back({"r11", ARM_REG_R11});
result.push_back({"ip", ARM_REG_R12});
result.push_back({"sp", ARM_REG_SP});
result.push_back({"lr", ARM_REG_LR});
result.push_back({"pc", ARM_REG_PC});
return result;
}
template<>
std::vector<Register> ExpectedRegisters<RegsArm64>() {
std::vector<Register> result;
result.push_back({"x0", ARM64_REG_R0});
result.push_back({"x1", ARM64_REG_R1});
result.push_back({"x2", ARM64_REG_R2});
result.push_back({"x3", ARM64_REG_R3});
result.push_back({"x4", ARM64_REG_R4});
result.push_back({"x5", ARM64_REG_R5});
result.push_back({"x6", ARM64_REG_R6});
result.push_back({"x7", ARM64_REG_R7});
result.push_back({"x8", ARM64_REG_R8});
result.push_back({"x9", ARM64_REG_R9});
result.push_back({"x10", ARM64_REG_R10});
result.push_back({"x11", ARM64_REG_R11});
result.push_back({"x12", ARM64_REG_R12});
result.push_back({"x13", ARM64_REG_R13});
result.push_back({"x14", ARM64_REG_R14});
result.push_back({"x15", ARM64_REG_R15});
result.push_back({"x16", ARM64_REG_R16});
result.push_back({"x17", ARM64_REG_R17});
result.push_back({"x18", ARM64_REG_R18});
result.push_back({"x19", ARM64_REG_R19});
result.push_back({"x20", ARM64_REG_R20});
result.push_back({"x21", ARM64_REG_R21});
result.push_back({"x22", ARM64_REG_R22});
result.push_back({"x23", ARM64_REG_R23});
result.push_back({"x24", ARM64_REG_R24});
result.push_back({"x25", ARM64_REG_R25});
result.push_back({"x26", ARM64_REG_R26});
result.push_back({"x27", ARM64_REG_R27});
result.push_back({"x28", ARM64_REG_R28});
result.push_back({"x29", ARM64_REG_R29});
result.push_back({"lr", ARM64_REG_LR});
result.push_back({"sp", ARM64_REG_SP});
result.push_back({"pc", ARM64_REG_PC});
result.push_back({"pst", ARM64_REG_PSTATE});
return result;
}
template<>
std::vector<Register> ExpectedRegisters<RegsX86>() {
std::vector<Register> result;
result.push_back({"eax", X86_REG_EAX});
result.push_back({"ebx", X86_REG_EBX});
result.push_back({"ecx", X86_REG_ECX});
result.push_back({"edx", X86_REG_EDX});
result.push_back({"ebp", X86_REG_EBP});
result.push_back({"edi", X86_REG_EDI});
result.push_back({"esi", X86_REG_ESI});
result.push_back({"esp", X86_REG_ESP});
result.push_back({"eip", X86_REG_EIP});
return result;
}
template<>
std::vector<Register> ExpectedRegisters<RegsX86_64>() {
std::vector<Register> result;
result.push_back({"rax", X86_64_REG_RAX});
result.push_back({"rbx", X86_64_REG_RBX});
result.push_back({"rcx", X86_64_REG_RCX});
result.push_back({"rdx", X86_64_REG_RDX});
result.push_back({"r8", X86_64_REG_R8});
result.push_back({"r9", X86_64_REG_R9});
result.push_back({"r10", X86_64_REG_R10});
result.push_back({"r11", X86_64_REG_R11});
result.push_back({"r12", X86_64_REG_R12});
result.push_back({"r13", X86_64_REG_R13});
result.push_back({"r14", X86_64_REG_R14});
result.push_back({"r15", X86_64_REG_R15});
result.push_back({"rdi", X86_64_REG_RDI});
result.push_back({"rsi", X86_64_REG_RSI});
result.push_back({"rbp", X86_64_REG_RBP});
result.push_back({"rsp", X86_64_REG_RSP});
result.push_back({"rip", X86_64_REG_RIP});
return result;
}
template<>
std::vector<Register> ExpectedRegisters<RegsMips>() {
std::vector<Register> result;
result.push_back({"r0", MIPS_REG_R0});
result.push_back({"r1", MIPS_REG_R1});
result.push_back({"r2", MIPS_REG_R2});
result.push_back({"r3", MIPS_REG_R3});
result.push_back({"r4", MIPS_REG_R4});
result.push_back({"r5", MIPS_REG_R5});
result.push_back({"r6", MIPS_REG_R6});
result.push_back({"r7", MIPS_REG_R7});
result.push_back({"r8", MIPS_REG_R8});
result.push_back({"r9", MIPS_REG_R9});
result.push_back({"r10", MIPS_REG_R10});
result.push_back({"r11", MIPS_REG_R11});
result.push_back({"r12", MIPS_REG_R12});
result.push_back({"r13", MIPS_REG_R13});
result.push_back({"r14", MIPS_REG_R14});
result.push_back({"r15", MIPS_REG_R15});
result.push_back({"r16", MIPS_REG_R16});
result.push_back({"r17", MIPS_REG_R17});
result.push_back({"r18", MIPS_REG_R18});
result.push_back({"r19", MIPS_REG_R19});
result.push_back({"r20", MIPS_REG_R20});
result.push_back({"r21", MIPS_REG_R21});
result.push_back({"r22", MIPS_REG_R22});
result.push_back({"r23", MIPS_REG_R23});
result.push_back({"r24", MIPS_REG_R24});
result.push_back({"r25", MIPS_REG_R25});
result.push_back({"r26", MIPS_REG_R26});
result.push_back({"r27", MIPS_REG_R27});
result.push_back({"r28", MIPS_REG_R28});
result.push_back({"sp", MIPS_REG_SP});
result.push_back({"r30", MIPS_REG_R30});
result.push_back({"ra", MIPS_REG_RA});
result.push_back({"pc", MIPS_REG_PC});
return result;
}
template<>
std::vector<Register> ExpectedRegisters<RegsMips64>() {
std::vector<Register> result;
result.push_back({"r0", MIPS64_REG_R0});
result.push_back({"r1", MIPS64_REG_R1});
result.push_back({"r2", MIPS64_REG_R2});
result.push_back({"r3", MIPS64_REG_R3});
result.push_back({"r4", MIPS64_REG_R4});
result.push_back({"r5", MIPS64_REG_R5});
result.push_back({"r6", MIPS64_REG_R6});
result.push_back({"r7", MIPS64_REG_R7});
result.push_back({"r8", MIPS64_REG_R8});
result.push_back({"r9", MIPS64_REG_R9});
result.push_back({"r10", MIPS64_REG_R10});
result.push_back({"r11", MIPS64_REG_R11});
result.push_back({"r12", MIPS64_REG_R12});
result.push_back({"r13", MIPS64_REG_R13});
result.push_back({"r14", MIPS64_REG_R14});
result.push_back({"r15", MIPS64_REG_R15});
result.push_back({"r16", MIPS64_REG_R16});
result.push_back({"r17", MIPS64_REG_R17});
result.push_back({"r18", MIPS64_REG_R18});
result.push_back({"r19", MIPS64_REG_R19});
result.push_back({"r20", MIPS64_REG_R20});
result.push_back({"r21", MIPS64_REG_R21});
result.push_back({"r22", MIPS64_REG_R22});
result.push_back({"r23", MIPS64_REG_R23});
result.push_back({"r24", MIPS64_REG_R24});
result.push_back({"r25", MIPS64_REG_R25});
result.push_back({"r26", MIPS64_REG_R26});
result.push_back({"r27", MIPS64_REG_R27});
result.push_back({"r28", MIPS64_REG_R28});
result.push_back({"sp", MIPS64_REG_SP});
result.push_back({"r30", MIPS64_REG_R30});
result.push_back({"ra", MIPS64_REG_RA});
result.push_back({"pc", MIPS64_REG_PC});
return result;
}
using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64, RegsMips, RegsMips64>;
TYPED_TEST_SUITE(RegsIterateTest, RegTypes);
TYPED_TEST(RegsIterateTest, iterate) {
std::vector<Register> expected = ExpectedRegisters<TypeParam>();
TypeParam regs;
for (const auto& reg : expected) {
regs[reg.offset] = reg.offset;
}
std::vector<Register> actual;
regs.IterateRegisters([&actual](const char* name, uint64_t value) {
actual.push_back({name, value});
});
ASSERT_EQ(expected, actual);
}
} // namespace unwindstack