| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -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 <gtest/gtest.h> | 
|  | 20 |  | 
|  | 21 | #include <unwindstack/Elf.h> | 
| Christopher Ferris | 5391416 | 2018-02-08 19:27:47 -0800 | [diff] [blame] | 22 | #include <unwindstack/MachineArm.h> | 
|  | 23 | #include <unwindstack/MachineArm64.h> | 
|  | 24 | #include <unwindstack/MachineMips.h> | 
|  | 25 | #include <unwindstack/MachineMips64.h> | 
|  | 26 | #include <unwindstack/MachineX86.h> | 
|  | 27 | #include <unwindstack/MachineX86_64.h> | 
| Christopher Ferris | d06001d | 2017-11-30 18:56:01 -0800 | [diff] [blame] | 28 | #include <unwindstack/RegsArm.h> | 
|  | 29 | #include <unwindstack/RegsArm64.h> | 
| Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 30 | #include <unwindstack/RegsMips.h> | 
|  | 31 | #include <unwindstack/RegsMips64.h> | 
| Christopher Ferris | 5391416 | 2018-02-08 19:27:47 -0800 | [diff] [blame] | 32 | #include <unwindstack/RegsX86.h> | 
|  | 33 | #include <unwindstack/RegsX86_64.h> | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 34 |  | 
|  | 35 | #include "MemoryFake.h" | 
|  | 36 |  | 
|  | 37 | namespace unwindstack { | 
|  | 38 |  | 
|  | 39 | class RegsStepIfSignalHandlerTest : public ::testing::Test { | 
|  | 40 | protected: | 
|  | 41 | void SetUp() override { | 
|  | 42 | elf_memory_ = new MemoryFake; | 
|  | 43 | elf_.reset(new Elf(elf_memory_)); | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | void ArmStepIfSignalHandlerNonRt(uint32_t pc_data); | 
|  | 47 | void ArmStepIfSignalHandlerRt(uint32_t pc_data); | 
|  | 48 |  | 
|  | 49 | MemoryFake* elf_memory_; | 
|  | 50 | MemoryFake process_memory_; | 
|  | 51 | std::unique_ptr<Elf> elf_; | 
|  | 52 | }; | 
|  | 53 |  | 
|  | 54 | void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data) { | 
|  | 55 | uint64_t addr = 0x1000; | 
|  | 56 | RegsArm regs; | 
|  | 57 | regs[ARM_REG_PC] = 0x5000; | 
|  | 58 | regs[ARM_REG_SP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 59 |  | 
|  | 60 | elf_memory_->SetData32(0x5000, pc_data); | 
|  | 61 |  | 
|  | 62 | for (uint64_t index = 0; index <= 30; index++) { | 
|  | 63 | process_memory_.SetData32(addr + index * 4, index * 0x10); | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_)); | 
|  | 67 | EXPECT_EQ(0x100U, regs[ARM_REG_SP]); | 
|  | 68 | EXPECT_EQ(0x120U, regs[ARM_REG_PC]); | 
|  | 69 | EXPECT_EQ(0x100U, regs.sp()); | 
|  | 70 | EXPECT_EQ(0x120U, regs.pc()); | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_non_rt) { | 
|  | 74 | // Form 1 | 
|  | 75 | ArmStepIfSignalHandlerNonRt(0xe3a07077); | 
|  | 76 |  | 
|  | 77 | // Form 2 | 
|  | 78 | ArmStepIfSignalHandlerNonRt(0xef900077); | 
|  | 79 |  | 
|  | 80 | // Form 3 | 
|  | 81 | ArmStepIfSignalHandlerNonRt(0xdf002777); | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) { | 
|  | 85 | uint64_t addr = 0x1000; | 
|  | 86 | RegsArm regs; | 
|  | 87 | regs[ARM_REG_PC] = 0x5000; | 
|  | 88 | regs[ARM_REG_SP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 89 |  | 
|  | 90 | elf_memory_->SetData32(0x5000, pc_data); | 
|  | 91 |  | 
|  | 92 | for (uint64_t index = 0; index <= 100; index++) { | 
|  | 93 | process_memory_.SetData32(addr + index * 4, index * 0x10); | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_)); | 
|  | 97 | EXPECT_EQ(0x350U, regs[ARM_REG_SP]); | 
|  | 98 | EXPECT_EQ(0x370U, regs[ARM_REG_PC]); | 
|  | 99 | EXPECT_EQ(0x350U, regs.sp()); | 
|  | 100 | EXPECT_EQ(0x370U, regs.pc()); | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_rt) { | 
|  | 104 | // Form 1 | 
|  | 105 | ArmStepIfSignalHandlerRt(0xe3a070ad); | 
|  | 106 |  | 
|  | 107 | // Form 2 | 
|  | 108 | ArmStepIfSignalHandlerRt(0xef9000ad); | 
|  | 109 |  | 
|  | 110 | // Form 3 | 
|  | 111 | ArmStepIfSignalHandlerRt(0xdf0027ad); | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) { | 
|  | 115 | uint64_t addr = 0x1000; | 
|  | 116 | RegsArm64 regs; | 
|  | 117 | regs[ARM64_REG_PC] = 0x8000; | 
|  | 118 | regs[ARM64_REG_SP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 119 |  | 
|  | 120 | elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL); | 
|  | 121 |  | 
|  | 122 | for (uint64_t index = 0; index <= 100; index++) { | 
|  | 123 | process_memory_.SetData64(addr + index * 8, index * 0x10); | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); | 
|  | 127 | EXPECT_EQ(0x460U, regs[ARM64_REG_SP]); | 
|  | 128 | EXPECT_EQ(0x470U, regs[ARM64_REG_PC]); | 
|  | 129 | EXPECT_EQ(0x460U, regs.sp()); | 
|  | 130 | EXPECT_EQ(0x470U, regs.pc()); | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) { | 
|  | 134 | uint64_t addr = 0xa00; | 
|  | 135 | RegsX86 regs; | 
|  | 136 | regs[X86_REG_EIP] = 0x4100; | 
|  | 137 | regs[X86_REG_ESP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 138 |  | 
|  | 139 | elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL); | 
|  | 140 | for (uint64_t index = 0; index <= 25; index++) { | 
|  | 141 | process_memory_.SetData32(addr + index * 4, index * 0x10); | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_)); | 
|  | 145 | EXPECT_EQ(0x70U, regs[X86_REG_EBP]); | 
|  | 146 | EXPECT_EQ(0x80U, regs[X86_REG_ESP]); | 
|  | 147 | EXPECT_EQ(0x90U, regs[X86_REG_EBX]); | 
|  | 148 | EXPECT_EQ(0xa0U, regs[X86_REG_EDX]); | 
|  | 149 | EXPECT_EQ(0xb0U, regs[X86_REG_ECX]); | 
|  | 150 | EXPECT_EQ(0xc0U, regs[X86_REG_EAX]); | 
|  | 151 | EXPECT_EQ(0xf0U, regs[X86_REG_EIP]); | 
|  | 152 | EXPECT_EQ(0x80U, regs.sp()); | 
|  | 153 | EXPECT_EQ(0xf0U, regs.pc()); | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) { | 
|  | 157 | uint64_t addr = 0xa00; | 
|  | 158 | RegsX86 regs; | 
|  | 159 | regs[X86_REG_EIP] = 0x4100; | 
|  | 160 | regs[X86_REG_ESP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 161 |  | 
|  | 162 | elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL); | 
|  | 163 | addr += 8; | 
|  | 164 | // Pointer to ucontext data. | 
|  | 165 | process_memory_.SetData32(addr, 0x8100); | 
|  | 166 |  | 
|  | 167 | addr = 0x8100; | 
|  | 168 | for (uint64_t index = 0; index <= 30; index++) { | 
|  | 169 | process_memory_.SetData32(addr + index * 4, index * 0x10); | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_)); | 
|  | 173 | EXPECT_EQ(0xb0U, regs[X86_REG_EBP]); | 
|  | 174 | EXPECT_EQ(0xc0U, regs[X86_REG_ESP]); | 
|  | 175 | EXPECT_EQ(0xd0U, regs[X86_REG_EBX]); | 
|  | 176 | EXPECT_EQ(0xe0U, regs[X86_REG_EDX]); | 
|  | 177 | EXPECT_EQ(0xf0U, regs[X86_REG_ECX]); | 
|  | 178 | EXPECT_EQ(0x100U, regs[X86_REG_EAX]); | 
|  | 179 | EXPECT_EQ(0x130U, regs[X86_REG_EIP]); | 
|  | 180 | EXPECT_EQ(0xc0U, regs.sp()); | 
|  | 181 | EXPECT_EQ(0x130U, regs.pc()); | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) { | 
|  | 185 | uint64_t addr = 0x500; | 
|  | 186 | RegsX86_64 regs; | 
|  | 187 | regs[X86_64_REG_RIP] = 0x7000; | 
|  | 188 | regs[X86_64_REG_RSP] = addr; | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 189 |  | 
|  | 190 | elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748); | 
|  | 191 | elf_memory_->SetData16(0x7008, 0x0f05); | 
|  | 192 |  | 
|  | 193 | for (uint64_t index = 0; index <= 30; index++) { | 
|  | 194 | process_memory_.SetData64(addr + index * 8, index * 0x10); | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | ASSERT_TRUE(regs.StepIfSignalHandler(0x7000, elf_.get(), &process_memory_)); | 
|  | 198 | EXPECT_EQ(0x140U, regs[X86_64_REG_RSP]); | 
|  | 199 | EXPECT_EQ(0x150U, regs[X86_64_REG_RIP]); | 
|  | 200 | EXPECT_EQ(0x140U, regs.sp()); | 
|  | 201 | EXPECT_EQ(0x150U, regs.pc()); | 
|  | 202 | } | 
|  | 203 |  | 
| Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 204 | TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_non_rt) { | 
|  | 205 | uint64_t addr = 0x1000; | 
|  | 206 | RegsMips regs; | 
|  | 207 | regs[MIPS_REG_PC] = 0x8000; | 
|  | 208 | regs[MIPS_REG_SP] = addr; | 
| Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 209 |  | 
|  | 210 | elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL); | 
|  | 211 |  | 
|  | 212 | for (uint64_t index = 0; index <= 50; index++) { | 
|  | 213 | process_memory_.SetData64(addr + index * 8, index * 0x10); | 
|  | 214 | } | 
|  | 215 |  | 
|  | 216 | ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); | 
|  | 217 | EXPECT_EQ(0x220U, regs[MIPS_REG_SP]); | 
|  | 218 | EXPECT_EQ(0x040U, regs[MIPS_REG_PC]); | 
|  | 219 | EXPECT_EQ(0x220U, regs.sp()); | 
|  | 220 | EXPECT_EQ(0x040U, regs.pc()); | 
|  | 221 | } | 
|  | 222 |  | 
|  | 223 | TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_rt) { | 
|  | 224 | uint64_t addr = 0x1000; | 
|  | 225 | RegsMips regs; | 
|  | 226 | regs[MIPS_REG_PC] = 0x8000; | 
|  | 227 | regs[MIPS_REG_SP] = addr; | 
| Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 228 |  | 
|  | 229 | elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL); | 
|  | 230 |  | 
|  | 231 | for (uint64_t index = 0; index <= 100; index++) { | 
|  | 232 | process_memory_.SetData64(addr + index * 8, index * 0x10); | 
|  | 233 | } | 
|  | 234 |  | 
|  | 235 | ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); | 
|  | 236 | EXPECT_EQ(0x350U, regs[MIPS_REG_SP]); | 
|  | 237 | EXPECT_EQ(0x170U, regs[MIPS_REG_PC]); | 
|  | 238 | EXPECT_EQ(0x350U, regs.sp()); | 
|  | 239 | EXPECT_EQ(0x170U, regs.pc()); | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | TEST_F(RegsStepIfSignalHandlerTest, mips64_step_if_signal_handler) { | 
|  | 243 | uint64_t addr = 0x1000; | 
|  | 244 | RegsMips64 regs; | 
|  | 245 | regs[MIPS64_REG_PC] = 0x8000; | 
|  | 246 | regs[MIPS64_REG_SP] = addr; | 
| Douglas Leung | 61b1a1a | 2017-11-08 10:53:53 +0100 | [diff] [blame] | 247 |  | 
|  | 248 | elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL); | 
|  | 249 |  | 
|  | 250 | for (uint64_t index = 0; index <= 100; index++) { | 
|  | 251 | process_memory_.SetData64(addr + index * 8, index * 0x10); | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 | ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); | 
|  | 255 | EXPECT_EQ(0x350U, regs[MIPS64_REG_SP]); | 
|  | 256 | EXPECT_EQ(0x600U, regs[MIPS64_REG_PC]); | 
|  | 257 | EXPECT_EQ(0x350U, regs.sp()); | 
|  | 258 | EXPECT_EQ(0x600U, regs.pc()); | 
|  | 259 | } | 
|  | 260 |  | 
| Christopher Ferris | eb4a6db | 2017-07-19 12:37:45 -0700 | [diff] [blame] | 261 | }  // namespace unwindstack |