diff options
author | Christopher Ferris <cferris@google.com> | 2017-03-17 17:01:45 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-03-17 17:01:46 +0000 |
commit | cc404b51fc424cbb786abce8b8f36b1dce1c0ab9 (patch) | |
tree | 62ebb9ce531a818efa51e551179dccad32ea949e /libunwindstack/Memory.cpp | |
parent | 0add3ca7c47b287bc01b5e738cb9b682d43f6f97 (diff) | |
parent | 3958f8060ac0adccd977c0fab7a53d45f3fce58d (diff) |
Merge "Elf interface for new unwinder."
Diffstat (limited to 'libunwindstack/Memory.cpp')
-rw-r--r-- | libunwindstack/Memory.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
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; |