Merge "Speed up StepIfSignalHandler path."
This commit is contained in:
commit
c6dd6e8a79
|
@ -115,6 +115,7 @@ cc_test {
|
|||
"tests/MemoryRangeTest.cpp",
|
||||
"tests/MemoryRemoteTest.cpp",
|
||||
"tests/MemoryTest.cpp",
|
||||
"tests/RegsStepIfSignalHandlerTest.cpp",
|
||||
"tests/RegsTest.cpp",
|
||||
"tests/SymbolsTest.cpp",
|
||||
"tests/UnwindTest.cpp",
|
||||
|
|
|
@ -96,7 +96,7 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse
|
|||
}
|
||||
|
||||
bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
|
||||
return valid_ && (regs->StepIfSignalHandler(process_memory) ||
|
||||
return valid_ && (regs->StepIfSignalHandler(rel_pc, this, process_memory) ||
|
||||
interface_->Step(rel_pc, regs, process_memory) ||
|
||||
(gnu_debugdata_interface_ &&
|
||||
gnu_debugdata_interface_->Step(rel_pc, regs, process_memory)));
|
||||
|
|
|
@ -350,9 +350,12 @@ Regs* Regs::CreateFromLocal() {
|
|||
return regs;
|
||||
}
|
||||
|
||||
bool RegsArm::StepIfSignalHandler(Memory* memory) {
|
||||
bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
|
||||
uint32_t data;
|
||||
if (!memory->Read(pc(), &data, sizeof(data))) {
|
||||
Memory* elf_memory = elf->memory();
|
||||
// Read from elf memory since it is usually more expensive to read from
|
||||
// process memory.
|
||||
if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -371,7 +374,7 @@ bool RegsArm::StepIfSignalHandler(Memory* memory) {
|
|||
// Form 3 (thumb):
|
||||
// 0x77 0x27 movs r7, #77
|
||||
// 0x00 0xdf svc 0
|
||||
if (!memory->Read(sp(), &data, sizeof(data))) {
|
||||
if (!process_memory->Read(sp(), &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
if (data == 0x5ac3c35a) {
|
||||
|
@ -395,7 +398,7 @@ bool RegsArm::StepIfSignalHandler(Memory* memory) {
|
|||
// Form 3 (thumb):
|
||||
// 0xad 0x27 movs r7, #ad
|
||||
// 0x00 0xdf svc 0
|
||||
if (!memory->Read(sp(), &data, sizeof(data))) {
|
||||
if (!process_memory->Read(sp(), &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
if (data == sp() + 8) {
|
||||
|
@ -410,16 +413,19 @@ bool RegsArm::StepIfSignalHandler(Memory* memory) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!memory->Read(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
|
||||
if (!process_memory->Read(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
|
||||
return false;
|
||||
}
|
||||
SetFromRaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegsArm64::StepIfSignalHandler(Memory* memory) {
|
||||
bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
|
||||
uint64_t data;
|
||||
if (!memory->Read(pc(), &data, sizeof(data))) {
|
||||
Memory* elf_memory = elf->memory();
|
||||
// Read from elf memory since it is usually more expensive to read from
|
||||
// process memory.
|
||||
if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -432,7 +438,8 @@ bool RegsArm64::StepIfSignalHandler(Memory* memory) {
|
|||
}
|
||||
|
||||
// SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
|
||||
if (!memory->Read(sp() + 0x80 + 0xb0 + 0x08, regs_.data(), sizeof(uint64_t) * ARM64_REG_LAST)) {
|
||||
if (!process_memory->Read(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
|
||||
sizeof(uint64_t) * ARM64_REG_LAST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -440,9 +447,12 @@ bool RegsArm64::StepIfSignalHandler(Memory* memory) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RegsX86::StepIfSignalHandler(Memory* memory) {
|
||||
bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
|
||||
uint64_t data;
|
||||
if (!memory->Read(pc(), &data, sizeof(data))) {
|
||||
Memory* elf_memory = elf->memory();
|
||||
// Read from elf memory since it is usually more expensive to read from
|
||||
// process memory.
|
||||
if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -458,7 +468,7 @@ bool RegsX86::StepIfSignalHandler(Memory* memory) {
|
|||
// int signum
|
||||
// struct sigcontext (same format as mcontext)
|
||||
struct x86_mcontext_t context;
|
||||
if (!memory->Read(sp() + 4, &context, sizeof(context))) {
|
||||
if (!process_memory->Read(sp() + 4, &context, sizeof(context))) {
|
||||
return false;
|
||||
}
|
||||
regs_[X86_REG_EBP] = context.ebp;
|
||||
|
@ -484,12 +494,12 @@ bool RegsX86::StepIfSignalHandler(Memory* memory) {
|
|||
|
||||
// Get the location of the sigcontext data.
|
||||
uint32_t ptr;
|
||||
if (!memory->Read(sp() + 8, &ptr, sizeof(ptr))) {
|
||||
if (!process_memory->Read(sp() + 8, &ptr, sizeof(ptr))) {
|
||||
return false;
|
||||
}
|
||||
// Only read the portion of the data structure we care about.
|
||||
x86_ucontext_t x86_ucontext;
|
||||
if (!memory->Read(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
|
||||
if (!process_memory->Read(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
|
||||
return false;
|
||||
}
|
||||
SetFromUcontext(&x86_ucontext);
|
||||
|
@ -498,14 +508,17 @@ bool RegsX86::StepIfSignalHandler(Memory* memory) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RegsX86_64::StepIfSignalHandler(Memory* memory) {
|
||||
bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
|
||||
uint64_t data;
|
||||
if (!memory->Read(pc(), &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
|
||||
Memory* elf_memory = elf->memory();
|
||||
// Read from elf memory since it is usually more expensive to read from
|
||||
// process memory.
|
||||
if (!elf_memory->Read(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t data2;
|
||||
if (!memory->Read(pc() + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
|
||||
if (!elf_memory->Read(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -517,7 +530,7 @@ bool RegsX86_64::StepIfSignalHandler(Memory* memory) {
|
|||
// Read the mcontext data from the stack.
|
||||
// sp points to the ucontext data structure, read only the mcontext part.
|
||||
x86_64_ucontext_t x86_64_ucontext;
|
||||
if (!memory->Read(sp() + 0x28, &x86_64_ucontext.uc_mcontext, sizeof(x86_64_mcontext_t))) {
|
||||
if (!process_memory->Read(sp() + 0x28, &x86_64_ucontext.uc_mcontext, sizeof(x86_64_mcontext_t))) {
|
||||
return false;
|
||||
}
|
||||
SetFromUcontext(&x86_64_ucontext);
|
||||
|
|
|
@ -57,7 +57,7 @@ class Regs {
|
|||
|
||||
virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0;
|
||||
|
||||
virtual bool StepIfSignalHandler(Memory*) = 0;
|
||||
virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
|
||||
|
||||
virtual void SetFromRaw() = 0;
|
||||
|
||||
|
@ -109,7 +109,7 @@ class RegsArm : public RegsImpl<uint32_t> {
|
|||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool StepIfSignalHandler(Memory* memory) override;
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
};
|
||||
|
||||
class RegsArm64 : public RegsImpl<uint64_t> {
|
||||
|
@ -121,7 +121,7 @@ class RegsArm64 : public RegsImpl<uint64_t> {
|
|||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool StepIfSignalHandler(Memory* memory) override;
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
};
|
||||
|
||||
class RegsX86 : public RegsImpl<uint32_t> {
|
||||
|
@ -133,7 +133,7 @@ class RegsX86 : public RegsImpl<uint32_t> {
|
|||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool StepIfSignalHandler(Memory* memory) override;
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
void SetFromUcontext(x86_ucontext_t* ucontext);
|
||||
};
|
||||
|
@ -147,7 +147,7 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
|
|||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool StepIfSignalHandler(Memory* memory) override;
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
void SetFromUcontext(x86_64_ucontext_t* ucontext);
|
||||
};
|
||||
|
|
|
@ -33,7 +33,7 @@ class RegsFake : public RegsImpl<TypeParam> {
|
|||
|
||||
uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
|
||||
void SetFromRaw() override {}
|
||||
bool StepIfSignalHandler(Memory*) override { return false; }
|
||||
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
||||
bool GetReturnAddressFromDefault(Memory*, uint64_t*) { return false; }
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "Machine.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class RegsStepIfSignalHandlerTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
elf_memory_ = new MemoryFake;
|
||||
elf_.reset(new Elf(elf_memory_));
|
||||
}
|
||||
|
||||
void ArmStepIfSignalHandlerNonRt(uint32_t pc_data);
|
||||
void ArmStepIfSignalHandlerRt(uint32_t pc_data);
|
||||
|
||||
MemoryFake* elf_memory_;
|
||||
MemoryFake process_memory_;
|
||||
std::unique_ptr<Elf> elf_;
|
||||
};
|
||||
|
||||
void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
process_memory_.SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0x100U, regs[ARM_REG_SP]);
|
||||
EXPECT_EQ(0x120U, regs[ARM_REG_PC]);
|
||||
EXPECT_EQ(0x100U, regs.sp());
|
||||
EXPECT_EQ(0x120U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_non_rt) {
|
||||
// Form 1
|
||||
ArmStepIfSignalHandlerNonRt(0xe3a07077);
|
||||
|
||||
// Form 2
|
||||
ArmStepIfSignalHandlerNonRt(0xef900077);
|
||||
|
||||
// Form 3
|
||||
ArmStepIfSignalHandlerNonRt(0xdf002777);
|
||||
}
|
||||
|
||||
void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
for (uint64_t index = 0; index <= 100; index++) {
|
||||
process_memory_.SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0x350U, regs[ARM_REG_SP]);
|
||||
EXPECT_EQ(0x370U, regs[ARM_REG_PC]);
|
||||
EXPECT_EQ(0x350U, regs.sp());
|
||||
EXPECT_EQ(0x370U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_rt) {
|
||||
// Form 1
|
||||
ArmStepIfSignalHandlerRt(0xe3a070ad);
|
||||
|
||||
// Form 2
|
||||
ArmStepIfSignalHandlerRt(0xef9000ad);
|
||||
|
||||
// Form 3
|
||||
ArmStepIfSignalHandlerRt(0xdf0027ad);
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm64 regs;
|
||||
regs[ARM64_REG_PC] = 0x8000;
|
||||
regs[ARM64_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
|
||||
|
||||
for (uint64_t index = 0; index <= 100; index++) {
|
||||
process_memory_.SetData64(addr + index * 8, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0x460U, regs[ARM64_REG_SP]);
|
||||
EXPECT_EQ(0x470U, regs[ARM64_REG_PC]);
|
||||
EXPECT_EQ(0x460U, regs.sp());
|
||||
EXPECT_EQ(0x470U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) {
|
||||
uint64_t addr = 0xa00;
|
||||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
|
||||
for (uint64_t index = 0; index <= 25; index++) {
|
||||
process_memory_.SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0x70U, regs[X86_REG_EBP]);
|
||||
EXPECT_EQ(0x80U, regs[X86_REG_ESP]);
|
||||
EXPECT_EQ(0x90U, regs[X86_REG_EBX]);
|
||||
EXPECT_EQ(0xa0U, regs[X86_REG_EDX]);
|
||||
EXPECT_EQ(0xb0U, regs[X86_REG_ECX]);
|
||||
EXPECT_EQ(0xc0U, regs[X86_REG_EAX]);
|
||||
EXPECT_EQ(0xf0U, regs[X86_REG_EIP]);
|
||||
EXPECT_EQ(0x80U, regs.sp());
|
||||
EXPECT_EQ(0xf0U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) {
|
||||
uint64_t addr = 0xa00;
|
||||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
|
||||
addr += 8;
|
||||
// Pointer to ucontext data.
|
||||
process_memory_.SetData32(addr, 0x8100);
|
||||
|
||||
addr = 0x8100;
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
process_memory_.SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0xb0U, regs[X86_REG_EBP]);
|
||||
EXPECT_EQ(0xc0U, regs[X86_REG_ESP]);
|
||||
EXPECT_EQ(0xd0U, regs[X86_REG_EBX]);
|
||||
EXPECT_EQ(0xe0U, regs[X86_REG_EDX]);
|
||||
EXPECT_EQ(0xf0U, regs[X86_REG_ECX]);
|
||||
EXPECT_EQ(0x100U, regs[X86_REG_EAX]);
|
||||
EXPECT_EQ(0x130U, regs[X86_REG_EIP]);
|
||||
EXPECT_EQ(0xc0U, regs.sp());
|
||||
EXPECT_EQ(0x130U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) {
|
||||
uint64_t addr = 0x500;
|
||||
RegsX86_64 regs;
|
||||
regs[X86_64_REG_RIP] = 0x7000;
|
||||
regs[X86_64_REG_RSP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748);
|
||||
elf_memory_->SetData16(0x7008, 0x0f05);
|
||||
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
process_memory_.SetData64(addr + index * 8, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(0x7000, elf_.get(), &process_memory_));
|
||||
EXPECT_EQ(0x140U, regs[X86_64_REG_RSP]);
|
||||
EXPECT_EQ(0x150U, regs[X86_64_REG_RIP]);
|
||||
EXPECT_EQ(0x140U, regs.sp());
|
||||
EXPECT_EQ(0x150U, regs.pc());
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
|
@ -23,8 +23,6 @@
|
|||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "Machine.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
@ -62,7 +60,7 @@ class RegsTestImpl : public RegsImpl<TypeParam> {
|
|||
|
||||
uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
|
||||
void SetFromRaw() override {}
|
||||
bool StepIfSignalHandler(Memory*) override { return false; }
|
||||
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
||||
};
|
||||
|
||||
class RegsTest : public ::testing::Test {
|
||||
|
@ -77,9 +75,6 @@ class RegsTest : public ::testing::Test {
|
|||
template <typename AddressType>
|
||||
void RegsReturnAddressRegister();
|
||||
|
||||
void ArmStepIfSignalHandlerNonRt(uint32_t pc_data);
|
||||
void ArmStepIfSignalHandlerRt(uint32_t pc_data);
|
||||
|
||||
ElfInterfaceFake* elf_interface_;
|
||||
MemoryFake* memory_;
|
||||
std::unique_ptr<ElfFake> elf_;
|
||||
|
@ -291,160 +286,4 @@ TEST_F(RegsTest, x86_64_set_from_raw) {
|
|||
EXPECT_EQ(0x4900000000U, x86_64.pc());
|
||||
}
|
||||
|
||||
void RegsTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
memory_->SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0x100U, regs[ARM_REG_SP]);
|
||||
EXPECT_EQ(0x120U, regs[ARM_REG_PC]);
|
||||
EXPECT_EQ(0x100U, regs.sp());
|
||||
EXPECT_EQ(0x120U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, arm_step_if_signal_handler_non_rt) {
|
||||
// Form 1
|
||||
ArmStepIfSignalHandlerNonRt(0xe3a07077);
|
||||
|
||||
// Form 2
|
||||
ArmStepIfSignalHandlerNonRt(0xef900077);
|
||||
|
||||
// Form 3
|
||||
ArmStepIfSignalHandlerNonRt(0xdf002777);
|
||||
}
|
||||
|
||||
void RegsTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
for (uint64_t index = 0; index <= 100; index++) {
|
||||
memory_->SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0x350U, regs[ARM_REG_SP]);
|
||||
EXPECT_EQ(0x370U, regs[ARM_REG_PC]);
|
||||
EXPECT_EQ(0x350U, regs.sp());
|
||||
EXPECT_EQ(0x370U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, arm_step_if_signal_handler_rt) {
|
||||
// Form 1
|
||||
ArmStepIfSignalHandlerRt(0xe3a070ad);
|
||||
|
||||
// Form 2
|
||||
ArmStepIfSignalHandlerRt(0xef9000ad);
|
||||
|
||||
// Form 3
|
||||
ArmStepIfSignalHandlerRt(0xdf0027ad);
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, arm64_step_if_signal_handler) {
|
||||
uint64_t addr = 0x1000;
|
||||
RegsArm64 regs;
|
||||
regs[ARM64_REG_PC] = 0x8000;
|
||||
regs[ARM64_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
|
||||
|
||||
for (uint64_t index = 0; index <= 100; index++) {
|
||||
memory_->SetData64(addr + index * 8, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0x460U, regs[ARM64_REG_SP]);
|
||||
EXPECT_EQ(0x470U, regs[ARM64_REG_PC]);
|
||||
EXPECT_EQ(0x460U, regs.sp());
|
||||
EXPECT_EQ(0x470U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, x86_step_if_signal_handler_no_siginfo) {
|
||||
uint64_t addr = 0xa00;
|
||||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
|
||||
for (uint64_t index = 0; index <= 25; index++) {
|
||||
memory_->SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0x70U, regs[X86_REG_EBP]);
|
||||
EXPECT_EQ(0x80U, regs[X86_REG_ESP]);
|
||||
EXPECT_EQ(0x90U, regs[X86_REG_EBX]);
|
||||
EXPECT_EQ(0xa0U, regs[X86_REG_EDX]);
|
||||
EXPECT_EQ(0xb0U, regs[X86_REG_ECX]);
|
||||
EXPECT_EQ(0xc0U, regs[X86_REG_EAX]);
|
||||
EXPECT_EQ(0xf0U, regs[X86_REG_EIP]);
|
||||
EXPECT_EQ(0x80U, regs.sp());
|
||||
EXPECT_EQ(0xf0U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, x86_step_if_signal_handler_siginfo) {
|
||||
uint64_t addr = 0xa00;
|
||||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
|
||||
addr += 8;
|
||||
// Pointer to ucontext data.
|
||||
memory_->SetData32(addr, 0x8100);
|
||||
|
||||
addr = 0x8100;
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
memory_->SetData32(addr + index * 4, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0xb0U, regs[X86_REG_EBP]);
|
||||
EXPECT_EQ(0xc0U, regs[X86_REG_ESP]);
|
||||
EXPECT_EQ(0xd0U, regs[X86_REG_EBX]);
|
||||
EXPECT_EQ(0xe0U, regs[X86_REG_EDX]);
|
||||
EXPECT_EQ(0xf0U, regs[X86_REG_ECX]);
|
||||
EXPECT_EQ(0x100U, regs[X86_REG_EAX]);
|
||||
EXPECT_EQ(0x130U, regs[X86_REG_EIP]);
|
||||
EXPECT_EQ(0xc0U, regs.sp());
|
||||
EXPECT_EQ(0x130U, regs.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, x86_64_step_if_signal_handler) {
|
||||
uint64_t addr = 0x500;
|
||||
RegsX86_64 regs;
|
||||
regs[X86_64_REG_RIP] = 0x7000;
|
||||
regs[X86_64_REG_RSP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
memory_->SetData64(0x7000, 0x0f0000000fc0c748);
|
||||
memory_->SetData16(0x7008, 0x0f05);
|
||||
|
||||
for (uint64_t index = 0; index <= 30; index++) {
|
||||
memory_->SetData64(addr + index * 8, index * 0x10);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(regs.StepIfSignalHandler(memory_));
|
||||
EXPECT_EQ(0x140U, regs[X86_64_REG_RSP]);
|
||||
EXPECT_EQ(0x150U, regs[X86_64_REG_RIP]);
|
||||
EXPECT_EQ(0x140U, regs.sp());
|
||||
EXPECT_EQ(0x150U, regs.pc());
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
Loading…
Reference in New Issue