• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ProcessVmRead(pid_t pid,uint64_t remote_src,void * dst,size_t len)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 
PtraceReadLong(pid_t pid,uint64_t addr,long * value)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 
PtraceRead(pid_t pid,uint64_t addr,void * dst,size_t bytes)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 
ReadFully(uint64_t addr,void * dst,size_t size)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 
ReadString(uint64_t addr,std::string * string,uint64_t max_read)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 
CreateProcessMemory(pid_t pid)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 
Read(uint64_t addr,void * dst,size_t size)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 
GetPtr(size_t offset)190 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
191   if (offset < raw_.size()) {
192     return &raw_[offset];
193   }
194   return nullptr;
195 }
196 
~MemoryFileAtOffset()197 MemoryFileAtOffset::~MemoryFileAtOffset() {
198   Clear();
199 }
200 
Clear()201 void MemoryFileAtOffset::Clear() {
202   if (data_) {
203     munmap(&data_[-offset_], size_ + offset_);
204     data_ = nullptr;
205   }
206 }
207 
Init(const std::string & file,uint64_t offset,uint64_t size)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 
Read(uint64_t addr,void * dst,size_t size)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 
Read(uint64_t addr,void * dst,size_t size)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 
Read(uint64_t addr,void * dst,size_t size)292 size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
293   return ProcessVmRead(getpid(), addr, dst, size);
294 }
295 
MemoryRange(const std::shared_ptr<Memory> & memory,uint64_t begin,uint64_t length,uint64_t offset)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 
Read(uint64_t addr,void * dst,size_t size)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 
Init(const std::string & file,uint64_t offset)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 
Read(uint64_t addr,void * dst,size_t size)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 
MemoryOfflineBuffer(const uint8_t * data,uint64_t start,uint64_t end)348 MemoryOfflineBuffer::MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end)
349     : data_(data), start_(start), end_(end) {}
350 
Reset(const uint8_t * data,uint64_t start,uint64_t end)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 
Read(uint64_t addr,void * dst,size_t size)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 
~MemoryOfflineParts()367 MemoryOfflineParts::~MemoryOfflineParts() {
368   for (auto memory : memories_) {
369     delete memory;
370   }
371 }
372 
Read(uint64_t addr,void * dst,size_t size)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