| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * | 
 | 3 |  * Copyright 2014, The Android Open Source Project | 
 | 4 |  * | 
 | 5 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 |  * you may not use this file except in compliance with the License. | 
 | 7 |  * You may obtain a copy of the License at | 
 | 8 |  * | 
 | 9 |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 |  * | 
 | 11 |  * Unless required by applicable law or agreed to in writing, software | 
 | 12 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 |  * See the License for the specific language governing permissions and | 
 | 15 |  * limitations under the License. | 
 | 16 |  */ | 
 | 17 |  | 
 | 18 | #include <stddef.h> | 
 | 19 | #include <stdlib.h> | 
 | 20 | #include <string.h> | 
 | 21 | #include <ctype.h> | 
 | 22 | #include <stdio.h> | 
 | 23 | #include <errno.h> | 
 | 24 | #include <sys/types.h> | 
 | 25 | #include <sys/ptrace.h> | 
 | 26 | #include <sys/user.h> | 
 | 27 | #include <sys/uio.h> | 
 | 28 | #include <linux/elf.h> | 
 | 29 |  | 
 | 30 | #include "../utility.h" | 
 | 31 | #include "../machine.h" | 
 | 32 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 33 | void dump_memory_and_code(log_t* log, pid_t tid) { | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 34 |     struct user_pt_regs regs; | 
 | 35 |     struct iovec io; | 
 | 36 |     io.iov_base = ®s; | 
 | 37 |     io.iov_len = sizeof(regs); | 
 | 38 |  | 
 | 39 |     if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &io) == -1) { | 
| Brigid Smith | e17f267 | 2014-06-19 11:33:38 -0700 | [diff] [blame] | 40 |         _LOG(log, logtype::ERROR, "%s: ptrace failed to get registers: %s\n", | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 41 |              __func__, strerror(errno)); | 
 | 42 |         return; | 
 | 43 |     } | 
 | 44 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 45 |     for (int reg = 0; reg < 31; reg++) { | 
 | 46 |         uintptr_t addr = regs.regs[reg]; | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 47 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 48 |         /* | 
 | 49 |          * Don't bother if it looks like a small int or ~= null, or if | 
 | 50 |          * it's in the kernel area. | 
 | 51 |          */ | 
 | 52 |         if (addr < 4096 || addr >= (1UL<<63)) { | 
 | 53 |             continue; | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 54 |         } | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 55 |  | 
 | 56 |         _LOG(log, logtype::MEMORY, "\nmemory near x%d:\n", reg); | 
 | 57 |         dump_memory(log, tid, addr); | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 58 |     } | 
 | 59 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 60 |     _LOG(log, logtype::MEMORY, "\ncode around pc:\n"); | 
 | 61 |     dump_memory(log, tid, (uintptr_t)regs.pc); | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 62 |  | 
 | 63 |     if (regs.pc != regs.sp) { | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 64 |         _LOG(log, logtype::MEMORY, "\ncode around sp:\n"); | 
 | 65 |         dump_memory(log, tid, (uintptr_t)regs.sp); | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 66 |     } | 
 | 67 | } | 
 | 68 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 69 | void dump_registers(log_t* log, pid_t tid) { | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 70 |   struct user_pt_regs r; | 
 | 71 |   struct iovec io; | 
 | 72 |   io.iov_base = &r; | 
 | 73 |   io.iov_len = sizeof(r); | 
 | 74 |  | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 75 |   if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRSTATUS, (void*) &io) == -1) { | 
| Brigid Smith | e17f267 | 2014-06-19 11:33:38 -0700 | [diff] [blame] | 76 |     _LOG(log, logtype::ERROR, "ptrace error: %s\n", strerror(errno)); | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 77 |     return; | 
 | 78 |   } | 
 | 79 |  | 
 | 80 |   for (int i = 0; i < 28; i += 4) { | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 81 |     _LOG(log, logtype::REGISTERS, | 
 | 82 |          "    x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx\n", | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 83 |          i, (uint64_t)r.regs[i], | 
 | 84 |          i+1, (uint64_t)r.regs[i+1], | 
 | 85 |          i+2, (uint64_t)r.regs[i+2], | 
 | 86 |          i+3, (uint64_t)r.regs[i+3]); | 
 | 87 |   } | 
 | 88 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 89 |   _LOG(log, logtype::REGISTERS, "    x28  %016lx  x29  %016lx  x30  %016lx\n", | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 90 |        (uint64_t)r.regs[28], (uint64_t)r.regs[29], (uint64_t)r.regs[30]); | 
 | 91 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 92 |   _LOG(log, logtype::REGISTERS, "    sp   %016lx  pc   %016lx\n", | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 93 |        (uint64_t)r.sp, (uint64_t)r.pc); | 
 | 94 |  | 
 | 95 |  | 
 | 96 |   struct user_fpsimd_state f; | 
 | 97 |   io.iov_base = &f; | 
 | 98 |   io.iov_len = sizeof(f); | 
 | 99 |  | 
 | 100 |   if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRFPREG, (void*) &io) == -1) { | 
| Brigid Smith | e17f267 | 2014-06-19 11:33:38 -0700 | [diff] [blame] | 101 |     _LOG(log, logtype::ERROR, "ptrace error: %s\n", strerror(errno)); | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 102 |     return; | 
 | 103 |   } | 
 | 104 |  | 
 | 105 |   for (int i = 0; i < 32; i += 4) { | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 106 |     _LOG(log, logtype::REGISTERS, "    v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx\n", | 
| Kévin PETIT | abc60c2 | 2013-12-19 12:36:59 +0000 | [diff] [blame] | 107 |          i, (uint64_t)f.vregs[i], | 
 | 108 |          i+1, (uint64_t)f.vregs[i+1], | 
 | 109 |          i+2, (uint64_t)f.vregs[i+2], | 
 | 110 |          i+3, (uint64_t)f.vregs[i+3]); | 
 | 111 |   } | 
 | 112 | } |