92237bad6a
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
257 lines
8.8 KiB
C++
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
|