diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp index 148c41810..fd8b7134f 100644 --- a/libbacktrace/BacktracePtrace.cpp +++ b/libbacktrace/BacktracePtrace.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -73,20 +72,42 @@ size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { return 0; } + bytes = MIN(map.end - addr, bytes); - - struct iovec local_io; - local_io.iov_base = buffer; - local_io.iov_len = bytes; - - struct iovec remote_io; - remote_io.iov_base = reinterpret_cast(addr); - remote_io.iov_len = bytes; - - ssize_t bytes_read = process_vm_readv(Tid(), &local_io, 1, &remote_io, 1, 0); - if (bytes_read == -1) { - return 0; + size_t bytes_read = 0; + word_t data_word; + size_t align_bytes = addr & (sizeof(word_t) - 1); + if (align_bytes != 0) { + if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) { + return 0; + } + size_t copy_bytes = MIN(sizeof(word_t) - align_bytes, bytes); + memcpy(buffer, reinterpret_cast(&data_word) + align_bytes, copy_bytes); + addr += copy_bytes; + buffer += copy_bytes; + bytes -= copy_bytes; + bytes_read += copy_bytes; } - return static_cast(bytes_read); + + size_t num_words = bytes / sizeof(word_t); + for (size_t i = 0; i < num_words; i++) { + if (!PtraceRead(Tid(), addr, &data_word)) { + return bytes_read; + } + memcpy(buffer, &data_word, sizeof(word_t)); + buffer += sizeof(word_t); + addr += sizeof(word_t); + bytes_read += sizeof(word_t); + } + + size_t left_over = bytes & (sizeof(word_t) - 1); + if (left_over) { + if (!PtraceRead(Tid(), addr, &data_word)) { + return bytes_read; + } + memcpy(buffer, &data_word, left_over); + bytes_read += left_over; + } + return bytes_read; #endif }