From 3958f8060ac0adccd977c0fab7a53d45f3fce58d Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 1 Feb 2017 15:44:40 -0800 Subject: Elf interface for new unwinder. This cl includes the code to read arm unwind information from a shared library. Bug: 23762183 Test: Passes all unit tests. I can dump the arm unwind information Test: for an arm shared library. Change-Id: I43501ea2eab843b81de8bd5128401dd1971af8d3 --- libunwindstack/Memory.cpp | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'libunwindstack/Memory.cpp') diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp index 336e4fe32..1fcf84280 100644 --- a/libunwindstack/Memory.cpp +++ b/libunwindstack/Memory.cpp @@ -48,14 +48,40 @@ bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) { return false; } +bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) { + uint64_t last_read_byte; + if (__builtin_add_overflow(size, addr, &last_read_byte)) { + return false; + } + if (last_read_byte > raw_.size()) { + return false; + } + memcpy(dst, &raw_[addr], size); + return true; +} + +uint8_t* MemoryBuffer::GetPtr(size_t offset) { + if (offset < raw_.size()) { + return &raw_[offset]; + } + return nullptr; +} + MemoryFileAtOffset::~MemoryFileAtOffset() { + Clear(); +} + +void MemoryFileAtOffset::Clear() { if (data_) { munmap(&data_[-offset_], size_ + offset_); data_ = nullptr; } } -bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset) { +bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) { + // Clear out any previous data if it exists. + Clear(); + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC))); if (fd == -1) { return false; @@ -71,6 +97,10 @@ bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset) { offset_ = offset & (getpagesize() - 1); uint64_t aligned_offset = offset & ~(getpagesize() - 1); size_ = buf.st_size - aligned_offset; + if (size < (UINT64_MAX - offset_) && size + offset_ < size_) { + // Truncate the mapped size. + size_ = size + offset_; + } void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset); if (map == MAP_FAILED) { return false; @@ -91,6 +121,12 @@ bool MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) { } static bool PtraceRead(pid_t pid, uint64_t addr, long* value) { +#if !defined(__LP64__) + // Cannot read an address greater than 32 bits. + if (addr > UINT32_MAX) { + return false; + } +#endif // ptrace() returns -1 and sets errno when the operation fails. // To disambiguate -1 from a valid result, we clear errno beforehand. errno = 0; -- cgit v1.2.3