diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-10-24 04:03:18 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-10-24 04:03:18 +0000 |
commit | 1c65e77e6d73b9eee13d913e0b7886c72282e67f (patch) | |
tree | ad4fe5d769556097d531f6c2ab67a2192a2f555c /libunwindstack | |
parent | b409e5e00b0af1cfe5648d132d4f62797738ac1d (diff) | |
parent | 6f580d8b843f4caac8c12383684941ca02de12a8 (diff) | |
download | core-1c65e77e6d73b9eee13d913e0b7886c72282e67f.tar.gz core-1c65e77e6d73b9eee13d913e0b7886c72282e67f.tar.bz2 core-1c65e77e6d73b9eee13d913e0b7886c72282e67f.zip |
Merge changes I8f33830f,Icd2b891b,I8736ff5c,Iae6e342a
* changes:
libunwindstack: add method to iterate across registers.
libbacktrace: expose BacktraceMap's unwindstack::Memory.
libunwindstack: expose UnwindStackMap::GetFunctionName.
libbacktrace: expose libunwindstack Unwind routine.
Diffstat (limited to 'libunwindstack')
-rw-r--r-- | libunwindstack/Android.bp | 1 | ||||
-rw-r--r-- | libunwindstack/Regs.cpp | 87 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Regs.h | 18 | ||||
-rw-r--r-- | libunwindstack/tests/RegsFake.h | 2 | ||||
-rw-r--r-- | libunwindstack/tests/RegsIterateTest.cpp | 167 |
5 files changed, 275 insertions, 0 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index f40086e5d..e687a6895 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -122,6 +122,7 @@ cc_test { "tests/MemoryRangeTest.cpp", "tests/MemoryRemoteTest.cpp", "tests/MemoryTest.cpp", + "tests/RegsIterateTest.cpp", "tests/RegsStepIfSignalHandlerTest.cpp", "tests/RegsTest.cpp", "tests/SymbolsTest.cpp", diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp index cf71e3922..36b8e25f5 100644 --- a/libunwindstack/Regs.cpp +++ b/libunwindstack/Regs.cpp @@ -80,6 +80,25 @@ bool RegsArm::SetPcFromReturnAddress(Memory*) { return true; } +void RegsArm::IterateRegisters(std::function<void(const char*, uint64_t)> fn) { + fn("r0", regs_[ARM_REG_R0]); + fn("r1", regs_[ARM_REG_R1]); + fn("r2", regs_[ARM_REG_R2]); + fn("r3", regs_[ARM_REG_R3]); + fn("r4", regs_[ARM_REG_R4]); + fn("r5", regs_[ARM_REG_R5]); + fn("r6", regs_[ARM_REG_R6]); + fn("r7", regs_[ARM_REG_R7]); + fn("r8", regs_[ARM_REG_R8]); + fn("r9", regs_[ARM_REG_R9]); + fn("r10", regs_[ARM_REG_R10]); + fn("r11", regs_[ARM_REG_R11]); + fn("ip", regs_[ARM_REG_R12]); + fn("sp", regs_[ARM_REG_SP]); + fn("lr", regs_[ARM_REG_LR]); + fn("pc", regs_[ARM_REG_PC]); +} + RegsArm64::RegsArm64() : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {} @@ -112,6 +131,42 @@ bool RegsArm64::SetPcFromReturnAddress(Memory*) { return true; } +void RegsArm64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) { + fn("x0", regs_[ARM64_REG_R0]); + fn("x1", regs_[ARM64_REG_R1]); + fn("x2", regs_[ARM64_REG_R2]); + fn("x3", regs_[ARM64_REG_R3]); + fn("x4", regs_[ARM64_REG_R4]); + fn("x5", regs_[ARM64_REG_R5]); + fn("x6", regs_[ARM64_REG_R6]); + fn("x7", regs_[ARM64_REG_R7]); + fn("x8", regs_[ARM64_REG_R8]); + fn("x9", regs_[ARM64_REG_R9]); + fn("x10", regs_[ARM64_REG_R10]); + fn("x11", regs_[ARM64_REG_R11]); + fn("x12", regs_[ARM64_REG_R12]); + fn("x13", regs_[ARM64_REG_R13]); + fn("x14", regs_[ARM64_REG_R14]); + fn("x15", regs_[ARM64_REG_R15]); + fn("x16", regs_[ARM64_REG_R16]); + fn("x17", regs_[ARM64_REG_R17]); + fn("x18", regs_[ARM64_REG_R18]); + fn("x19", regs_[ARM64_REG_R19]); + fn("x20", regs_[ARM64_REG_R20]); + fn("x21", regs_[ARM64_REG_R21]); + fn("x22", regs_[ARM64_REG_R22]); + fn("x23", regs_[ARM64_REG_R23]); + fn("x24", regs_[ARM64_REG_R24]); + fn("x25", regs_[ARM64_REG_R25]); + fn("x26", regs_[ARM64_REG_R26]); + fn("x27", regs_[ARM64_REG_R27]); + fn("x28", regs_[ARM64_REG_R28]); + fn("x29", regs_[ARM64_REG_R29]); + fn("sp", regs_[ARM64_REG_SP]); + fn("lr", regs_[ARM64_REG_LR]); + fn("pc", regs_[ARM64_REG_PC]); +} + RegsX86::RegsX86() : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {} @@ -146,6 +201,18 @@ bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) { return true; } +void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) { + fn("eax", regs_[X86_REG_EAX]); + fn("ebx", regs_[X86_REG_EBX]); + fn("ecx", regs_[X86_REG_ECX]); + fn("edx", regs_[X86_REG_EDX]); + fn("ebp", regs_[X86_REG_EBP]); + fn("edi", regs_[X86_REG_EDI]); + fn("esi", regs_[X86_REG_ESI]); + fn("esp", regs_[X86_REG_ESP]); + fn("eip", regs_[X86_REG_EIP]); +} + RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {} @@ -181,6 +248,26 @@ bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) { return true; } +void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) { + fn("rax", regs_[X86_64_REG_RAX]); + fn("rbx", regs_[X86_64_REG_RBX]); + fn("rcx", regs_[X86_64_REG_RCX]); + fn("rdx", regs_[X86_64_REG_RDX]); + fn("r8", regs_[X86_64_REG_R8]); + fn("r9", regs_[X86_64_REG_R9]); + fn("r10", regs_[X86_64_REG_R10]); + fn("r11", regs_[X86_64_REG_R11]); + fn("r12", regs_[X86_64_REG_R12]); + fn("r13", regs_[X86_64_REG_R13]); + fn("r14", regs_[X86_64_REG_R14]); + fn("r15", regs_[X86_64_REG_R15]); + fn("rdi", regs_[X86_64_REG_RDI]); + fn("rsi", regs_[X86_64_REG_RSI]); + fn("rbp", regs_[X86_64_REG_RBP]); + fn("rsp", regs_[X86_64_REG_RSP]); + fn("rip", regs_[X86_64_REG_RIP]); +} + static Regs* ReadArm(void* remote_data) { arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data); diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h index 9d3150bf6..6576e4c91 100644 --- a/libunwindstack/include/unwindstack/Regs.h +++ b/libunwindstack/include/unwindstack/Regs.h @@ -19,6 +19,8 @@ #include <stdint.h> +#include <functional> +#include <string> #include <vector> namespace unwindstack { @@ -63,6 +65,8 @@ class Regs { virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0; + virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0; + uint16_t sp_reg() { return sp_reg_; } uint16_t total_regs() { return total_regs_; } @@ -94,6 +98,12 @@ class RegsImpl : public Regs { void* RawData() override { return regs_.data(); } + virtual void IterateRegisters(std::function<void(const char*, uint64_t)> fn) override { + for (size_t i = 0; i < regs_.size(); ++i) { + fn(std::to_string(i).c_str(), regs_[i]); + } + } + protected: AddressType pc_; AddressType sp_; @@ -114,6 +124,8 @@ class RegsArm : public RegsImpl<uint32_t> { bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; + + virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; }; class RegsArm64 : public RegsImpl<uint64_t> { @@ -130,6 +142,8 @@ class RegsArm64 : public RegsImpl<uint64_t> { bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; + + virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; }; class RegsX86 : public RegsImpl<uint32_t> { @@ -148,6 +162,8 @@ class RegsX86 : public RegsImpl<uint32_t> { bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; void SetFromUcontext(x86_ucontext_t* ucontext); + + virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; }; class RegsX86_64 : public RegsImpl<uint64_t> { @@ -166,6 +182,8 @@ class RegsX86_64 : public RegsImpl<uint64_t> { bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; void SetFromUcontext(x86_64_ucontext_t* ucontext); + + virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; }; } // namespace unwindstack diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h index efcd029ab..fedaf8734 100644 --- a/libunwindstack/tests/RegsFake.h +++ b/libunwindstack/tests/RegsFake.h @@ -42,6 +42,8 @@ class RegsFake : public Regs { return true; } + void IterateRegisters(std::function<void(const char*, uint64_t)>) override {} + uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; } bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp new file mode 100644 index 000000000..c8d1d98bd --- /dev/null +++ b/libunwindstack/tests/RegsIterateTest.cpp @@ -0,0 +1,167 @@ +/* + * 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 <utility> +#include <type_traits> +#include <vector> + +#include <gtest/gtest.h> + +#include <unwindstack/Elf.h> +#include <unwindstack/ElfInterface.h> +#include <unwindstack/MapInfo.h> +#include <unwindstack/Regs.h> + +#include "Machine.h" + +namespace unwindstack { + +struct Register { + std::string expected_name; + uint64_t offset; + + bool operator==(const Register& rhs) const { + return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset); + } +}; + +template<typename T> +class RegsIterateTest : public ::testing::Test { +}; + +template<typename RegsType> +std::vector<Register> ExpectedRegisters(); + +template<> +std::vector<Register> ExpectedRegisters<RegsArm>() { + std::vector<Register> result; + result.push_back({"r0", ARM_REG_R0}); + result.push_back({"r1", ARM_REG_R1}); + result.push_back({"r2", ARM_REG_R2}); + result.push_back({"r3", ARM_REG_R3}); + result.push_back({"r4", ARM_REG_R4}); + result.push_back({"r5", ARM_REG_R5}); + result.push_back({"r6", ARM_REG_R6}); + result.push_back({"r7", ARM_REG_R7}); + result.push_back({"r8", ARM_REG_R8}); + result.push_back({"r9", ARM_REG_R9}); + result.push_back({"r10", ARM_REG_R10}); + result.push_back({"r11", ARM_REG_R11}); + result.push_back({"ip", ARM_REG_R12}); + result.push_back({"sp", ARM_REG_SP}); + result.push_back({"lr", ARM_REG_LR}); + result.push_back({"pc", ARM_REG_PC}); + return result; +} + +template<> +std::vector<Register> ExpectedRegisters<RegsArm64>() { + std::vector<Register> result; + result.push_back({"x0", ARM64_REG_R0}); + result.push_back({"x1", ARM64_REG_R1}); + result.push_back({"x2", ARM64_REG_R2}); + result.push_back({"x3", ARM64_REG_R3}); + result.push_back({"x4", ARM64_REG_R4}); + result.push_back({"x5", ARM64_REG_R5}); + result.push_back({"x6", ARM64_REG_R6}); + result.push_back({"x7", ARM64_REG_R7}); + result.push_back({"x8", ARM64_REG_R8}); + result.push_back({"x9", ARM64_REG_R9}); + result.push_back({"x10", ARM64_REG_R10}); + result.push_back({"x11", ARM64_REG_R11}); + result.push_back({"x12", ARM64_REG_R12}); + result.push_back({"x13", ARM64_REG_R13}); + result.push_back({"x14", ARM64_REG_R14}); + result.push_back({"x15", ARM64_REG_R15}); + result.push_back({"x16", ARM64_REG_R16}); + result.push_back({"x17", ARM64_REG_R17}); + result.push_back({"x18", ARM64_REG_R18}); + result.push_back({"x19", ARM64_REG_R19}); + result.push_back({"x20", ARM64_REG_R20}); + result.push_back({"x21", ARM64_REG_R21}); + result.push_back({"x22", ARM64_REG_R22}); + result.push_back({"x23", ARM64_REG_R23}); + result.push_back({"x24", ARM64_REG_R24}); + result.push_back({"x25", ARM64_REG_R25}); + result.push_back({"x26", ARM64_REG_R26}); + result.push_back({"x27", ARM64_REG_R27}); + result.push_back({"x28", ARM64_REG_R28}); + result.push_back({"x29", ARM64_REG_R29}); + result.push_back({"sp", ARM64_REG_SP}); + result.push_back({"lr", ARM64_REG_LR}); + result.push_back({"pc", ARM64_REG_PC}); + return result; +} + +template<> +std::vector<Register> ExpectedRegisters<RegsX86>() { + std::vector<Register> result; + result.push_back({"eax", X86_REG_EAX}); + result.push_back({"ebx", X86_REG_EBX}); + result.push_back({"ecx", X86_REG_ECX}); + result.push_back({"edx", X86_REG_EDX}); + result.push_back({"ebp", X86_REG_EBP}); + result.push_back({"edi", X86_REG_EDI}); + result.push_back({"esi", X86_REG_ESI}); + result.push_back({"esp", X86_REG_ESP}); + result.push_back({"eip", X86_REG_EIP}); + return result; +} + +template<> +std::vector<Register> ExpectedRegisters<RegsX86_64>() { + std::vector<Register> result; + result.push_back({"rax", X86_64_REG_RAX}); + result.push_back({"rbx", X86_64_REG_RBX}); + result.push_back({"rcx", X86_64_REG_RCX}); + result.push_back({"rdx", X86_64_REG_RDX}); + result.push_back({"r8", X86_64_REG_R8}); + result.push_back({"r9", X86_64_REG_R9}); + result.push_back({"r10", X86_64_REG_R10}); + result.push_back({"r11", X86_64_REG_R11}); + result.push_back({"r12", X86_64_REG_R12}); + result.push_back({"r13", X86_64_REG_R13}); + result.push_back({"r14", X86_64_REG_R14}); + result.push_back({"r15", X86_64_REG_R15}); + result.push_back({"rdi", X86_64_REG_RDI}); + result.push_back({"rsi", X86_64_REG_RSI}); + result.push_back({"rbp", X86_64_REG_RBP}); + result.push_back({"rsp", X86_64_REG_RSP}); + result.push_back({"rip", X86_64_REG_RIP}); + return result; +} + +using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64>; +TYPED_TEST_CASE(RegsIterateTest, RegTypes); + +TYPED_TEST(RegsIterateTest, iterate) { + std::vector<Register> expected = ExpectedRegisters<TypeParam>(); + TypeParam regs; + for (const auto& reg : expected) { + regs[reg.offset] = reg.offset; + } + + std::vector<Register> actual; + regs.IterateRegisters([&actual](const char* name, uint64_t value) { + actual.push_back({name, value}); + }); + + ASSERT_EQ(expected, actual); +} + +} // namespace unwindstack |