Loading libunwindstack/Android.bp +45 −10 Original line number Diff line number Diff line Loading @@ -30,6 +30,15 @@ cc_defaults { enabled: false, }, }, multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, } cc_defaults { Loading @@ -38,8 +47,12 @@ cc_defaults { srcs: [ "ArmExidx.cpp", "Memory.cpp", "Elf.cpp", "ElfInterface.cpp", "ElfInterfaceArm.cpp", "Log.cpp", "Regs.cpp", "Memory.cpp", ], shared_libs: [ Loading Loading @@ -74,6 +87,9 @@ cc_defaults { srcs: [ "tests/ArmExidxDecodeTest.cpp", "tests/ArmExidxExtractTest.cpp", "tests/ElfInterfaceArmTest.cpp", "tests/ElfInterfaceTest.cpp", "tests/ElfTest.cpp", "tests/LogFake.cpp", "tests/MemoryFake.cpp", "tests/MemoryFileTest.cpp", Loading @@ -93,15 +109,6 @@ cc_defaults { "liblog", ], multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, target: { linux: { host_ldlibs: [ Loading Loading @@ -130,3 +137,31 @@ cc_test { "libunwindstack_debug", ], } //------------------------------------------------------------------------- // Utility Executables //------------------------------------------------------------------------- cc_defaults { name: "libunwindstack_executables", defaults: ["libunwindstack_flags"], shared_libs: [ "libunwindstack", "libbase", ], static_libs: [ "liblog", ], compile_multilib: "both", } cc_binary { name: "unwind_info", defaults: ["libunwindstack_executables"], srcs: [ "unwind_info.cpp", ], } libunwindstack/ArmExidx.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include "ArmExidx.h" #include "Log.h" #include "Machine.h" #include "Memory.h" #include "Regs.h" void ArmExidx::LogRawData() { std::string log_str("Raw Data:"); Loading Loading @@ -216,10 +218,16 @@ inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) { cfa_ += 4; } } // If the sp register is modified, change the cfa value. if (registers & (1 << ARM_REG_SP)) { cfa_ = (*regs_)[ARM_REG_SP]; } // Indicate if the pc register was set. if (registers & (1 << ARM_REG_PC)) { pc_set_ = true; } return true; } Loading Loading @@ -296,9 +304,6 @@ inline bool ArmExidx::DecodePrefix_10_11_0000() { return false; } } if (!(*regs_)[ARM_REG_PC]) { (*regs_)[ARM_REG_PC] = (*regs_)[ARM_REG_LR]; } status_ = ARM_STATUS_FINISH; return false; } Loading Loading @@ -675,6 +680,7 @@ bool ArmExidx::Decode() { } bool ArmExidx::Eval() { pc_set_ = false; while (Decode()); return status_ == ARM_STATUS_FINISH; } libunwindstack/ArmExidx.h +10 −5 Original line number Diff line number Diff line Loading @@ -21,8 +21,9 @@ #include <deque> #include "Memory.h" #include "Regs.h" // Forward declarations. class Memory; class RegsArm; enum ArmStatus : size_t { ARM_STATUS_NONE = 0, Loading @@ -43,7 +44,7 @@ enum ArmOp : uint8_t { class ArmExidx { public: ArmExidx(Regs32* regs, Memory* elf_memory, Memory* process_memory) ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory) : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {} virtual ~ArmExidx() {} Loading @@ -59,11 +60,14 @@ class ArmExidx { ArmStatus status() { return status_; } Regs32* regs() { return regs_; } RegsArm* regs() { return regs_; } uint32_t cfa() { return cfa_; } void set_cfa(uint32_t cfa) { cfa_ = cfa; } bool pc_set() { return pc_set_; } void set_pc_set(bool pc_set) { pc_set_ = pc_set; } void set_log(bool log) { log_ = log; } void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; } void set_log_indent(uint8_t indent) { log_indent_ = indent; } Loading @@ -87,7 +91,7 @@ class ArmExidx { bool DecodePrefix_11_010(uint8_t byte); bool DecodePrefix_11(uint8_t byte); Regs32* regs_ = nullptr; RegsArm* regs_ = nullptr; uint32_t cfa_ = 0; std::deque<uint8_t> data_; ArmStatus status_ = ARM_STATUS_NONE; Loading @@ -98,6 +102,7 @@ class ArmExidx { bool log_ = false; uint8_t log_indent_ = 0; bool log_skip_execution_ = false; bool pc_set_ = false; }; #endif // _LIBUNWINDSTACK_ARM_EXIDX_H libunwindstack/Elf.cpp 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 <elf.h> #include <string.h> #include <memory> #include <string> #define LOG_TAG "unwind" #include <log/log.h> #include "Elf.h" #include "ElfInterface.h" #include "ElfInterfaceArm.h" #include "Machine.h" #include "Memory.h" #include "Regs.h" bool Elf::Init() { if (!memory_) { return false; } interface_.reset(CreateInterfaceFromMemory(memory_.get())); if (!interface_) { return false; } valid_ = interface_->Init(); if (valid_) { interface_->InitHeaders(); } else { interface_.reset(nullptr); } return valid_; } bool Elf::IsValidElf(Memory* memory) { if (memory == nullptr) { return false; } // Verify that this is a valid elf file. uint8_t e_ident[SELFMAG + 1]; if (!memory->Read(0, e_ident, SELFMAG)) { return false; } if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { return false; } return true; } ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { if (!IsValidElf(memory)) { return nullptr; } std::unique_ptr<ElfInterface> interface; if (!memory->Read(EI_CLASS, &class_type_, 1)) { return nullptr; } if (class_type_ == ELFCLASS32) { Elf32_Half e_machine; if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) { return nullptr; } if (e_machine != EM_ARM && e_machine != EM_386) { // Unsupported. ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine); return nullptr; } machine_type_ = e_machine; if (e_machine == EM_ARM) { interface.reset(new ElfInterfaceArm(memory)); } else { interface.reset(new ElfInterface32(memory)); } } else if (class_type_ == ELFCLASS64) { Elf64_Half e_machine; if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) { return nullptr; } if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) { // Unsupported. ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine); return nullptr; } machine_type_ = e_machine; interface.reset(new ElfInterface64(memory)); } return interface.release(); } libunwindstack/Elf.h 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ #ifndef _LIBUNWINDSTACK_ELF_H #define _LIBUNWINDSTACK_ELF_H #include <stddef.h> #include <memory> #include <string> #include "ElfInterface.h" #include "Memory.h" #if !defined(EM_AARCH64) #define EM_AARCH64 183 #endif // Forward declaration. class Regs; class Elf { public: Elf(Memory* memory) : memory_(memory) {} virtual ~Elf() = default; bool Init(); void InitGnuDebugdata(); bool GetSoname(std::string* name) { return valid_ && interface_->GetSoname(name); } bool GetFunctionName(uint64_t, std::string*, uint64_t*) { return false; } bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) { return valid_ && interface_->Step(rel_pc, regs, process_memory); } ElfInterface* CreateInterfaceFromMemory(Memory* memory); bool valid() { return valid_; } uint32_t machine_type() { return machine_type_; } uint8_t class_type() { return class_type_; } Memory* memory() { return memory_.get(); } ElfInterface* interface() { return interface_.get(); } static bool IsValidElf(Memory* memory); protected: bool valid_ = false; std::unique_ptr<ElfInterface> interface_; std::unique_ptr<Memory> memory_; uint32_t machine_type_; uint8_t class_type_; }; #endif // _LIBUNWINDSTACK_ELF_H Loading
libunwindstack/Android.bp +45 −10 Original line number Diff line number Diff line Loading @@ -30,6 +30,15 @@ cc_defaults { enabled: false, }, }, multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, } cc_defaults { Loading @@ -38,8 +47,12 @@ cc_defaults { srcs: [ "ArmExidx.cpp", "Memory.cpp", "Elf.cpp", "ElfInterface.cpp", "ElfInterfaceArm.cpp", "Log.cpp", "Regs.cpp", "Memory.cpp", ], shared_libs: [ Loading Loading @@ -74,6 +87,9 @@ cc_defaults { srcs: [ "tests/ArmExidxDecodeTest.cpp", "tests/ArmExidxExtractTest.cpp", "tests/ElfInterfaceArmTest.cpp", "tests/ElfInterfaceTest.cpp", "tests/ElfTest.cpp", "tests/LogFake.cpp", "tests/MemoryFake.cpp", "tests/MemoryFileTest.cpp", Loading @@ -93,15 +109,6 @@ cc_defaults { "liblog", ], multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, target: { linux: { host_ldlibs: [ Loading Loading @@ -130,3 +137,31 @@ cc_test { "libunwindstack_debug", ], } //------------------------------------------------------------------------- // Utility Executables //------------------------------------------------------------------------- cc_defaults { name: "libunwindstack_executables", defaults: ["libunwindstack_flags"], shared_libs: [ "libunwindstack", "libbase", ], static_libs: [ "liblog", ], compile_multilib: "both", } cc_binary { name: "unwind_info", defaults: ["libunwindstack_executables"], srcs: [ "unwind_info.cpp", ], }
libunwindstack/ArmExidx.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include "ArmExidx.h" #include "Log.h" #include "Machine.h" #include "Memory.h" #include "Regs.h" void ArmExidx::LogRawData() { std::string log_str("Raw Data:"); Loading Loading @@ -216,10 +218,16 @@ inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) { cfa_ += 4; } } // If the sp register is modified, change the cfa value. if (registers & (1 << ARM_REG_SP)) { cfa_ = (*regs_)[ARM_REG_SP]; } // Indicate if the pc register was set. if (registers & (1 << ARM_REG_PC)) { pc_set_ = true; } return true; } Loading Loading @@ -296,9 +304,6 @@ inline bool ArmExidx::DecodePrefix_10_11_0000() { return false; } } if (!(*regs_)[ARM_REG_PC]) { (*regs_)[ARM_REG_PC] = (*regs_)[ARM_REG_LR]; } status_ = ARM_STATUS_FINISH; return false; } Loading Loading @@ -675,6 +680,7 @@ bool ArmExidx::Decode() { } bool ArmExidx::Eval() { pc_set_ = false; while (Decode()); return status_ == ARM_STATUS_FINISH; }
libunwindstack/ArmExidx.h +10 −5 Original line number Diff line number Diff line Loading @@ -21,8 +21,9 @@ #include <deque> #include "Memory.h" #include "Regs.h" // Forward declarations. class Memory; class RegsArm; enum ArmStatus : size_t { ARM_STATUS_NONE = 0, Loading @@ -43,7 +44,7 @@ enum ArmOp : uint8_t { class ArmExidx { public: ArmExidx(Regs32* regs, Memory* elf_memory, Memory* process_memory) ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory) : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {} virtual ~ArmExidx() {} Loading @@ -59,11 +60,14 @@ class ArmExidx { ArmStatus status() { return status_; } Regs32* regs() { return regs_; } RegsArm* regs() { return regs_; } uint32_t cfa() { return cfa_; } void set_cfa(uint32_t cfa) { cfa_ = cfa; } bool pc_set() { return pc_set_; } void set_pc_set(bool pc_set) { pc_set_ = pc_set; } void set_log(bool log) { log_ = log; } void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; } void set_log_indent(uint8_t indent) { log_indent_ = indent; } Loading @@ -87,7 +91,7 @@ class ArmExidx { bool DecodePrefix_11_010(uint8_t byte); bool DecodePrefix_11(uint8_t byte); Regs32* regs_ = nullptr; RegsArm* regs_ = nullptr; uint32_t cfa_ = 0; std::deque<uint8_t> data_; ArmStatus status_ = ARM_STATUS_NONE; Loading @@ -98,6 +102,7 @@ class ArmExidx { bool log_ = false; uint8_t log_indent_ = 0; bool log_skip_execution_ = false; bool pc_set_ = false; }; #endif // _LIBUNWINDSTACK_ARM_EXIDX_H
libunwindstack/Elf.cpp 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 <elf.h> #include <string.h> #include <memory> #include <string> #define LOG_TAG "unwind" #include <log/log.h> #include "Elf.h" #include "ElfInterface.h" #include "ElfInterfaceArm.h" #include "Machine.h" #include "Memory.h" #include "Regs.h" bool Elf::Init() { if (!memory_) { return false; } interface_.reset(CreateInterfaceFromMemory(memory_.get())); if (!interface_) { return false; } valid_ = interface_->Init(); if (valid_) { interface_->InitHeaders(); } else { interface_.reset(nullptr); } return valid_; } bool Elf::IsValidElf(Memory* memory) { if (memory == nullptr) { return false; } // Verify that this is a valid elf file. uint8_t e_ident[SELFMAG + 1]; if (!memory->Read(0, e_ident, SELFMAG)) { return false; } if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { return false; } return true; } ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { if (!IsValidElf(memory)) { return nullptr; } std::unique_ptr<ElfInterface> interface; if (!memory->Read(EI_CLASS, &class_type_, 1)) { return nullptr; } if (class_type_ == ELFCLASS32) { Elf32_Half e_machine; if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) { return nullptr; } if (e_machine != EM_ARM && e_machine != EM_386) { // Unsupported. ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine); return nullptr; } machine_type_ = e_machine; if (e_machine == EM_ARM) { interface.reset(new ElfInterfaceArm(memory)); } else { interface.reset(new ElfInterface32(memory)); } } else if (class_type_ == ELFCLASS64) { Elf64_Half e_machine; if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) { return nullptr; } if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) { // Unsupported. ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine); return nullptr; } machine_type_ = e_machine; interface.reset(new ElfInterface64(memory)); } return interface.release(); }
libunwindstack/Elf.h 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ #ifndef _LIBUNWINDSTACK_ELF_H #define _LIBUNWINDSTACK_ELF_H #include <stddef.h> #include <memory> #include <string> #include "ElfInterface.h" #include "Memory.h" #if !defined(EM_AARCH64) #define EM_AARCH64 183 #endif // Forward declaration. class Regs; class Elf { public: Elf(Memory* memory) : memory_(memory) {} virtual ~Elf() = default; bool Init(); void InitGnuDebugdata(); bool GetSoname(std::string* name) { return valid_ && interface_->GetSoname(name); } bool GetFunctionName(uint64_t, std::string*, uint64_t*) { return false; } bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) { return valid_ && interface_->Step(rel_pc, regs, process_memory); } ElfInterface* CreateInterfaceFromMemory(Memory* memory); bool valid() { return valid_; } uint32_t machine_type() { return machine_type_; } uint8_t class_type() { return class_type_; } Memory* memory() { return memory_.get(); } ElfInterface* interface() { return interface_.get(); } static bool IsValidElf(Memory* memory); protected: bool valid_ = false; std::unique_ptr<ElfInterface> interface_; std::unique_ptr<Memory> memory_; uint32_t machine_type_; uint8_t class_type_; }; #endif // _LIBUNWINDSTACK_ELF_H