120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris/* 220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * Copyright 2008, The Android Open Source Project 320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * 420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * you may not use this file except in compliance with the License. 620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * You may obtain a copy of the License at 720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * 820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * 1020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * Unless required by applicable law or agreed to in writing, software 1120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 1220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * See the License for the specific language governing permissions and 1420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris * limitations under the License. 1520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith#define LOG_TAG "DEBUG" 1862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith 19c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin#include "utility.h" 20c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin 21053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <errno.h> 22053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <signal.h> 23c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin#include <string.h> 2413e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <sys/ptrace.h> 25053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/wait.h> 26ff2dcd9af994a23ed483939a416b48bdc10eefd5Mark Salyzyn#include <unistd.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2899235e9967db4c3889435f67a45e2c79f7f59587Christopher Ferris#include <string> 2999235e9967db4c3889435f67a45e2c79f7f59587Christopher Ferris 304f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 3157f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao#include <android-base/unique_fd.h> 32c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin#include <backtrace/Backtrace.h> 33cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <log/log.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith// Whitelist output desired in the logcat output. 3662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithbool is_allowed_in_logcat(enum logtype ltype) { 37b36b5923386be8d74da2767dfc1dc62a0012a655Christopher Ferris if ((ltype == HEADER) 3862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith || (ltype == REGISTERS) 3962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith || (ltype == BACKTRACE)) { 4062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith return true; 4162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith } 4262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith return false; 4362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith} 4462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith 4597258aad8a41e375696a06793e5de3e9d75f6f1bChenjie Luo__attribute__((__weak__, visibility("default"))) 4662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithvoid _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) { 4750eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith bool write_to_tombstone = (log->tfd != -1); 4850eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith bool write_to_logcat = is_allowed_in_logcat(ltype) 49c75a02fe3f9abec006a1e88794f2fa12fbeafd8fBrigid Smith && log->crashed_tid != -1 50c75a02fe3f9abec006a1e88794f2fa12fbeafd8fBrigid Smith && log->current_tid != -1 5150eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith && (log->crashed_tid == log->current_tid); 5213e715b491e876865e752a3a69dd6f347049a488Jeff Brown 53c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin char buf[512]; 5420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris va_list ap; 5520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris va_start(ap, fmt); 56c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin vsnprintf(buf, sizeof(buf), fmt, ap); 57c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin va_end(ap); 5813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 59c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin size_t len = strlen(buf); 60c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin if (len <= 0) { 61c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin return; 6220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 63ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate 6462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith if (write_to_tombstone) { 65c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin TEMP_FAILURE_RETRY(write(log->tfd, buf, len)); 6620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 6713e715b491e876865e752a3a69dd6f347049a488Jeff Brown 6862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith if (write_to_logcat) { 69b0412a5c2b446edb137980333aa0a0bbfda2e955Christopher Ferris __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_FATAL, LOG_TAG, buf); 7099235e9967db4c3889435f67a45e2c79f7f59587Christopher Ferris if (log->amfd_data != nullptr) { 7199235e9967db4c3889435f67a45e2c79f7f59587Christopher Ferris *log->amfd_data += buf; 7213e715b491e876865e752a3a69dd6f347049a488Jeff Brown } 7320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 7413e715b491e876865e752a3a69dd6f347049a488Jeff Brown} 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 76cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaobool wait_for_signal(pid_t tid, siginfo_t* siginfo) { 777c89f9e955ddd79312113f83cb4c210a68a940aaJosh Gao while (true) { 7820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris int status; 79f5a960a187ba8959596f6a324c2b5a05c1be9b35Josh Gao pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL)); 801072f917cfa36ff905c31122a3cd99224e305932Christopher Ferris if (n == -1) { 811072f917cfa36ff905c31122a3cd99224e305932Christopher Ferris ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); 82cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao return false; 831072f917cfa36ff905c31122a3cd99224e305932Christopher Ferris } else if (n == tid) { 8420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (WIFSTOPPED(status)) { 85cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (ptrace(PTRACE_GETSIGINFO, tid, nullptr, siginfo) != 0) { 86cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ALOGE("PTRACE_GETSIGINFO failed: %s", strerror(errno)); 87cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao return false; 88cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 89cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao return true; 9020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } else { 9150eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); 921072f917cfa36ff905c31122a3cd99224e305932Christopher Ferris // This is the only circumstance under which we can allow a detach 931072f917cfa36ff905c31122a3cd99224e305932Christopher Ferris // to fail with ESRCH, which indicates the tid has exited. 94cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao return false; 9520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 9620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 9720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 98136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden} 994bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT 100e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris#define MEMORY_BYTES_TO_DUMP 256 101e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris#define MEMORY_BYTES_PER_LINE 16 102e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 103e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferrisvoid dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...) { 104e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris std::string log_msg; 105e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris va_list ap; 106e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris va_start(ap, fmt); 107e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris android::base::StringAppendV(&log_msg, fmt, ap); 108e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris va_end(ap); 109e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 110e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // Align the address to sizeof(long) and start 32 bytes before the address. 111e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris addr &= ~(sizeof(long) - 1); 112e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris if (addr >= 4128) { 113e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris addr -= 32; 114e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 1154bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT 116e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // Don't bother if the address looks too low, or looks too high. 117e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris if (addr < 4096 || 118e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris#if defined(__LP64__) 119e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris addr > 0x4000000000000000UL - MEMORY_BYTES_TO_DUMP) { 1204bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#else 121e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris addr > 0xffff0000 - MEMORY_BYTES_TO_DUMP) { 1224bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#endif 123e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris return; 124e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 125e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 126e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris _LOG(log, logtype::MEMORY, "\n%s\n", log_msg.c_str()); 127e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 128e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // Dump 256 bytes 129e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)]; 130e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris memset(data, 0, MEMORY_BYTES_TO_DUMP); 131e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris size_t bytes = backtrace->Read(addr, reinterpret_cast<uint8_t*>(data), sizeof(data)); 132e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris if (bytes % sizeof(uintptr_t) != 0) { 133e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // This should never happen, but just in case. 134e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris ALOGE("Bytes read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t)); 135e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris bytes &= ~(sizeof(uintptr_t) - 1); 136e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 137e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 138456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris uintptr_t start = 0; 139456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris bool skip_2nd_read = false; 140456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris if (bytes == 0) { 141456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // In this case, we might want to try another read at the beginning of 142456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // the next page only if it's within the amount of memory we would have 143456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // read. 144456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris size_t page_size = sysconf(_SC_PAGE_SIZE); 145456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris start = ((addr + (page_size - 1)) & ~(page_size - 1)) - addr; 146456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris if (start == 0 || start >= MEMORY_BYTES_TO_DUMP) { 147456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris skip_2nd_read = true; 148456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris } 149456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris } 150456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris 151456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris if (bytes < MEMORY_BYTES_TO_DUMP && !skip_2nd_read) { 152456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // Try to do one more read. This could happen if a read crosses a map, 153456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // but the maps do not have any break between them. Or it could happen 154456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // if reading from an unreadable map, but the read would cross back 155456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // into a readable map. Only requires one extra read because a map has 156456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // to contain at least one page, and the total number of bytes to dump 157456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris // is smaller than a page. 158456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris size_t bytes2 = backtrace->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes, 159456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris sizeof(data) - bytes - start); 160e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris bytes += bytes2; 161e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) { 162e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // This should never happen, but we'll try and continue any way. 163e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris ALOGE("Bytes after second read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t)); 164e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris bytes &= ~(sizeof(uintptr_t) - 1); 165e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 166e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 167e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 168e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // Dump the code around memory as: 169e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // addr contents ascii 170e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q 171e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // 0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000 ......-..p...... 172e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // On 32-bit machines, there are still 16 bytes per line but addresses and 173e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // words are of course presented differently. 174e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris uintptr_t* data_ptr = data; 175456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris size_t current = 0; 176456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris size_t total_bytes = start + bytes; 177e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris for (size_t line = 0; line < MEMORY_BYTES_TO_DUMP / MEMORY_BYTES_PER_LINE; line++) { 178e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris std::string logline; 179e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris android::base::StringAppendF(&logline, " %" PRIPTR, addr); 180e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 181e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris addr += MEMORY_BYTES_PER_LINE; 182e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris std::string ascii; 183456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++) { 184456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris if (current >= start && current + sizeof(uintptr_t) <= total_bytes) { 185e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris android::base::StringAppendF(&logline, " %" PRIPTR, *data_ptr); 186e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris 187e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris // Fill out the ascii string from the data. 188e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris uint8_t* ptr = reinterpret_cast<uint8_t*>(data_ptr); 189e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris for (size_t val = 0; val < sizeof(uintptr_t); val++, ptr++) { 190e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris if (*ptr >= 0x20 && *ptr < 0x7f) { 191e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris ascii += *ptr; 192e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } else { 193e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris ascii += '.'; 194e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 1954bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT } 196456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris data_ptr++; 197e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } else { 198e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris logline += ' ' + std::string(sizeof(uintptr_t) * 2, '-'); 199e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris ascii += std::string(sizeof(uintptr_t), '.'); 200e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 201456abbabf26f50f903a13aa87a57766236e8b5adChristopher Ferris current += sizeof(uintptr_t); 2024bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT } 203e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris _LOG(log, logtype::MEMORY, "%s %s\n", logline.c_str(), ascii.c_str()); 204e8bc77eb845ab5557a4c98fe0da604d4a3740befChristopher Ferris } 2054bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT} 20657f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao 20757f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gaovoid read_with_default(const char* path, char* buf, size_t len, const char* default_value) { 20857f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao android::base::unique_fd fd(open(path, O_RDONLY)); 20957f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao if (fd != -1) { 21057f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao int rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, len - 1)); 21157f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao if (rc != -1) { 21257f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao buf[rc] = '\0'; 21357f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao 21457f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao // Trim trailing newlines. 21557f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao if (rc > 0 && buf[rc - 1] == '\n') { 21657f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao buf[rc - 1] = '\0'; 21757f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao } 21857f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao return; 21957f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao } 22057f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao } 22157f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao strcpy(buf, default_value); 22257f58f8e4a143f1208593c8b397b9a17d055dad0Josh Gao} 223