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 <sys/ptrace.h> 25#include <sys/wait.h> 26#include <unistd.h> 27 28#include <string> 29 30#include <android-base/stringprintf.h> 31#include <android-base/unique_fd.h> 32#include <backtrace/Backtrace.h> 33#include <log/log.h> 34 35// Whitelist output desired in the logcat output. 36bool is_allowed_in_logcat(enum logtype ltype) { 37 if ((ltype == HEADER) 38 || (ltype == REGISTERS) 39 || (ltype == BACKTRACE)) { 40 return true; 41 } 42 return false; 43} 44 45__attribute__((__weak__, visibility("default"))) 46void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) { 47 bool write_to_tombstone = (log->tfd != -1); 48 bool write_to_logcat = is_allowed_in_logcat(ltype) 49 && log->crashed_tid != -1 50 && log->current_tid != -1 51 && (log->crashed_tid == log->current_tid); 52 53 char buf[512]; 54 va_list ap; 55 va_start(ap, fmt); 56 vsnprintf(buf, sizeof(buf), fmt, ap); 57 va_end(ap); 58 59 size_t len = strlen(buf); 60 if (len <= 0) { 61 return; 62 } 63 64 if (write_to_tombstone) { 65 TEMP_FAILURE_RETRY(write(log->tfd, buf, len)); 66 } 67 68 if (write_to_logcat) { 69 __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_FATAL, LOG_TAG, buf); 70 if (log->amfd_data != nullptr) { 71 *log->amfd_data += buf; 72 } 73 } 74} 75 76bool wait_for_signal(pid_t tid, siginfo_t* siginfo) { 77 while (true) { 78 int status; 79 pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL)); 80 if (n == -1) { 81 ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); 82 return false; 83 } else if (n == tid) { 84 if (WIFSTOPPED(status)) { 85 if (ptrace(PTRACE_GETSIGINFO, tid, nullptr, siginfo) != 0) { 86 ALOGE("PTRACE_GETSIGINFO failed: %s", strerror(errno)); 87 return false; 88 } 89 return true; 90 } else { 91 ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); 92 // This is the only circumstance under which we can allow a detach 93 // to fail with ESRCH, which indicates the tid has exited. 94 return false; 95 } 96 } 97 } 98} 99 100#define MEMORY_BYTES_TO_DUMP 256 101#define MEMORY_BYTES_PER_LINE 16 102 103void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...) { 104 std::string log_msg; 105 va_list ap; 106 va_start(ap, fmt); 107 android::base::StringAppendV(&log_msg, fmt, ap); 108 va_end(ap); 109 110 // Align the address to sizeof(long) and start 32 bytes before the address. 111 addr &= ~(sizeof(long) - 1); 112 if (addr >= 4128) { 113 addr -= 32; 114 } 115 116 // Don't bother if the address looks too low, or looks too high. 117 if (addr < 4096 || 118#if defined(__LP64__) 119 addr > 0x4000000000000000UL - MEMORY_BYTES_TO_DUMP) { 120#else 121 addr > 0xffff0000 - MEMORY_BYTES_TO_DUMP) { 122#endif 123 return; 124 } 125 126 _LOG(log, logtype::MEMORY, "\n%s\n", log_msg.c_str()); 127 128 // Dump 256 bytes 129 uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)]; 130 memset(data, 0, MEMORY_BYTES_TO_DUMP); 131 size_t bytes = backtrace->Read(addr, reinterpret_cast<uint8_t*>(data), sizeof(data)); 132 if (bytes % sizeof(uintptr_t) != 0) { 133 // This should never happen, but just in case. 134 ALOGE("Bytes read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t)); 135 bytes &= ~(sizeof(uintptr_t) - 1); 136 } 137 138 uintptr_t start = 0; 139 bool skip_2nd_read = false; 140 if (bytes == 0) { 141 // In this case, we might want to try another read at the beginning of 142 // the next page only if it's within the amount of memory we would have 143 // read. 144 size_t page_size = sysconf(_SC_PAGE_SIZE); 145 start = ((addr + (page_size - 1)) & ~(page_size - 1)) - addr; 146 if (start == 0 || start >= MEMORY_BYTES_TO_DUMP) { 147 skip_2nd_read = true; 148 } 149 } 150 151 if (bytes < MEMORY_BYTES_TO_DUMP && !skip_2nd_read) { 152 // Try to do one more read. This could happen if a read crosses a map, 153 // but the maps do not have any break between them. Or it could happen 154 // if reading from an unreadable map, but the read would cross back 155 // into a readable map. Only requires one extra read because a map has 156 // to contain at least one page, and the total number of bytes to dump 157 // is smaller than a page. 158 size_t bytes2 = backtrace->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes, 159 sizeof(data) - bytes - start); 160 bytes += bytes2; 161 if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) { 162 // This should never happen, but we'll try and continue any way. 163 ALOGE("Bytes after second read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t)); 164 bytes &= ~(sizeof(uintptr_t) - 1); 165 } 166 } 167 168 // Dump the code around memory as: 169 // addr contents ascii 170 // 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q 171 // 0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000 ......-..p...... 172 // On 32-bit machines, there are still 16 bytes per line but addresses and 173 // words are of course presented differently. 174 uintptr_t* data_ptr = data; 175 size_t current = 0; 176 size_t total_bytes = start + bytes; 177 for (size_t line = 0; line < MEMORY_BYTES_TO_DUMP / MEMORY_BYTES_PER_LINE; line++) { 178 std::string logline; 179 android::base::StringAppendF(&logline, " %" PRIPTR, addr); 180 181 addr += MEMORY_BYTES_PER_LINE; 182 std::string ascii; 183 for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++) { 184 if (current >= start && current + sizeof(uintptr_t) <= total_bytes) { 185 android::base::StringAppendF(&logline, " %" PRIPTR, *data_ptr); 186 187 // Fill out the ascii string from the data. 188 uint8_t* ptr = reinterpret_cast<uint8_t*>(data_ptr); 189 for (size_t val = 0; val < sizeof(uintptr_t); val++, ptr++) { 190 if (*ptr >= 0x20 && *ptr < 0x7f) { 191 ascii += *ptr; 192 } else { 193 ascii += '.'; 194 } 195 } 196 data_ptr++; 197 } else { 198 logline += ' ' + std::string(sizeof(uintptr_t) * 2, '-'); 199 ascii += std::string(sizeof(uintptr_t), '.'); 200 } 201 current += sizeof(uintptr_t); 202 } 203 _LOG(log, logtype::MEMORY, "%s %s\n", logline.c_str(), ascii.c_str()); 204 } 205} 206 207void read_with_default(const char* path, char* buf, size_t len, const char* default_value) { 208 android::base::unique_fd fd(open(path, O_RDONLY)); 209 if (fd != -1) { 210 int rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, len - 1)); 211 if (rc != -1) { 212 buf[rc] = '\0'; 213 214 // Trim trailing newlines. 215 if (rc > 0 && buf[rc - 1] == '\n') { 216 buf[rc - 1] = '\0'; 217 } 218 return; 219 } 220 } 221 strcpy(buf, default_value); 222} 223