Home | History | Annotate | Download | only in libunwindstack
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <fcntl.h>
     19 #include <sys/mman.h>
     20 #include <sys/ptrace.h>
     21 #include <sys/stat.h>
     22 #include <sys/types.h>
     23 #include <sys/uio.h>
     24 #include <unistd.h>
     25 
     26 #include <algorithm>
     27 #include <memory>
     28 
     29 #include <android-base/unique_fd.h>
     30 
     31 #include <unwindstack/Memory.h>
     32 
     33 #include "Check.h"
     34 
     35 namespace unwindstack {
     36 
     37 static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) {
     38 
     39   // Split up the remote read across page boundaries.
     40   // From the manpage:
     41   //   A partial read/write may result if one of the remote_iov elements points to an invalid
     42   //   memory region in the remote process.
     43   //
     44   //   Partial transfers apply at the granularity of iovec elements.  These system calls won't
     45   //   perform a partial transfer that splits a single iovec element.
     46   constexpr size_t kMaxIovecs = 64;
     47   struct iovec src_iovs[kMaxIovecs];
     48 
     49   uint64_t cur = remote_src;
     50   size_t total_read = 0;
     51   while (len > 0) {
     52     struct iovec dst_iov = {
     53         .iov_base = &reinterpret_cast<uint8_t*>(dst)[total_read], .iov_len = len,
     54     };
     55 
     56     size_t iovecs_used = 0;
     57     while (len > 0) {
     58       if (iovecs_used == kMaxIovecs) {
     59         break;
     60       }
     61 
     62       // struct iovec uses void* for iov_base.
     63       if (cur >= UINTPTR_MAX) {
     64         errno = EFAULT;
     65         return total_read;
     66       }
     67 
     68       src_iovs[iovecs_used].iov_base = reinterpret_cast<void*>(cur);
     69 
     70       uintptr_t misalignment = cur & (getpagesize() - 1);
     71       size_t iov_len = getpagesize() - misalignment;
     72       iov_len = std::min(iov_len, len);
     73 
     74       len -= iov_len;
     75       if (__builtin_add_overflow(cur, iov_len, &cur)) {
     76         errno = EFAULT;
     77         return total_read;
     78       }
     79 
     80       src_iovs[iovecs_used].iov_len = iov_len;
     81       ++iovecs_used;
     82     }
     83 
     84     ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0);
     85     if (rc == -1) {
     86       return total_read;
     87     }
     88     total_read += rc;
     89   }
     90   return total_read;
     91 }
     92 
     93 static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) {
     94   // ptrace() returns -1 and sets errno when the operation fails.
     95   // To disambiguate -1 from a valid result, we clear errno beforehand.
     96   errno = 0;
     97   *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast<void*>(addr), nullptr);
     98   if (*value == -1 && errno) {
     99     return false;
    100   }
    101   return true;
    102 }
    103 
    104 static size_t PtraceRead(pid_t pid, uint64_t addr, void* dst, size_t bytes) {
    105   // Make sure that there is no overflow.
    106   uint64_t max_size;
    107   if (__builtin_add_overflow(addr, bytes, &max_size)) {
    108     return 0;
    109   }
    110 
    111   size_t bytes_read = 0;
    112   long data;
    113   size_t align_bytes = addr & (sizeof(long) - 1);
    114   if (align_bytes != 0) {
    115     if (!PtraceReadLong(pid, addr & ~(sizeof(long) - 1), &data)) {
    116       return 0;
    117     }
    118     size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes);
    119     memcpy(dst, reinterpret_cast<uint8_t*>(&data) + align_bytes, copy_bytes);
    120     addr += copy_bytes;
    121     dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + copy_bytes);
    122     bytes -= copy_bytes;
    123     bytes_read += copy_bytes;
    124   }
    125 
    126   for (size_t i = 0; i < bytes / sizeof(long); i++) {
    127     if (!PtraceReadLong(pid, addr, &data)) {
    128       return bytes_read;
    129     }
    130     memcpy(dst, &data, sizeof(long));
    131     dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
    132     addr += sizeof(long);
    133     bytes_read += sizeof(long);
    134   }
    135 
    136   size_t left_over = bytes & (sizeof(long) - 1);
    137   if (left_over) {
    138     if (!PtraceReadLong(pid, addr, &data)) {
    139       return bytes_read;
    140     }
    141     memcpy(dst, &data, left_over);
    142     bytes_read += left_over;
    143   }
    144   return bytes_read;
    145 }
    146 
    147 bool Memory::ReadFully(uint64_t addr, void* dst, size_t size) {
    148   size_t rc = Read(addr, dst, size);
    149   return rc == size;
    150 }
    151 
    152 bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
    153   string->clear();
    154   uint64_t bytes_read = 0;
    155   while (bytes_read < max_read) {
    156     uint8_t value;
    157     if (!ReadFully(addr, &value, sizeof(value))) {
    158       return false;
    159     }
    160     if (value == '\0') {
    161       return true;
    162     }
    163     string->push_back(value);
    164     addr++;
    165     bytes_read++;
    166   }
    167   return false;
    168 }
    169 
    170 std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) {
    171   if (pid == getpid()) {
    172     return std::shared_ptr<Memory>(new MemoryLocal());
    173   }
    174   return std::shared_ptr<Memory>(new MemoryRemote(pid));
    175 }
    176 
    177 size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
    178   if (addr >= raw_.size()) {
    179     return 0;
    180   }
    181 
    182   size_t bytes_left = raw_.size() - static_cast<size_t>(addr);
    183   const unsigned char* actual_base = static_cast<const unsigned char*>(raw_.data()) + addr;
    184   size_t actual_len = std::min(bytes_left, size);
    185 
    186   memcpy(dst, actual_base, actual_len);
    187   return actual_len;
    188 }
    189 
    190 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
    191   if (offset < raw_.size()) {
    192     return &raw_[offset];
    193   }
    194   return nullptr;
    195 }
    196 
    197 MemoryFileAtOffset::~MemoryFileAtOffset() {
    198   Clear();
    199 }
    200 
    201 void MemoryFileAtOffset::Clear() {
    202   if (data_) {
    203     munmap(&data_[-offset_], size_ + offset_);
    204     data_ = nullptr;
    205   }
    206 }
    207 
    208 bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) {
    209   // Clear out any previous data if it exists.
    210   Clear();
    211 
    212   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
    213   if (fd == -1) {
    214     return false;
    215   }
    216   struct stat buf;
    217   if (fstat(fd, &buf) == -1) {
    218     return false;
    219   }
    220   if (offset >= static_cast<uint64_t>(buf.st_size)) {
    221     return false;
    222   }
    223 
    224   offset_ = offset & (getpagesize() - 1);
    225   uint64_t aligned_offset = offset & ~(getpagesize() - 1);
    226   if (aligned_offset > static_cast<uint64_t>(buf.st_size) ||
    227       offset > static_cast<uint64_t>(buf.st_size)) {
    228     return false;
    229   }
    230 
    231   size_ = buf.st_size - aligned_offset;
    232   uint64_t max_size;
    233   if (!__builtin_add_overflow(size, offset_, &max_size) && max_size < size_) {
    234     // Truncate the mapped size.
    235     size_ = max_size;
    236   }
    237   void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset);
    238   if (map == MAP_FAILED) {
    239     return false;
    240   }
    241 
    242   data_ = &reinterpret_cast<uint8_t*>(map)[offset_];
    243   size_ -= offset_;
    244 
    245   return true;
    246 }
    247 
    248 size_t MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
    249   if (addr >= size_) {
    250     return 0;
    251   }
    252 
    253   size_t bytes_left = size_ - static_cast<size_t>(addr);
    254   const unsigned char* actual_base = static_cast<const unsigned char*>(data_) + addr;
    255   size_t actual_len = std::min(bytes_left, size);
    256 
    257   memcpy(dst, actual_base, actual_len);
    258   return actual_len;
    259 }
    260 
    261 size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) {
    262 #if !defined(__LP64__)
    263   // Cannot read an address greater than 32 bits in a 32 bit context.
    264   if (addr > UINT32_MAX) {
    265     return 0;
    266   }
    267 #endif
    268 
    269   size_t (*read_func)(pid_t, uint64_t, void*, size_t) =
    270       reinterpret_cast<size_t (*)(pid_t, uint64_t, void*, size_t)>(read_redirect_func_.load());
    271   if (read_func != nullptr) {
    272     return read_func(pid_, addr, dst, size);
    273   } else {
    274     // Prefer process_vm_read, try it first. If it doesn't work, use the
    275     // ptrace function. If at least one of them returns at least some data,
    276     // set that as the permanent function to use.
    277     // This assumes that if process_vm_read works once, it will continue
    278     // to work.
    279     size_t bytes = ProcessVmRead(pid_, addr, dst, size);
    280     if (bytes > 0) {
    281       read_redirect_func_ = reinterpret_cast<uintptr_t>(ProcessVmRead);
    282       return bytes;
    283     }
    284     bytes = PtraceRead(pid_, addr, dst, size);
    285     if (bytes > 0) {
    286       read_redirect_func_ = reinterpret_cast<uintptr_t>(PtraceRead);
    287     }
    288     return bytes;
    289   }
    290 }
    291 
    292 size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
    293   return ProcessVmRead(getpid(), addr, dst, size);
    294 }
    295 
    296 MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
    297                          uint64_t offset)
    298     : memory_(memory), begin_(begin), length_(length), offset_(offset) {}
    299 
    300 size_t MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
    301   if (addr < offset_) {
    302     return 0;
    303   }
    304 
    305   uint64_t read_offset = addr - offset_;
    306   if (read_offset >= length_) {
    307     return 0;
    308   }
    309 
    310   uint64_t read_length = std::min(static_cast<uint64_t>(size), length_ - read_offset);
    311   uint64_t read_addr;
    312   if (__builtin_add_overflow(read_offset, begin_, &read_addr)) {
    313     return 0;
    314   }
    315 
    316   return memory_->Read(read_addr, dst, read_length);
    317 }
    318 
    319 bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
    320   auto memory_file = std::make_shared<MemoryFileAtOffset>();
    321   if (!memory_file->Init(file, offset)) {
    322     return false;
    323   }
    324 
    325   // The first uint64_t value is the start of memory.
    326   uint64_t start;
    327   if (!memory_file->ReadFully(0, &start, sizeof(start))) {
    328     return false;
    329   }
    330 
    331   uint64_t size = memory_file->Size();
    332   if (__builtin_sub_overflow(size, sizeof(start), &size)) {
    333     return false;
    334   }
    335 
    336   memory_ = std::make_unique<MemoryRange>(memory_file, sizeof(start), size, start);
    337   return true;
    338 }
    339 
    340 size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
    341   if (!memory_) {
    342     return 0;
    343   }
    344 
    345   return memory_->Read(addr, dst, size);
    346 }
    347 
    348 MemoryOfflineBuffer::MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end)
    349     : data_(data), start_(start), end_(end) {}
    350 
    351 void MemoryOfflineBuffer::Reset(const uint8_t* data, uint64_t start, uint64_t end) {
    352   data_ = data;
    353   start_ = start;
    354   end_ = end;
    355 }
    356 
    357 size_t MemoryOfflineBuffer::Read(uint64_t addr, void* dst, size_t size) {
    358   if (addr < start_ || addr >= end_) {
    359     return 0;
    360   }
    361 
    362   size_t read_length = std::min(size, static_cast<size_t>(end_ - addr));
    363   memcpy(dst, &data_[addr - start_], read_length);
    364   return read_length;
    365 }
    366 
    367 MemoryOfflineParts::~MemoryOfflineParts() {
    368   for (auto memory : memories_) {
    369     delete memory;
    370   }
    371 }
    372 
    373 size_t MemoryOfflineParts::Read(uint64_t addr, void* dst, size_t size) {
    374   if (memories_.empty()) {
    375     return 0;
    376   }
    377 
    378   // Do a read on each memory object, no support for reading across the
    379   // different memory objects.
    380   for (MemoryOffline* memory : memories_) {
    381     size_t bytes = memory->Read(addr, dst, size);
    382     if (bytes != 0) {
    383       return bytes;
    384     }
    385   }
    386   return 0;
    387 }
    388 
    389 }  // namespace unwindstack
    390