| 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 |