Josh Gao | 6f580d8 | 2017-09-22 12:57:15 -0700 | [diff] [blame] | 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> |
Christopher Ferris | 5391416 | 2018-02-08 19:27:47 -0800 | [diff] [blame] | 27 | #include <unwindstack/MachineArm.h> |
| 28 | #include <unwindstack/MachineArm64.h> |
| 29 | #include <unwindstack/MachineMips.h> |
| 30 | #include <unwindstack/MachineMips64.h> |
| 31 | #include <unwindstack/MachineX86.h> |
| 32 | #include <unwindstack/MachineX86_64.h> |
Josh Gao | 6f580d8 | 2017-09-22 12:57:15 -0700 | [diff] [blame] | 33 | #include <unwindstack/MapInfo.h> |
Christopher Ferris | d06001d | 2017-11-30 18:56:01 -0800 | [diff] [blame] | 34 | #include <unwindstack/RegsArm.h> |
| 35 | #include <unwindstack/RegsArm64.h> |
Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 36 | #include <unwindstack/RegsMips.h> |
| 37 | #include <unwindstack/RegsMips64.h> |
Christopher Ferris | 5391416 | 2018-02-08 19:27:47 -0800 | [diff] [blame] | 38 | #include <unwindstack/RegsX86.h> |
| 39 | #include <unwindstack/RegsX86_64.h> |
Josh Gao | 6f580d8 | 2017-09-22 12:57:15 -0700 | [diff] [blame] | 40 | |
| 41 | namespace unwindstack { |
| 42 | |
| 43 | struct Register { |
| 44 | std::string expected_name; |
| 45 | uint64_t offset; |
| 46 | |
| 47 | bool operator==(const Register& rhs) const { |
| 48 | return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset); |
| 49 | } |
| 50 | }; |
| 51 | |
| 52 | template<typename T> |
| 53 | class RegsIterateTest : public ::testing::Test { |
| 54 | }; |
| 55 | |
| 56 | template<typename RegsType> |
| 57 | std::vector<Register> ExpectedRegisters(); |
| 58 | |
| 59 | template<> |
| 60 | std::vector<Register> ExpectedRegisters<RegsArm>() { |
| 61 | std::vector<Register> result; |
| 62 | result.push_back({"r0", ARM_REG_R0}); |
| 63 | result.push_back({"r1", ARM_REG_R1}); |
| 64 | result.push_back({"r2", ARM_REG_R2}); |
| 65 | result.push_back({"r3", ARM_REG_R3}); |
| 66 | result.push_back({"r4", ARM_REG_R4}); |
| 67 | result.push_back({"r5", ARM_REG_R5}); |
| 68 | result.push_back({"r6", ARM_REG_R6}); |
| 69 | result.push_back({"r7", ARM_REG_R7}); |
| 70 | result.push_back({"r8", ARM_REG_R8}); |
| 71 | result.push_back({"r9", ARM_REG_R9}); |
| 72 | result.push_back({"r10", ARM_REG_R10}); |
| 73 | result.push_back({"r11", ARM_REG_R11}); |
| 74 | result.push_back({"ip", ARM_REG_R12}); |
| 75 | result.push_back({"sp", ARM_REG_SP}); |
| 76 | result.push_back({"lr", ARM_REG_LR}); |
| 77 | result.push_back({"pc", ARM_REG_PC}); |
| 78 | return result; |
| 79 | } |
| 80 | |
| 81 | template<> |
| 82 | std::vector<Register> ExpectedRegisters<RegsArm64>() { |
| 83 | std::vector<Register> result; |
| 84 | result.push_back({"x0", ARM64_REG_R0}); |
| 85 | result.push_back({"x1", ARM64_REG_R1}); |
| 86 | result.push_back({"x2", ARM64_REG_R2}); |
| 87 | result.push_back({"x3", ARM64_REG_R3}); |
| 88 | result.push_back({"x4", ARM64_REG_R4}); |
| 89 | result.push_back({"x5", ARM64_REG_R5}); |
| 90 | result.push_back({"x6", ARM64_REG_R6}); |
| 91 | result.push_back({"x7", ARM64_REG_R7}); |
| 92 | result.push_back({"x8", ARM64_REG_R8}); |
| 93 | result.push_back({"x9", ARM64_REG_R9}); |
| 94 | result.push_back({"x10", ARM64_REG_R10}); |
| 95 | result.push_back({"x11", ARM64_REG_R11}); |
| 96 | result.push_back({"x12", ARM64_REG_R12}); |
| 97 | result.push_back({"x13", ARM64_REG_R13}); |
| 98 | result.push_back({"x14", ARM64_REG_R14}); |
| 99 | result.push_back({"x15", ARM64_REG_R15}); |
| 100 | result.push_back({"x16", ARM64_REG_R16}); |
| 101 | result.push_back({"x17", ARM64_REG_R17}); |
| 102 | result.push_back({"x18", ARM64_REG_R18}); |
| 103 | result.push_back({"x19", ARM64_REG_R19}); |
| 104 | result.push_back({"x20", ARM64_REG_R20}); |
| 105 | result.push_back({"x21", ARM64_REG_R21}); |
| 106 | result.push_back({"x22", ARM64_REG_R22}); |
| 107 | result.push_back({"x23", ARM64_REG_R23}); |
| 108 | result.push_back({"x24", ARM64_REG_R24}); |
| 109 | result.push_back({"x25", ARM64_REG_R25}); |
| 110 | result.push_back({"x26", ARM64_REG_R26}); |
| 111 | result.push_back({"x27", ARM64_REG_R27}); |
| 112 | result.push_back({"x28", ARM64_REG_R28}); |
| 113 | result.push_back({"x29", ARM64_REG_R29}); |
| 114 | result.push_back({"sp", ARM64_REG_SP}); |
| 115 | result.push_back({"lr", ARM64_REG_LR}); |
| 116 | result.push_back({"pc", ARM64_REG_PC}); |
| 117 | return result; |
| 118 | } |
| 119 | |
| 120 | template<> |
| 121 | std::vector<Register> ExpectedRegisters<RegsX86>() { |
| 122 | std::vector<Register> result; |
| 123 | result.push_back({"eax", X86_REG_EAX}); |
| 124 | result.push_back({"ebx", X86_REG_EBX}); |
| 125 | result.push_back({"ecx", X86_REG_ECX}); |
| 126 | result.push_back({"edx", X86_REG_EDX}); |
| 127 | result.push_back({"ebp", X86_REG_EBP}); |
| 128 | result.push_back({"edi", X86_REG_EDI}); |
| 129 | result.push_back({"esi", X86_REG_ESI}); |
| 130 | result.push_back({"esp", X86_REG_ESP}); |
| 131 | result.push_back({"eip", X86_REG_EIP}); |
| 132 | return result; |
| 133 | } |
| 134 | |
| 135 | template<> |
| 136 | std::vector<Register> ExpectedRegisters<RegsX86_64>() { |
| 137 | std::vector<Register> result; |
| 138 | result.push_back({"rax", X86_64_REG_RAX}); |
| 139 | result.push_back({"rbx", X86_64_REG_RBX}); |
| 140 | result.push_back({"rcx", X86_64_REG_RCX}); |
| 141 | result.push_back({"rdx", X86_64_REG_RDX}); |
| 142 | result.push_back({"r8", X86_64_REG_R8}); |
| 143 | result.push_back({"r9", X86_64_REG_R9}); |
| 144 | result.push_back({"r10", X86_64_REG_R10}); |
| 145 | result.push_back({"r11", X86_64_REG_R11}); |
| 146 | result.push_back({"r12", X86_64_REG_R12}); |
| 147 | result.push_back({"r13", X86_64_REG_R13}); |
| 148 | result.push_back({"r14", X86_64_REG_R14}); |
| 149 | result.push_back({"r15", X86_64_REG_R15}); |
| 150 | result.push_back({"rdi", X86_64_REG_RDI}); |
| 151 | result.push_back({"rsi", X86_64_REG_RSI}); |
| 152 | result.push_back({"rbp", X86_64_REG_RBP}); |
| 153 | result.push_back({"rsp", X86_64_REG_RSP}); |
| 154 | result.push_back({"rip", X86_64_REG_RIP}); |
| 155 | return result; |
| 156 | } |
| 157 | |
Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 158 | template<> |
| 159 | std::vector<Register> ExpectedRegisters<RegsMips>() { |
| 160 | std::vector<Register> result; |
| 161 | result.push_back({"r0", MIPS_REG_R0}); |
| 162 | result.push_back({"r1", MIPS_REG_R1}); |
| 163 | result.push_back({"r2", MIPS_REG_R2}); |
| 164 | result.push_back({"r3", MIPS_REG_R3}); |
| 165 | result.push_back({"r4", MIPS_REG_R4}); |
| 166 | result.push_back({"r5", MIPS_REG_R5}); |
| 167 | result.push_back({"r6", MIPS_REG_R6}); |
| 168 | result.push_back({"r7", MIPS_REG_R7}); |
| 169 | result.push_back({"r8", MIPS_REG_R8}); |
| 170 | result.push_back({"r9", MIPS_REG_R9}); |
| 171 | result.push_back({"r10", MIPS_REG_R10}); |
| 172 | result.push_back({"r11", MIPS_REG_R11}); |
| 173 | result.push_back({"r12", MIPS_REG_R12}); |
| 174 | result.push_back({"r13", MIPS_REG_R13}); |
| 175 | result.push_back({"r14", MIPS_REG_R14}); |
| 176 | result.push_back({"r15", MIPS_REG_R15}); |
| 177 | result.push_back({"r16", MIPS_REG_R16}); |
| 178 | result.push_back({"r17", MIPS_REG_R17}); |
| 179 | result.push_back({"r18", MIPS_REG_R18}); |
| 180 | result.push_back({"r19", MIPS_REG_R19}); |
| 181 | result.push_back({"r20", MIPS_REG_R20}); |
| 182 | result.push_back({"r21", MIPS_REG_R21}); |
| 183 | result.push_back({"r22", MIPS_REG_R22}); |
| 184 | result.push_back({"r23", MIPS_REG_R23}); |
| 185 | result.push_back({"r24", MIPS_REG_R24}); |
| 186 | result.push_back({"r25", MIPS_REG_R25}); |
| 187 | result.push_back({"r26", MIPS_REG_R26}); |
| 188 | result.push_back({"r27", MIPS_REG_R27}); |
| 189 | result.push_back({"r28", MIPS_REG_R28}); |
| 190 | result.push_back({"sp", MIPS_REG_SP}); |
| 191 | result.push_back({"r30", MIPS_REG_R30}); |
| 192 | result.push_back({"ra", MIPS_REG_RA}); |
| 193 | result.push_back({"pc", MIPS_REG_PC}); |
| 194 | |
| 195 | return result; |
| 196 | } |
| 197 | |
| 198 | template<> |
| 199 | std::vector<Register> ExpectedRegisters<RegsMips64>() { |
| 200 | std::vector<Register> result; |
| 201 | result.push_back({"r0", MIPS64_REG_R0}); |
| 202 | result.push_back({"r1", MIPS64_REG_R1}); |
| 203 | result.push_back({"r2", MIPS64_REG_R2}); |
| 204 | result.push_back({"r3", MIPS64_REG_R3}); |
| 205 | result.push_back({"r4", MIPS64_REG_R4}); |
| 206 | result.push_back({"r5", MIPS64_REG_R5}); |
| 207 | result.push_back({"r6", MIPS64_REG_R6}); |
| 208 | result.push_back({"r7", MIPS64_REG_R7}); |
| 209 | result.push_back({"r8", MIPS64_REG_R8}); |
| 210 | result.push_back({"r9", MIPS64_REG_R9}); |
| 211 | result.push_back({"r10", MIPS64_REG_R10}); |
| 212 | result.push_back({"r11", MIPS64_REG_R11}); |
| 213 | result.push_back({"r12", MIPS64_REG_R12}); |
| 214 | result.push_back({"r13", MIPS64_REG_R13}); |
| 215 | result.push_back({"r14", MIPS64_REG_R14}); |
| 216 | result.push_back({"r15", MIPS64_REG_R15}); |
| 217 | result.push_back({"r16", MIPS64_REG_R16}); |
| 218 | result.push_back({"r17", MIPS64_REG_R17}); |
| 219 | result.push_back({"r18", MIPS64_REG_R18}); |
| 220 | result.push_back({"r19", MIPS64_REG_R19}); |
| 221 | result.push_back({"r20", MIPS64_REG_R20}); |
| 222 | result.push_back({"r21", MIPS64_REG_R21}); |
| 223 | result.push_back({"r22", MIPS64_REG_R22}); |
| 224 | result.push_back({"r23", MIPS64_REG_R23}); |
| 225 | result.push_back({"r24", MIPS64_REG_R24}); |
| 226 | result.push_back({"r25", MIPS64_REG_R25}); |
| 227 | result.push_back({"r26", MIPS64_REG_R26}); |
| 228 | result.push_back({"r27", MIPS64_REG_R27}); |
| 229 | result.push_back({"r28", MIPS64_REG_R28}); |
| 230 | result.push_back({"sp", MIPS64_REG_SP}); |
| 231 | result.push_back({"r30", MIPS64_REG_R30}); |
| 232 | result.push_back({"ra", MIPS64_REG_RA}); |
| 233 | result.push_back({"pc", MIPS64_REG_PC}); |
| 234 | |
| 235 | return result; |
| 236 | } |
| 237 | |
| 238 | using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64, RegsMips, RegsMips64>; |
Christopher Ferris | 7e21eba | 2019-06-20 16:16:42 -0700 | [diff] [blame] | 239 | TYPED_TEST_SUITE(RegsIterateTest, RegTypes); |
Josh Gao | 6f580d8 | 2017-09-22 12:57:15 -0700 | [diff] [blame] | 240 | |
| 241 | TYPED_TEST(RegsIterateTest, iterate) { |
| 242 | std::vector<Register> expected = ExpectedRegisters<TypeParam>(); |
| 243 | TypeParam regs; |
| 244 | for (const auto& reg : expected) { |
| 245 | regs[reg.offset] = reg.offset; |
| 246 | } |
| 247 | |
| 248 | std::vector<Register> actual; |
| 249 | regs.IterateRegisters([&actual](const char* name, uint64_t value) { |
| 250 | actual.push_back({name, value}); |
| 251 | }); |
| 252 | |
| 253 | ASSERT_EQ(expected, actual); |
| 254 | } |
| 255 | |
| 256 | } // namespace unwindstack |