diff options
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; |