1 /* 2 * Copyright 2008, 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 #define LOG_TAG "DEBUG" 18 19 #include "utility.h" 20 21 #include <errno.h> 22 #include <signal.h> 23 #include <string.h> 24 #include <unistd.h> 25 #include <sys/ptrace.h> 26 #include <sys/wait.h> 27 28 #include <backtrace/Backtrace.h> 29 #include <log/log.h> 30 31 const int SLEEP_TIME_USEC = 50000; // 0.05 seconds 32 const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds 33 34 static int write_to_am(int fd, const char* buf, int len) { 35 int to_write = len; 36 while (to_write > 0) { 37 int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write)); 38 if (written < 0) { 39 // hard failure 40 ALOGE("AM write failure (%d / %s)\n", errno, strerror(errno)); 41 return -1; 42 } 43 to_write -= written; 44 } 45 return len; 46 } 47 48 // Whitelist output desired in the logcat output. 49 bool is_allowed_in_logcat(enum logtype ltype) { 50 if ((ltype == ERROR) 51 || (ltype == HEADER) 52 || (ltype == REGISTERS) 53 || (ltype == BACKTRACE)) { 54 return true; 55 } 56 return false; 57 } 58 59 void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) { 60 bool write_to_tombstone = (log->tfd != -1); 61 bool write_to_logcat = is_allowed_in_logcat(ltype) 62 && log->crashed_tid != -1 63 && log->current_tid != -1 64 && (log->crashed_tid == log->current_tid); 65 bool write_to_activitymanager = (log->amfd != -1); 66 67 char buf[512]; 68 va_list ap; 69 va_start(ap, fmt); 70 vsnprintf(buf, sizeof(buf), fmt, ap); 71 va_end(ap); 72 73 size_t len = strlen(buf); 74 if (len <= 0) { 75 return; 76 } 77 78 if (write_to_tombstone) { 79 TEMP_FAILURE_RETRY(write(log->tfd, buf, len)); 80 } 81 82 if (write_to_logcat) { 83 __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, LOG_TAG, buf); 84 if (write_to_activitymanager) { 85 int written = write_to_am(log->amfd, buf, len); 86 if (written <= 0) { 87 // timeout or other failure on write; stop informing the activity manager 88 log->amfd = -1; 89 } 90 } 91 } 92 } 93 94 int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed) { 95 bool allow_dead_tid = false; 96 for (;;) { 97 int status; 98 pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG)); 99 if (n == -1) { 100 ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); 101 break; 102 } else if (n == tid) { 103 if (WIFSTOPPED(status)) { 104 return WSTOPSIG(status); 105 } else { 106 ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); 107 // This is the only circumstance under which we can allow a detach 108 // to fail with ESRCH, which indicates the tid has exited. 109 allow_dead_tid = true; 110 break; 111 } 112 } 113 114 if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) { 115 ALOGE("timed out waiting for stop signal: tid=%d", tid); 116 break; 117 } 118 119 usleep(SLEEP_TIME_USEC); 120 *total_sleep_time_usec += SLEEP_TIME_USEC; 121 } 122 123 if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { 124 if (allow_dead_tid && errno == ESRCH) { 125 ALOGE("tid exited before attach completed: tid %d", tid); 126 } else { 127 *detach_failed = true; 128 ALOGE("detach failed: tid %d, %s", tid, strerror(errno)); 129 } 130 } 131 return -1; 132 } 133 134 #if defined (__mips__) 135 #define DUMP_MEMORY_AS_ASCII 1 136 #else 137 #define DUMP_MEMORY_AS_ASCII 0 138 #endif 139 140 void dump_memory(log_t* log, pid_t tid, uintptr_t addr) { 141 char code_buffer[64]; 142 char ascii_buffer[32]; 143 uintptr_t p, end; 144 145 p = addr & ~(sizeof(long) - 1); 146 /* Dump 32 bytes before addr */ 147 p -= 32; 148 if (p > addr) { 149 /* catch underflow */ 150 p = 0; 151 } 152 /* Dump 256 bytes */ 153 end = p + 256; 154 /* catch overflow; 'end - p' has to be multiples of 16 */ 155 while (end < p) { 156 end -= 16; 157 } 158 159 /* Dump the code around PC as: 160 * addr contents ascii 161 * 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q 162 * 0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000 ......-..p...... 163 * On 32-bit machines, there are still 16 bytes per line but addresses and 164 * words are of course presented differently. 165 */ 166 while (p < end) { 167 char* asc_out = ascii_buffer; 168 169 int len = snprintf(code_buffer, sizeof(code_buffer), "%" PRIPTR " ", p); 170 171 for (size_t i = 0; i < 16/sizeof(long); i++) { 172 long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL); 173 if (data == -1 && errno != 0) { 174 // ptrace failed, probably because we're dumping memory in an 175 // unmapped or inaccessible page. 176 #ifdef __LP64__ 177 len += sprintf(code_buffer + len, "---------------- "); 178 #else 179 len += sprintf(code_buffer + len, "-------- "); 180 #endif 181 } else { 182 len += sprintf(code_buffer + len, "%" PRIPTR " ", 183 static_cast<uintptr_t>(data)); 184 } 185 186 #if DUMP_MEMORY_AS_ASCII 187 for (size_t j = 0; j < sizeof(long); j++) { 188 /* 189 * Our isprint() allows high-ASCII characters that display 190 * differently (often badly) in different viewers, so we 191 * just use a simpler test. 192 */ 193 char val = (data >> (j*8)) & 0xff; 194 if (val >= 0x20 && val < 0x7f) { 195 *asc_out++ = val; 196 } else { 197 *asc_out++ = '.'; 198 } 199 } 200 #endif 201 p += sizeof(long); 202 } 203 *asc_out = '\0'; 204 _LOG(log, logtype::MEMORY, " %s %s\n", code_buffer, ascii_buffer); 205 } 206 } 207