Make the library usable as a library.
- Add namespace unwindstack everywhere so that it's easier for other code to use the library. - Move some of the header files into include/unwindstack so that they can be exposed. - Modify the headers so that only a limited number need to be exposed. - Update the tools to use the new headers. - Add a GetLoadBias() call on the Elf object. This prevents the need to get the interface object out of the Elf object. - Move the GetRelPc() call out of the Reg class, to the Elf class. It's not always the case that a Reg object will be around when you want to get a relative pc. The tests for this moved to ElfTest.cpp. Bug: 23762183 Test: Unit tests pass. Change-Id: Iac609dac1dd90ed83d1a1e24ff2579c96c023bc3
This commit is contained in:
parent
b76158d56a
commit
d226a51409
|
@ -44,6 +44,7 @@ cc_defaults {
|
|||
cc_library {
|
||||
name: "libunwindstack",
|
||||
defaults: ["libunwindstack_flags"],
|
||||
export_include_dirs: ["include"],
|
||||
|
||||
srcs: [
|
||||
"ArmExidx.cpp",
|
||||
|
|
|
@ -21,12 +21,15 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "ArmExidx.h"
|
||||
#include "Check.h"
|
||||
#include "Log.h"
|
||||
#include "Machine.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void ArmExidx::LogRawData() {
|
||||
std::string log_str("Raw Data:");
|
||||
|
@ -684,3 +687,5 @@ bool ArmExidx::Eval() {
|
|||
while (Decode());
|
||||
return status_ == ARM_STATUS_FINISH;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <deque>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Memory;
|
||||
class RegsArm;
|
||||
|
@ -105,4 +107,6 @@ class ArmExidx {
|
|||
bool pc_set_ = false;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_ARM_EXIDX_H
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Log.h"
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
#define CHECK(assertion) \
|
||||
if (__builtin_expect(!(assertion), false)) { \
|
||||
|
@ -27,4 +29,6 @@
|
|||
abort(); \
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_ERROR_H
|
||||
|
|
|
@ -23,12 +23,15 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "DwarfCfa.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfOp.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
constexpr typename DwarfCfa<AddressType>::process_func DwarfCfa<AddressType>::kCallbackTable[64];
|
||||
|
@ -711,3 +714,5 @@ const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = {
|
|||
// Explicitly instantiate DwarfCfa.
|
||||
template class DwarfCfa<uint32_t>;
|
||||
template class DwarfCfa<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -24,10 +24,13 @@
|
|||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfLocation.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfStructs.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// DWARF Standard home: http://dwarfstd.org/
|
||||
// This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf
|
||||
|
@ -252,4 +255,6 @@ class DwarfCfa {
|
|||
};
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_CFA_H
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "DwarfDebugFrame.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfSection.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Memory.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) {
|
||||
|
@ -309,3 +312,5 @@ const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) {
|
|||
// Explicitly instantiate DwarfDebugFrame.
|
||||
template class DwarfDebugFrame<uint32_t>;
|
||||
template class DwarfDebugFrame<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "DwarfSection.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
|
||||
|
@ -73,4 +75,6 @@ class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
|
|||
std::vector<FdeInfo> fdes_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "Check.h"
|
||||
#include "DwarfEhFrame.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfSection.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Memory.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) {
|
||||
|
@ -211,3 +213,5 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_of
|
|||
// Explicitly instantiate DwarfEhFrame.
|
||||
template class DwarfEhFrame<uint32_t>;
|
||||
template class DwarfEhFrame<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "DwarfSection.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Memory;
|
||||
|
@ -86,4 +88,6 @@ class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
|
|||
std::unordered_map<uint64_t, FdeInfo> fde_info_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
enum DwarfEncoding : uint8_t {
|
||||
DW_EH_PE_omit = 0xff,
|
||||
|
||||
|
@ -44,4 +46,6 @@ enum DwarfEncoding : uint8_t {
|
|||
DW_EH_PE_block = 0x0f,
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_ENCODING_H
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
enum DwarfError : uint8_t {
|
||||
DWARF_ERROR_NONE,
|
||||
DWARF_ERROR_MEMORY_INVALID,
|
||||
|
@ -31,4 +33,6 @@ enum DwarfError : uint8_t {
|
|||
DWARF_ERROR_UNSUPPORTED_VERSION,
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_ERROR_H
|
||||
|
|
|
@ -18,10 +18,13 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "Check.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "Memory.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) {
|
||||
if (!memory_->Read(cur_offset_, dst, num_bytes)) {
|
||||
|
@ -246,3 +249,5 @@ template size_t DwarfMemory::GetEncodedSize<uint64_t>(uint8_t);
|
|||
|
||||
template bool DwarfMemory::ReadEncodedValue<uint32_t>(uint8_t, uint64_t*);
|
||||
template bool DwarfMemory::ReadEncodedValue<uint64_t>(uint8_t, uint64_t*);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfOp.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
|
||||
|
@ -460,3 +463,5 @@ bool DwarfOp<AddressType>::op_not_implemented() {
|
|||
// Explicitly instantiate DwarfOp.
|
||||
template class DwarfOp<uint32_t>;
|
||||
template class DwarfOp<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <vector>
|
||||
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
enum DwarfVersion : uint8_t {
|
||||
DWARF_VERSION_2 = 2,
|
||||
|
@ -1633,4 +1636,6 @@ class DwarfOp {
|
|||
};
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_OP_H
|
||||
|
|
|
@ -16,16 +16,22 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "DwarfCfa.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfLocation.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfOp.h"
|
||||
#include "DwarfSection.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
|
||||
|
||||
const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
|
||||
uint64_t fde_offset;
|
||||
|
@ -42,6 +48,7 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
|
|||
}
|
||||
|
||||
bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
|
||||
last_error_ = DWARF_ERROR_NONE;
|
||||
const DwarfFde* fde = GetFdeFromPc(pc);
|
||||
if (fde == nullptr || fde->cie == nullptr) {
|
||||
last_error_ = DWARF_ERROR_ILLEGAL_STATE;
|
||||
|
@ -248,6 +255,9 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
|
|||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
// Set the default for the lsda encoding.
|
||||
cie->lsda_encoding = DW_EH_PE_omit;
|
||||
|
||||
if (length32 == static_cast<uint32_t>(-1)) {
|
||||
// 64 bit Cie
|
||||
uint64_t length64;
|
||||
|
@ -541,3 +551,5 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t lo
|
|||
// Explicitly instantiate DwarfSectionImpl
|
||||
template class DwarfSectionImpl<uint32_t>;
|
||||
template class DwarfSectionImpl<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -23,12 +23,17 @@
|
|||
#define LOG_TAG "unwind"
|
||||
#include <log/log.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "ElfInterface.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "ElfInterfaceArm.h"
|
||||
#include "Machine.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
bool Elf::Init() {
|
||||
if (!memory_) {
|
||||
|
@ -71,6 +76,36 @@ void Elf::InitGnuDebugdata() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Elf::GetSoname(std::string* name) {
|
||||
return valid_ && interface_->GetSoname(name);
|
||||
}
|
||||
|
||||
uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
|
||||
uint64_t load_bias = 0;
|
||||
if (valid()) {
|
||||
load_bias = interface_->load_bias();
|
||||
}
|
||||
|
||||
return pc - map_info->start + load_bias + map_info->elf_offset;
|
||||
}
|
||||
|
||||
bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
|
||||
return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
|
||||
(gnu_debugdata_interface_ &&
|
||||
gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
|
||||
}
|
||||
|
||||
bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
|
||||
return valid_ && (interface_->Step(rel_pc, regs, process_memory) ||
|
||||
(gnu_debugdata_interface_ &&
|
||||
gnu_debugdata_interface_->Step(rel_pc, regs, process_memory)));
|
||||
}
|
||||
|
||||
uint64_t Elf::GetLoadBias() {
|
||||
if (!valid_) return 0;
|
||||
return interface_->load_bias();
|
||||
}
|
||||
|
||||
bool Elf::IsValidElf(Memory* memory) {
|
||||
if (memory == nullptr) {
|
||||
return false;
|
||||
|
@ -133,3 +168,5 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
|
|||
|
||||
return interface.release();
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -24,15 +24,18 @@
|
|||
#include <Xz.h>
|
||||
#include <XzCrc64.h>
|
||||
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "DwarfDebugFrame.h"
|
||||
#include "DwarfEhFrame.h"
|
||||
#include "DwarfSection.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
ElfInterface::~ElfInterface() {
|
||||
for (auto symbol : symbols_) {
|
||||
delete symbol;
|
||||
|
@ -387,3 +390,5 @@ template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std
|
|||
uint64_t*);
|
||||
template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
|
||||
uint64_t*);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
#include <elf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "ArmExidx.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "ElfInterfaceArm.h"
|
||||
#include "Machine.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
|
||||
if (start_offset_ == 0 || total_entries_ == 0) {
|
||||
|
@ -127,3 +129,5 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ElfInterface.h"
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ElfInterfaceArm : public ElfInterface32 {
|
||||
public:
|
||||
|
@ -87,4 +89,6 @@ class ElfInterfaceArm : public ElfInterface32 {
|
|||
std::unordered_map<size_t, uint32_t> addrs_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include "Log.h"
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
static bool g_print_to_stdout = false;
|
||||
|
||||
|
@ -51,3 +53,5 @@ void log(uint8_t indent, const char* format, ...) {
|
|||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
enum ArmReg : uint16_t {
|
||||
ARM_REG_R0 = 0,
|
||||
ARM_REG_R1,
|
||||
|
@ -134,4 +136,6 @@ enum X86_64Reg : uint16_t {
|
|||
X86_64_REG_PC = X86_64_REG_RIP,
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_MACHINE_H
|
||||
|
|
|
@ -20,10 +20,12 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "MapInfo.h"
|
||||
#include "Maps.h"
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
Memory* MapInfo::CreateMemory(pid_t pid) {
|
||||
if (end <= start) {
|
||||
|
@ -86,3 +88,5 @@ Elf* MapInfo::GetElf(pid_t pid, bool init_gnu_debugdata) {
|
|||
// don't try to reinit the object.
|
||||
return elf;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Maps.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
MapInfo* Maps::Find(uint64_t pc) {
|
||||
if (maps_.empty()) {
|
||||
|
@ -196,3 +200,5 @@ bool OfflineMaps::Parse() {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -28,7 +28,11 @@
|
|||
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "Check.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
|
||||
string->clear();
|
||||
|
@ -245,6 +249,11 @@ bool MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
MemoryRange::MemoryRange(Memory* memory, uint64_t begin, uint64_t end)
|
||||
: memory_(memory), begin_(begin), length_(end - begin) {
|
||||
CHECK(end > begin);
|
||||
}
|
||||
|
||||
bool MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
|
||||
uint64_t max_read;
|
||||
if (__builtin_add_overflow(addr, size, &max_read) || max_read > length_) {
|
||||
|
@ -253,3 +262,5 @@ bool MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
|
|||
// The check above guarantees that addr + begin_ will not overflow.
|
||||
return memory_->Read(addr + begin_, dst, size);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,24 +21,17 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "Check.h"
|
||||
#include "Elf.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "Machine.h"
|
||||
#include "MapInfo.h"
|
||||
#include "Regs.h"
|
||||
#include "Ucontext.h"
|
||||
#include "User.h"
|
||||
|
||||
template <typename AddressType>
|
||||
uint64_t RegsImpl<AddressType>::GetRelPc(Elf* elf, const MapInfo* map_info) {
|
||||
uint64_t load_bias = 0;
|
||||
if (elf->valid()) {
|
||||
load_bias = elf->interface()->load_bias();
|
||||
}
|
||||
|
||||
return pc_ - map_info->start + load_bias + map_info->elf_offset;
|
||||
}
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
bool RegsImpl<AddressType>::GetReturnAddressFromDefault(Memory* memory, uint64_t* value) {
|
||||
|
@ -354,3 +347,5 @@ Regs* Regs::CreateFromLocal() {
|
|||
#endif
|
||||
return regs;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "Check.h"
|
||||
#include "Memory.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
Symbols::Symbols(uint64_t offset, uint64_t size, uint64_t entry_size, uint64_t str_offset,
|
||||
uint64_t str_size)
|
||||
: cur_offset_(offset),
|
||||
|
@ -108,3 +111,5 @@ bool Symbols::GetName(uint64_t addr, uint64_t load_bias, Memory* elf_memory, std
|
|||
// Instantiate all of the needed template functions.
|
||||
template bool Symbols::GetName<Elf32_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*);
|
||||
template bool Symbols::GetName<Elf64_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declaration.
|
||||
class Memory;
|
||||
|
||||
|
@ -61,4 +63,6 @@ class Symbols {
|
|||
std::vector<Info> symbols_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_SYMBOLS_H
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// ARM ucontext structures
|
||||
//-------------------------------------------------------------------
|
||||
|
@ -177,4 +179,6 @@ typedef struct x86_64_ucontext {
|
|||
} x86_64_ucontext_t;
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_UCONTEXT_H
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#ifndef _LIBUNWINDSTACK_USER_H
|
||||
#define _LIBUNWINDSTACK_USER_H
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
struct x86_user_regs {
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
|
@ -93,4 +95,6 @@ struct arm64_user_regs {
|
|||
// The largest user structure.
|
||||
constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_USER_H
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
enum DwarfLocationEnum : uint8_t {
|
||||
DWARF_LOCATION_INVALID = 0,
|
||||
DWARF_LOCATION_UNDEFINED,
|
||||
|
@ -38,4 +40,6 @@ struct DwarfLocation {
|
|||
|
||||
typedef std::unordered_map<uint16_t, DwarfLocation> dwarf_loc_regs_t;
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_LOCATION_H
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Memory;
|
||||
|
||||
|
@ -69,4 +71,6 @@ class DwarfMemory {
|
|||
uint64_t text_offset_ = static_cast<uint64_t>(-1);
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_MEMORY_H
|
|
@ -22,18 +22,20 @@
|
|||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfLocation.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
enum DwarfError : uint8_t;
|
||||
class Memory;
|
||||
class Regs;
|
||||
|
||||
class DwarfSection {
|
||||
public:
|
||||
DwarfSection(Memory* memory) : memory_(memory) {}
|
||||
DwarfSection(Memory* memory);
|
||||
virtual ~DwarfSection() = default;
|
||||
|
||||
class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
|
||||
|
@ -102,7 +104,7 @@ class DwarfSection {
|
|||
|
||||
protected:
|
||||
DwarfMemory memory_;
|
||||
DwarfError last_error_ = DWARF_ERROR_NONE;
|
||||
DwarfError last_error_;
|
||||
|
||||
uint64_t fde_count_;
|
||||
std::unordered_map<uint64_t, DwarfFde> fde_entries_;
|
||||
|
@ -134,4 +136,6 @@ class DwarfSectionImpl : public DwarfSection {
|
|||
AddressType* value);
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_SECTION_H
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "DwarfEncoding.h"
|
||||
namespace unwindstack {
|
||||
|
||||
struct DwarfCie {
|
||||
uint8_t version = 0;
|
||||
uint8_t fde_address_encoding = DW_EH_PE_absptr;
|
||||
uint8_t lsda_encoding = DW_EH_PE_omit;
|
||||
uint8_t fde_address_encoding = 0;
|
||||
uint8_t lsda_encoding = 0;
|
||||
uint8_t segment_size = 0;
|
||||
std::vector<char> augmentation_string;
|
||||
uint64_t personality_handler = 0;
|
||||
|
@ -49,4 +49,6 @@ struct DwarfFde {
|
|||
|
||||
constexpr uint16_t CFA_REG = static_cast<uint16_t>(-1);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_DWARF_STRUCTS_H
|
|
@ -22,14 +22,17 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ElfInterface.h"
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#if !defined(EM_AARCH64)
|
||||
#define EM_AARCH64 183
|
||||
#endif
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declaration.
|
||||
struct MapInfo;
|
||||
class Regs;
|
||||
|
||||
class Elf {
|
||||
|
@ -41,24 +44,18 @@ class Elf {
|
|||
|
||||
void InitGnuDebugdata();
|
||||
|
||||
bool GetSoname(std::string* name) {
|
||||
return valid_ && interface_->GetSoname(name);
|
||||
}
|
||||
bool GetSoname(std::string* name);
|
||||
|
||||
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
|
||||
return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
|
||||
(gnu_debugdata_interface_ &&
|
||||
gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
|
||||
}
|
||||
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
|
||||
|
||||
bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
|
||||
return valid_ && (interface_->Step(rel_pc, regs, process_memory) ||
|
||||
(gnu_debugdata_interface_ &&
|
||||
gnu_debugdata_interface_->Step(rel_pc, regs, process_memory)));
|
||||
}
|
||||
uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
|
||||
|
||||
bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory);
|
||||
|
||||
ElfInterface* CreateInterfaceFromMemory(Memory* memory);
|
||||
|
||||
uint64_t GetLoadBias();
|
||||
|
||||
bool valid() { return valid_; }
|
||||
|
||||
uint32_t machine_type() { return machine_type_; }
|
||||
|
@ -84,4 +81,6 @@ class Elf {
|
|||
std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_ELF_H
|
|
@ -25,7 +25,9 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "DwarfSection.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Memory;
|
||||
|
@ -166,4 +168,6 @@ class ElfInterface64 : public ElfInterface {
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_ELF_INTERFACE_H
|
|
@ -19,7 +19,11 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void log_to_stdout(bool enable);
|
||||
void log(uint8_t indent, const char* format, ...);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_LOG_H
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Elf;
|
||||
class Memory;
|
||||
|
@ -42,4 +44,6 @@ struct MapInfo {
|
|||
Elf* GetElf(pid_t pid, bool init_gnu_debugdata = false);
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_MAP_INFO_H
|
|
@ -23,8 +23,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "MapInfo.h"
|
||||
#include <unwindstack/MapInfo.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Special flag to indicate a map is in /dev/. However, a map in
|
||||
// /dev/ashmem/... does not set this flag.
|
||||
|
@ -104,4 +105,6 @@ class OfflineMaps : public FileMaps {
|
|||
bool Parse() override;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_MAPS_H
|
|
@ -24,7 +24,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Check.h"
|
||||
namespace unwindstack {
|
||||
|
||||
class Memory {
|
||||
public:
|
||||
|
@ -47,13 +47,9 @@ class Memory {
|
|||
return Read(offset, field, size);
|
||||
}
|
||||
|
||||
inline bool Read32(uint64_t addr, uint32_t* dst) {
|
||||
return Read(addr, dst, sizeof(uint32_t));
|
||||
}
|
||||
inline bool Read32(uint64_t addr, uint32_t* dst) { return Read(addr, dst, sizeof(uint32_t)); }
|
||||
|
||||
inline bool Read64(uint64_t addr, uint64_t* dst) {
|
||||
return Read(addr, dst, sizeof(uint64_t));
|
||||
}
|
||||
inline bool Read64(uint64_t addr, uint64_t* dst) { return Read(addr, dst, sizeof(uint64_t)); }
|
||||
};
|
||||
|
||||
class MemoryBuffer : public Memory {
|
||||
|
@ -129,10 +125,7 @@ class MemoryLocal : public Memory {
|
|||
|
||||
class MemoryRange : public Memory {
|
||||
public:
|
||||
MemoryRange(Memory* memory, uint64_t begin, uint64_t end)
|
||||
: memory_(memory), begin_(begin), length_(end - begin) {
|
||||
CHECK(end > begin);
|
||||
}
|
||||
MemoryRange(Memory* memory, uint64_t begin, uint64_t end);
|
||||
virtual ~MemoryRange() { delete memory_; }
|
||||
|
||||
bool Read(uint64_t addr, void* dst, size_t size) override;
|
||||
|
@ -143,4 +136,6 @@ class MemoryRange : public Memory {
|
|||
uint64_t length_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_MEMORY_H
|
|
@ -21,9 +21,12 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
// Forward declarations.
|
||||
class Elf;
|
||||
struct MapInfo;
|
||||
class Memory;
|
||||
|
||||
class Regs {
|
||||
public:
|
||||
|
@ -50,8 +53,6 @@ class Regs {
|
|||
|
||||
virtual bool GetReturnAddressFromDefault(Memory* memory, uint64_t* value) = 0;
|
||||
|
||||
virtual uint64_t GetRelPc(Elf* elf, const MapInfo* map_info) = 0;
|
||||
|
||||
virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0;
|
||||
|
||||
virtual void SetFromRaw() = 0;
|
||||
|
@ -77,8 +78,6 @@ class RegsImpl : public Regs {
|
|||
: Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {}
|
||||
virtual ~RegsImpl() = default;
|
||||
|
||||
uint64_t GetRelPc(Elf* elf, const MapInfo* map_info) override;
|
||||
|
||||
bool GetReturnAddressFromDefault(Memory* memory, uint64_t* value) override;
|
||||
|
||||
uint64_t pc() override { return pc_; }
|
||||
|
@ -137,4 +136,6 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
|
|||
void SetFromRaw() override;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_REGS_H
|
|
@ -29,6 +29,8 @@
|
|||
#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H
|
||||
#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
inline void RegsGetLocal(Regs* regs) {
|
||||
|
@ -97,4 +99,6 @@ inline void RegsGetLocal(Regs* regs) {
|
|||
|
||||
#endif
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_REGS_GET_LOCAL_H
|
|
@ -23,13 +23,16 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "ArmExidx.h"
|
||||
#include "Regs.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
|
||||
protected:
|
||||
void Init(Memory* process_memory = nullptr) {
|
||||
|
@ -1092,3 +1095,5 @@ TEST_P(ArmExidxDecodeTest, eval_pc_set) {
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest, ::testing::Values("logging", "no_logging"));
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,12 +21,15 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "ArmExidx.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ArmExidxExtractTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -329,3 +332,5 @@ TEST_F(ArmExidxExtractTest, raw_data_non_compact) {
|
|||
ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
|
||||
ASSERT_EQ("4 unwind Raw Data: 0x11 0x22 0x33 0xb0\n", GetFakeLogPrint());
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -23,15 +23,18 @@
|
|||
#include <android-base/stringprintf.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "DwarfCfa.h"
|
||||
#include "DwarfLocation.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class DwarfCfaLogTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -812,3 +815,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cf
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaLogTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfCfaLogTest, DwarfCfaLogTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,15 +21,19 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfLocation.h>
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "DwarfCfa.h"
|
||||
#include "DwarfLocation.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Log.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class DwarfCfaTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -957,3 +961,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_o
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfCfaTest, DwarfCfaTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
|
||||
#include "DwarfDebugFrame.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
#include "RegsFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfDebugFrame : public DwarfDebugFrame<TypeParam> {
|
||||
public:
|
||||
|
@ -454,3 +457,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
|
||||
#include "DwarfEhFrame.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
#include "RegsFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> {
|
||||
public:
|
||||
|
@ -407,3 +410,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init, GetFdeInfoFromIndex_expect_ca
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "DwarfMemory.h"
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class DwarfMemoryTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -494,3 +496,5 @@ TEST_F(DwarfMemoryTest, AdjustEncodedValue_funcrel) {
|
|||
ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x40, &value));
|
||||
ASSERT_EQ(0x14234U, value);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,14 +21,17 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfOp.h"
|
||||
#include "Log.h"
|
||||
#include "Regs.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class DwarfOpLogTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -66,3 +69,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfOpLogTest, multiple_ops);
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfOpLogTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpLogTest, DwarfOpLogTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,14 +21,17 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfMemory.h>
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "DwarfError.h"
|
||||
#include "DwarfMemory.h"
|
||||
#include "DwarfOp.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
#include "RegsFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class DwarfOpTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -1579,3 +1582,5 @@ REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, illegal_in
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpTest, DwarfOpTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,12 +19,17 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "DwarfSection.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
#include "LogFake.h"
|
||||
#include "MemoryFake.h"
|
||||
#include "RegsFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
|
||||
public:
|
||||
|
@ -830,3 +835,5 @@ REGISTER_TYPED_TEST_CASE_P(
|
|||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "DwarfSection.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MockDwarfSection : public DwarfSection {
|
||||
public:
|
||||
MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
|
||||
|
@ -158,3 +160,5 @@ TEST_F(DwarfSectionTest, Step_pass) {
|
|||
|
||||
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -20,12 +20,15 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "ElfInterfaceArm.h"
|
||||
#include "Machine.h"
|
||||
#include "Regs.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ElfInterfaceArmTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -370,3 +373,5 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
|
|||
ASSERT_EQ(0x10U, regs.pc());
|
||||
ASSERT_EQ(0x10U, regs[ARM_REG_PC]);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ElfInterface.h"
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
|
||||
#include "DwarfEncoding.h"
|
||||
#include "ElfInterfaceArm.h"
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
@ -33,6 +35,8 @@
|
|||
#define EM_AARCH64 183
|
||||
#endif
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ElfInterfaceTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -921,3 +925,5 @@ TEST_F(ElfInterfaceTest, init_section_headers_offsets32) {
|
|||
TEST_F(ElfInterfaceTest, init_section_headers_offsets64) {
|
||||
InitSectionHeadersOffsets<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
|
||||
#include "ElfTestUtils.h"
|
||||
#include "MemoryFake.h"
|
||||
|
@ -31,6 +32,8 @@
|
|||
#define PT_ARM_EXIDX 0x70000001
|
||||
#endif
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ElfTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -237,3 +240,33 @@ TEST_F(ElfTest, gnu_debugdata_init64) {
|
|||
elf.InitGnuDebugdata();
|
||||
ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
|
||||
}
|
||||
|
||||
class MockElf : public Elf {
|
||||
public:
|
||||
MockElf(Memory* memory) : Elf(memory) {}
|
||||
virtual ~MockElf() = default;
|
||||
|
||||
void set_valid(bool valid) { valid_ = valid; }
|
||||
void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
|
||||
};
|
||||
|
||||
TEST_F(ElfTest, rel_pc) {
|
||||
MockElf elf(memory_);
|
||||
|
||||
ElfInterface* interface = new ElfInterface32(memory_);
|
||||
elf.set_elf_interface(interface);
|
||||
|
||||
elf.set_valid(true);
|
||||
interface->set_load_bias(0);
|
||||
MapInfo map_info{.start = 0x1000, .end = 0x2000};
|
||||
|
||||
ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
|
||||
|
||||
interface->set_load_bias(0x3000);
|
||||
ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
|
||||
|
||||
elf.set_valid(false);
|
||||
ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "ElfTestUtils.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename Ehdr>
|
||||
void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type) {
|
||||
memset(ehdr, 0, sizeof(Ehdr));
|
||||
|
@ -136,3 +138,5 @@ template void TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(uint32_t, uint32_t, b
|
|||
TestCopyFuncType);
|
||||
template void TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(uint32_t, uint32_t, bool,
|
||||
TestCopyFuncType);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
typedef std::function<void(uint64_t, const void*, size_t)> TestCopyFuncType;
|
||||
|
||||
template <typename Ehdr>
|
||||
|
@ -28,4 +30,6 @@ template <typename Ehdr, typename Shdr>
|
|||
void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine_type, bool init_gnu_debudata,
|
||||
TestCopyFuncType copy_func);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "LogFake.h"
|
||||
|
||||
// Forward declarations.
|
||||
class Backtrace;
|
||||
struct EventTagMap;
|
||||
struct AndroidLogEntry;
|
||||
|
||||
|
@ -33,6 +32,8 @@ std::string g_fake_log_buf;
|
|||
|
||||
std::string g_fake_log_print;
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void ResetLogs() {
|
||||
g_fake_log_buf = "";
|
||||
g_fake_log_print = "";
|
||||
|
@ -46,6 +47,8 @@ std::string GetFakeLogPrint() {
|
|||
return g_fake_log_print;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) {
|
||||
g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' ';
|
||||
g_fake_log_buf += tag;
|
||||
|
|
|
@ -19,8 +19,12 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void ResetLogs();
|
||||
std::string GetFakeLogBuf();
|
||||
std::string GetFakeLogPrint();
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
#include <android-base/test_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "MapInfo.h"
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MapInfoCreateMemoryTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -203,3 +205,5 @@ TEST_F(MapInfoCreateMemoryTest, remote_memory) {
|
|||
kill(pid, SIGKILL);
|
||||
ASSERT_EQ(pid, wait(nullptr));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -30,9 +30,13 @@
|
|||
#include <android-base/test_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "ElfTestUtils.h"
|
||||
#include "MapInfo.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MapInfoGetElfTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -138,3 +142,5 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
|
|||
EXPECT_EQ(ELFCLASS64, elf->class_type());
|
||||
EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include <android-base/test_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Maps.h"
|
||||
#include <unwindstack/Maps.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
TEST(MapsTest, parse_permissions) {
|
||||
BufferMaps maps(
|
||||
|
@ -235,3 +237,5 @@ TEST(MapsTest, find) {
|
|||
ASSERT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags);
|
||||
ASSERT_EQ("/system/lib/fake5.so", info->name);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "LogFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MemoryBufferTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
@ -75,3 +77,5 @@ TEST_F(MemoryBufferTest, read_failure_overflow) {
|
|||
|
||||
ASSERT_FALSE(memory_->Read(UINT64_MAX - 100, buffer.data(), 200));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) {
|
||||
const uint8_t* src = reinterpret_cast<const uint8_t*>(memory);
|
||||
for (size_t i = 0; i < length; i++, addr++) {
|
||||
|
@ -44,3 +46,5 @@ bool MemoryFake::Read(uint64_t addr, void* memory, size_t size) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MemoryFake : public Memory {
|
||||
public:
|
||||
|
@ -87,4 +89,6 @@ class MemoryFakeRemote : public MemoryRemote {
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include <android-base/file.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MemoryFileTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -269,3 +271,5 @@ TEST_F(MemoryFileTest, init_reinit) {
|
|||
ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
TEST(MemoryLocalTest, read) {
|
||||
std::vector<uint8_t> src(1024);
|
||||
|
@ -64,3 +66,5 @@ TEST(MemoryLocalTest, read_overflow) {
|
|||
uint64_t value;
|
||||
ASSERT_FALSE(local.Read(reinterpret_cast<uint64_t>(&value), dst.data(), SIZE_MAX));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
TEST(MemoryRangeTest, read) {
|
||||
std::vector<uint8_t> src(1024);
|
||||
memset(src.data(), 0x4c, 1024);
|
||||
|
@ -70,3 +72,5 @@ TEST(MemoryRangeTest, read_overflow) {
|
|||
std::unique_ptr<MemoryRange> overflow(new MemoryRange(new MemoryFakeAlwaysReadZero, 100, 200));
|
||||
ASSERT_FALSE(overflow->Read(UINT64_MAX - 10, buffer.data(), 100));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -31,10 +31,12 @@
|
|||
#include <android-base/file.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class MemoryRemoteTest : public ::testing::Test {
|
||||
protected:
|
||||
static uint64_t NanoTime() {
|
||||
|
@ -164,3 +166,5 @@ TEST_F(MemoryRemoteTest, read_illegal) {
|
|||
kill(pid, SIGKILL);
|
||||
ASSERT_EQ(pid, wait(nullptr));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
TEST(MemoryTest, read32) {
|
||||
MemoryFakeAlwaysReadZero memory;
|
||||
|
||||
|
@ -124,3 +126,5 @@ TEST(MemoryTest, read_string_error) {
|
|||
ASSERT_TRUE(memory.ReadString(0, &dst_name));
|
||||
ASSERT_EQ("short", dst_name);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Regs.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class RegsFake : public RegsImpl<TypeParam> {
|
||||
|
@ -28,10 +31,11 @@ class RegsFake : public RegsImpl<TypeParam> {
|
|||
: RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
|
||||
virtual ~RegsFake() = default;
|
||||
|
||||
uint64_t GetRelPc(Elf*, const MapInfo*) override { return 0; }
|
||||
uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
|
||||
void SetFromRaw() override {}
|
||||
bool GetReturnAddressFromDefault(Memory*, uint64_t*) { return false; }
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
|
||||
|
|
|
@ -18,13 +18,15 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "MapInfo.h"
|
||||
#include "Regs.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
class ElfFake : public Elf {
|
||||
public:
|
||||
ElfFake(Memory* memory) : Elf(memory) { valid_ = true; }
|
||||
|
@ -69,9 +71,6 @@ class RegsTest : public ::testing::Test {
|
|||
elf_->set_elf_interface(elf_interface_);
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
void regs_rel_pc();
|
||||
|
||||
template <typename AddressType>
|
||||
void regs_return_address_register();
|
||||
|
||||
|
@ -126,26 +125,6 @@ TEST_F(RegsTest, regs64) {
|
|||
ASSERT_EQ(10U, regs64[8]);
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
void RegsTest::regs_rel_pc() {
|
||||
RegsTestImpl<AddressType> regs(30, 12);
|
||||
|
||||
elf_interface_->set_load_bias(0);
|
||||
MapInfo map_info{.start = 0x1000, .end = 0x2000};
|
||||
regs.set_pc(0x1101);
|
||||
ASSERT_EQ(0x101U, regs.GetRelPc(elf_.get(), &map_info));
|
||||
elf_interface_->set_load_bias(0x3000);
|
||||
ASSERT_EQ(0x3101U, regs.GetRelPc(elf_.get(), &map_info));
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, regs32_rel_pc) {
|
||||
regs_rel_pc<uint32_t>();
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, regs64_rel_pc) {
|
||||
regs_rel_pc<uint64_t>();
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
void RegsTest::regs_return_address_register() {
|
||||
RegsTestImpl<AddressType> regs(20, 10, Regs::Location(Regs::LOCATION_REGISTER, 5));
|
||||
|
@ -250,19 +229,19 @@ TEST_F(RegsTest, elf_invalid) {
|
|||
MapInfo map_info{.start = 0x1000, .end = 0x2000};
|
||||
|
||||
regs_arm.set_pc(0x1500);
|
||||
ASSERT_EQ(0x500U, regs_arm.GetRelPc(&invalid_elf, &map_info));
|
||||
ASSERT_EQ(0x500U, invalid_elf.GetRelPc(regs_arm.pc(), &map_info));
|
||||
ASSERT_EQ(0x500U, regs_arm.GetAdjustedPc(0x500U, &invalid_elf));
|
||||
|
||||
regs_arm64.set_pc(0x1600);
|
||||
ASSERT_EQ(0x600U, regs_arm64.GetRelPc(&invalid_elf, &map_info));
|
||||
ASSERT_EQ(0x600U, invalid_elf.GetRelPc(regs_arm64.pc(), &map_info));
|
||||
ASSERT_EQ(0x600U, regs_arm64.GetAdjustedPc(0x600U, &invalid_elf));
|
||||
|
||||
regs_x86.set_pc(0x1700);
|
||||
ASSERT_EQ(0x700U, regs_x86.GetRelPc(&invalid_elf, &map_info));
|
||||
ASSERT_EQ(0x700U, invalid_elf.GetRelPc(regs_x86.pc(), &map_info));
|
||||
ASSERT_EQ(0x700U, regs_x86.GetAdjustedPc(0x700U, &invalid_elf));
|
||||
|
||||
regs_x86_64.set_pc(0x1800);
|
||||
ASSERT_EQ(0x800U, regs_x86_64.GetRelPc(&invalid_elf, &map_info));
|
||||
ASSERT_EQ(0x800U, invalid_elf.GetRelPc(regs_x86_64.pc(), &map_info));
|
||||
ASSERT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, &invalid_elf));
|
||||
}
|
||||
|
||||
|
@ -305,3 +284,5 @@ TEST_F(RegsTest, x86_64_set_from_raw) {
|
|||
EXPECT_EQ(0x1200000000U, x86_64.sp());
|
||||
EXPECT_EQ(0x4900000000U, x86_64.pc());
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -32,10 +32,13 @@
|
|||
#include <android-base/test_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "MemoryFake.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class SymbolsTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -333,3 +336,5 @@ REGISTER_TYPED_TEST_CASE_P(SymbolsTest, function_bounds_check, no_symbol, multip
|
|||
|
||||
typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, SymbolsTest, SymbolsTestTypes);
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -31,12 +31,14 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "MapInfo.h"
|
||||
#include "Maps.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
#include "RegsGetLocal.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
#include <unwindstack/RegsGetLocal.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
static std::atomic_bool g_ready(false);
|
||||
static volatile bool g_ready_for_remote = false;
|
||||
|
@ -71,7 +73,7 @@ static void VerifyUnwind(pid_t pid, Memory* memory, Maps* maps, Regs* regs) {
|
|||
ASSERT_TRUE(map_info != nullptr) << ErrorMsg(function_names, function_name_index, unwind_stream);
|
||||
|
||||
Elf* elf = map_info->GetElf(pid, true);
|
||||
uint64_t rel_pc = regs->GetRelPc(elf, map_info);
|
||||
uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info);
|
||||
uint64_t adjusted_rel_pc = rel_pc;
|
||||
if (frame_num != 0) {
|
||||
adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
|
||||
|
@ -210,7 +212,7 @@ TEST(UnwindTest, from_context) {
|
|||
|
||||
// Wait for context data.
|
||||
void* ucontext;
|
||||
for (size_t i = 0; i < 200; i++) {
|
||||
for (size_t i = 0; i < 2000; i++) {
|
||||
ucontext = reinterpret_cast<void*>(g_ucontext.load());
|
||||
if (ucontext != nullptr) {
|
||||
break;
|
||||
|
@ -231,3 +233,5 @@ TEST(UnwindTest, from_context) {
|
|||
g_finish = true;
|
||||
thread.join();
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
|
@ -27,10 +28,11 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "Maps.h"
|
||||
#include "Memory.h"
|
||||
#include "Regs.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
||||
static bool Attach(pid_t pid) {
|
||||
if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
|
||||
|
@ -54,14 +56,14 @@ static bool Detach(pid_t pid) {
|
|||
}
|
||||
|
||||
void DoUnwind(pid_t pid) {
|
||||
RemoteMaps remote_maps(pid);
|
||||
unwindstack::RemoteMaps remote_maps(pid);
|
||||
if (!remote_maps.Parse()) {
|
||||
printf("Failed to parse map data.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t machine_type;
|
||||
Regs* regs = Regs::RemoteGet(pid, &machine_type);
|
||||
unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid, &machine_type);
|
||||
if (regs == nullptr) {
|
||||
printf("Unable to get remote reg data\n");
|
||||
return;
|
||||
|
@ -90,20 +92,20 @@ void DoUnwind(pid_t pid) {
|
|||
}
|
||||
printf("\n");
|
||||
|
||||
MemoryRemote remote_memory(pid);
|
||||
unwindstack::MemoryRemote remote_memory(pid);
|
||||
for (size_t frame_num = 0; frame_num < 64; frame_num++) {
|
||||
if (regs->pc() == 0) {
|
||||
break;
|
||||
}
|
||||
MapInfo* map_info = remote_maps.Find(regs->pc());
|
||||
unwindstack::MapInfo* map_info = remote_maps.Find(regs->pc());
|
||||
if (map_info == nullptr) {
|
||||
printf("Failed to find map data for the pc\n");
|
||||
break;
|
||||
}
|
||||
|
||||
Elf* elf = map_info->GetElf(pid, true);
|
||||
unwindstack::Elf* elf = map_info->GetElf(pid, true);
|
||||
|
||||
uint64_t rel_pc = regs->GetRelPc(elf, map_info);
|
||||
uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info);
|
||||
uint64_t adjusted_rel_pc = rel_pc;
|
||||
// Don't need to adjust the first frame pc.
|
||||
if (frame_num != 0) {
|
||||
|
|
|
@ -25,13 +25,16 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/ElfInterface.h>
|
||||
#include <unwindstack/Log.h>
|
||||
|
||||
#include "ArmExidx.h"
|
||||
#include "DwarfSection.h"
|
||||
#include "DwarfStructs.h"
|
||||
#include "Elf.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "ElfInterfaceArm.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
void DumpArm(ElfInterfaceArm* interface) {
|
||||
if (interface == nullptr) {
|
||||
|
@ -100,27 +103,12 @@ void DumpDwarfSection(ElfInterface* interface, DwarfSection* section, uint64_t l
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
printf("Need to pass the name of an elf file to the program.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(argv[1], &st) == -1) {
|
||||
printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
printf("%s is not a regular file.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetElfInfo(const char* file) {
|
||||
// Send all log messages to stdout.
|
||||
log_to_stdout(true);
|
||||
|
||||
MemoryFileAtOffset* memory = new MemoryFileAtOffset;
|
||||
if (!memory->Init(argv[1], 0)) {
|
||||
if (!memory->Init(file, 0)) {
|
||||
// Initializatation failed.
|
||||
printf("Failed to init\n");
|
||||
return 1;
|
||||
|
@ -128,7 +116,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
Elf elf(memory);
|
||||
if (!elf.Init() || !elf.valid()) {
|
||||
printf("%s is not a valid elf file.\n", argv[1]);
|
||||
printf("%s is not a valid elf file.\n", file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -173,3 +161,24 @@ int main(int argc, char** argv) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
printf("Need to pass the name of an elf file to the program.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(argv[1], &st) == -1) {
|
||||
printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
printf("%s is not a regular file.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return unwindstack::GetElfInfo(argv[1]);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
@ -22,9 +23,9 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Elf.h"
|
||||
#include "ElfInterface.h"
|
||||
#include "Log.h"
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/Log.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
|
@ -43,15 +44,15 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
// Send all log messages to stdout.
|
||||
log_to_stdout(true);
|
||||
unwindstack::log_to_stdout(true);
|
||||
|
||||
MemoryFileAtOffset* memory = new MemoryFileAtOffset;
|
||||
unwindstack::MemoryFileAtOffset* memory = new unwindstack::MemoryFileAtOffset;
|
||||
if (!memory->Init(argv[1], 0)) {
|
||||
printf("Failed to init\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Elf elf(memory);
|
||||
unwindstack::Elf elf(memory);
|
||||
if (!elf.Init() || !elf.valid()) {
|
||||
printf("%s is not a valid elf file.\n", argv[1]);
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue