1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdint.h>
18
19 #include <utility>
20 #include <type_traits>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24
25 #include <unwindstack/Elf.h>
26 #include <unwindstack/ElfInterface.h>
27 #include <unwindstack/MachineArm.h>
28 #include <unwindstack/MachineArm64.h>
29 #include <unwindstack/MachineRiscv64.h>
30 #include <unwindstack/MachineX86.h>
31 #include <unwindstack/MachineX86_64.h>
32 #include <unwindstack/MapInfo.h>
33 #include <unwindstack/RegsArm.h>
34 #include <unwindstack/RegsArm64.h>
35 #include <unwindstack/RegsRiscv64.h>
36 #include <unwindstack/RegsX86.h>
37 #include <unwindstack/RegsX86_64.h>
38
39 namespace unwindstack {
40
41 struct Register {
42 std::string expected_name;
43 uint64_t offset;
44
operator ==unwindstack::Register45 bool operator==(const Register& rhs) const {
46 return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset);
47 }
48 };
49
50 template<typename T>
51 class RegsIterateTest : public ::testing::Test {
52 };
53
54 template<typename RegsType>
55 std::vector<Register> ExpectedRegisters();
56
57 template<>
ExpectedRegisters()58 std::vector<Register> ExpectedRegisters<RegsArm>() {
59 std::vector<Register> result;
60 result.push_back({"r0", ARM_REG_R0});
61 result.push_back({"r1", ARM_REG_R1});
62 result.push_back({"r2", ARM_REG_R2});
63 result.push_back({"r3", ARM_REG_R3});
64 result.push_back({"r4", ARM_REG_R4});
65 result.push_back({"r5", ARM_REG_R5});
66 result.push_back({"r6", ARM_REG_R6});
67 result.push_back({"r7", ARM_REG_R7});
68 result.push_back({"r8", ARM_REG_R8});
69 result.push_back({"r9", ARM_REG_R9});
70 result.push_back({"r10", ARM_REG_R10});
71 result.push_back({"r11", ARM_REG_R11});
72 result.push_back({"ip", ARM_REG_R12});
73 result.push_back({"sp", ARM_REG_SP});
74 result.push_back({"lr", ARM_REG_LR});
75 result.push_back({"pc", ARM_REG_PC});
76 return result;
77 }
78
79 template<>
ExpectedRegisters()80 std::vector<Register> ExpectedRegisters<RegsArm64>() {
81 std::vector<Register> result;
82 result.push_back({"x0", ARM64_REG_R0});
83 result.push_back({"x1", ARM64_REG_R1});
84 result.push_back({"x2", ARM64_REG_R2});
85 result.push_back({"x3", ARM64_REG_R3});
86 result.push_back({"x4", ARM64_REG_R4});
87 result.push_back({"x5", ARM64_REG_R5});
88 result.push_back({"x6", ARM64_REG_R6});
89 result.push_back({"x7", ARM64_REG_R7});
90 result.push_back({"x8", ARM64_REG_R8});
91 result.push_back({"x9", ARM64_REG_R9});
92 result.push_back({"x10", ARM64_REG_R10});
93 result.push_back({"x11", ARM64_REG_R11});
94 result.push_back({"x12", ARM64_REG_R12});
95 result.push_back({"x13", ARM64_REG_R13});
96 result.push_back({"x14", ARM64_REG_R14});
97 result.push_back({"x15", ARM64_REG_R15});
98 result.push_back({"x16", ARM64_REG_R16});
99 result.push_back({"x17", ARM64_REG_R17});
100 result.push_back({"x18", ARM64_REG_R18});
101 result.push_back({"x19", ARM64_REG_R19});
102 result.push_back({"x20", ARM64_REG_R20});
103 result.push_back({"x21", ARM64_REG_R21});
104 result.push_back({"x22", ARM64_REG_R22});
105 result.push_back({"x23", ARM64_REG_R23});
106 result.push_back({"x24", ARM64_REG_R24});
107 result.push_back({"x25", ARM64_REG_R25});
108 result.push_back({"x26", ARM64_REG_R26});
109 result.push_back({"x27", ARM64_REG_R27});
110 result.push_back({"x28", ARM64_REG_R28});
111 result.push_back({"x29", ARM64_REG_R29});
112 result.push_back({"lr", ARM64_REG_LR});
113 result.push_back({"sp", ARM64_REG_SP});
114 result.push_back({"pc", ARM64_REG_PC});
115 result.push_back({"pst", ARM64_REG_PSTATE});
116 return result;
117 }
118
119 template<>
ExpectedRegisters()120 std::vector<Register> ExpectedRegisters<RegsX86>() {
121 std::vector<Register> result;
122 result.push_back({"eax", X86_REG_EAX});
123 result.push_back({"ebx", X86_REG_EBX});
124 result.push_back({"ecx", X86_REG_ECX});
125 result.push_back({"edx", X86_REG_EDX});
126 result.push_back({"ebp", X86_REG_EBP});
127 result.push_back({"edi", X86_REG_EDI});
128 result.push_back({"esi", X86_REG_ESI});
129 result.push_back({"esp", X86_REG_ESP});
130 result.push_back({"eip", X86_REG_EIP});
131 return result;
132 }
133
134 template<>
ExpectedRegisters()135 std::vector<Register> ExpectedRegisters<RegsX86_64>() {
136 std::vector<Register> result;
137 result.push_back({"rax", X86_64_REG_RAX});
138 result.push_back({"rbx", X86_64_REG_RBX});
139 result.push_back({"rcx", X86_64_REG_RCX});
140 result.push_back({"rdx", X86_64_REG_RDX});
141 result.push_back({"r8", X86_64_REG_R8});
142 result.push_back({"r9", X86_64_REG_R9});
143 result.push_back({"r10", X86_64_REG_R10});
144 result.push_back({"r11", X86_64_REG_R11});
145 result.push_back({"r12", X86_64_REG_R12});
146 result.push_back({"r13", X86_64_REG_R13});
147 result.push_back({"r14", X86_64_REG_R14});
148 result.push_back({"r15", X86_64_REG_R15});
149 result.push_back({"rdi", X86_64_REG_RDI});
150 result.push_back({"rsi", X86_64_REG_RSI});
151 result.push_back({"rbp", X86_64_REG_RBP});
152 result.push_back({"rsp", X86_64_REG_RSP});
153 result.push_back({"rip", X86_64_REG_RIP});
154 return result;
155 }
156
157 template <>
ExpectedRegisters()158 std::vector<Register> ExpectedRegisters<RegsRiscv64>() {
159 std::vector<Register> result;
160 result.push_back({"pc", RISCV64_REG_PC});
161 result.push_back({"ra", RISCV64_REG_RA});
162 result.push_back({"sp", RISCV64_REG_SP});
163 result.push_back({"gp", RISCV64_REG_GP});
164 result.push_back({"tp", RISCV64_REG_TP});
165 result.push_back({"t0", RISCV64_REG_T0});
166 result.push_back({"t1", RISCV64_REG_T1});
167 result.push_back({"t2", RISCV64_REG_T2});
168 result.push_back({"t3", RISCV64_REG_T3});
169 result.push_back({"t4", RISCV64_REG_T4});
170 result.push_back({"t5", RISCV64_REG_T5});
171 result.push_back({"t6", RISCV64_REG_T6});
172 result.push_back({"s0", RISCV64_REG_S0});
173 result.push_back({"s1", RISCV64_REG_S1});
174 result.push_back({"s2", RISCV64_REG_S2});
175 result.push_back({"s3", RISCV64_REG_S3});
176 result.push_back({"s4", RISCV64_REG_S4});
177 result.push_back({"s5", RISCV64_REG_S5});
178 result.push_back({"s6", RISCV64_REG_S6});
179 result.push_back({"s7", RISCV64_REG_S7});
180 result.push_back({"s8", RISCV64_REG_S8});
181 result.push_back({"s9", RISCV64_REG_S9});
182 result.push_back({"s10", RISCV64_REG_S10});
183 result.push_back({"s11", RISCV64_REG_S11});
184 result.push_back({"a0", RISCV64_REG_A0});
185 result.push_back({"a1", RISCV64_REG_A1});
186 result.push_back({"a2", RISCV64_REG_A2});
187 result.push_back({"a3", RISCV64_REG_A3});
188 result.push_back({"a4", RISCV64_REG_A4});
189 result.push_back({"a5", RISCV64_REG_A5});
190 result.push_back({"a6", RISCV64_REG_A6});
191 result.push_back({"a7", RISCV64_REG_A7});
192 result.push_back({"vlenb", RISCV64_REG_VLENB});
193
194 return result;
195 }
196
197 using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64, RegsRiscv64>;
198 TYPED_TEST_SUITE(RegsIterateTest, RegTypes);
199
TYPED_TEST(RegsIterateTest,iterate)200 TYPED_TEST(RegsIterateTest, iterate) {
201 std::vector<Register> expected = ExpectedRegisters<TypeParam>();
202 TypeParam regs;
203 for (const auto& reg : expected) {
204 regs[reg.offset] = reg.offset;
205 }
206
207 std::vector<Register> actual;
208 regs.IterateRegisters([&actual](const char* name, uint64_t value) {
209 actual.push_back({name, value});
210 });
211
212 ASSERT_EQ(expected, actual);
213 }
214
215 } // namespace unwindstack
216