1/* 2 * Copyright (C) 2007-2014 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#if (FAKE_LOG_DEVICE == 0) 17#include <endian.h> 18#endif 19#include <errno.h> 20#include <fcntl.h> 21#if !defined(_WIN32) 22#include <pthread.h> 23#endif 24#include <stdarg.h> 25#include <stdatomic.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <sys/stat.h> 30#include <sys/types.h> 31#if (FAKE_LOG_DEVICE == 0) 32#include <sys/socket.h> 33#include <sys/un.h> 34#endif 35#include <time.h> 36#include <unistd.h> 37 38#ifdef __BIONIC__ 39#include <android/set_abort_message.h> 40#endif 41 42#include <log/logd.h> 43#include <log/logger.h> 44#include <log/log_read.h> 45#include <private/android_filesystem_config.h> 46#include <private/android_logger.h> 47 48#define LOG_BUF_SIZE 1024 49 50#if FAKE_LOG_DEVICE 51/* This will be defined when building for the host. */ 52#include "fake_log_device.h" 53#endif 54 55static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); 56static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; 57#if !defined(_WIN32) 58static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; 59#endif 60 61#ifndef __unused 62#define __unused __attribute__((__unused__)) 63#endif 64 65#if FAKE_LOG_DEVICE 66static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 }; 67#else 68static int logd_fd = -1; 69static int pstore_fd = -1; 70#endif 71 72/* 73 * This is used by the C++ code to decide if it should write logs through 74 * the C code. Basically, if /dev/socket/logd is available, we're running in 75 * the simulator rather than a desktop tool and want to use the device. 76 */ 77static enum { 78 kLogUninitialized, kLogNotAvailable, kLogAvailable 79} g_log_status = kLogUninitialized; 80 81int __android_log_dev_available(void) 82{ 83 if (g_log_status == kLogUninitialized) { 84 if (access("/dev/socket/logdw", W_OK) == 0) 85 g_log_status = kLogAvailable; 86 else 87 g_log_status = kLogNotAvailable; 88 } 89 90 return (g_log_status == kLogAvailable); 91} 92 93/* log_init_lock assumed */ 94static int __write_to_log_initialize() 95{ 96 int i, ret = 0; 97 98#if FAKE_LOG_DEVICE 99 for (i = 0; i < LOG_ID_MAX; i++) { 100 char buf[sizeof("/dev/log_system")]; 101 snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i)); 102 log_fds[i] = fakeLogOpen(buf, O_WRONLY); 103 } 104#else 105 if (pstore_fd < 0) { 106 pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY)); 107 } 108 109 if (logd_fd < 0) { 110 i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)); 111 if (i < 0) { 112 ret = -errno; 113 } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) { 114 ret = -errno; 115 close(i); 116 } else { 117 struct sockaddr_un un; 118 memset(&un, 0, sizeof(struct sockaddr_un)); 119 un.sun_family = AF_UNIX; 120 strcpy(un.sun_path, "/dev/socket/logdw"); 121 122 if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un, 123 sizeof(struct sockaddr_un))) < 0) { 124 ret = -errno; 125 close(i); 126 } else { 127 logd_fd = i; 128 } 129 } 130 } 131#endif 132 133 return ret; 134} 135 136static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) 137{ 138 ssize_t ret; 139#if FAKE_LOG_DEVICE 140 int log_fd; 141 142 if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) { 143 log_fd = log_fds[(int)log_id]; 144 } else { 145 return -EBADF; 146 } 147 do { 148 ret = fakeLogWritev(log_fd, vec, nr); 149 if (ret < 0) { 150 ret = -errno; 151 } 152 } while (ret == -EINTR); 153#else 154 static const unsigned header_length = 2; 155 struct iovec newVec[nr + header_length]; 156 android_log_header_t header; 157 android_pmsg_log_header_t pmsg_header; 158 struct timespec ts; 159 size_t i, payload_size; 160 static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */ 161 static pid_t last_pid = (pid_t) -1; 162 static atomic_int_fast32_t dropped; 163 164 if (!nr) { 165 return -EINVAL; 166 } 167 168 if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ 169 last_uid = getuid(); 170 } 171 if (last_pid == (pid_t) -1) { 172 last_pid = getpid(); 173 } 174 /* 175 * struct { 176 * // what we provide to pstore 177 * android_pmsg_log_header_t pmsg_header; 178 * // what we provide to socket 179 * android_log_header_t header; 180 * // caller provides 181 * union { 182 * struct { 183 * char prio; 184 * char payload[]; 185 * } string; 186 * struct { 187 * uint32_t tag 188 * char payload[]; 189 * } binary; 190 * }; 191 * }; 192 */ 193 194 clock_gettime(CLOCK_REALTIME, &ts); 195 196 pmsg_header.magic = LOGGER_MAGIC; 197 pmsg_header.len = sizeof(pmsg_header) + sizeof(header); 198 pmsg_header.uid = last_uid; 199 pmsg_header.pid = last_pid; 200 201 header.tid = gettid(); 202 header.realtime.tv_sec = ts.tv_sec; 203 header.realtime.tv_nsec = ts.tv_nsec; 204 205 newVec[0].iov_base = (unsigned char *) &pmsg_header; 206 newVec[0].iov_len = sizeof(pmsg_header); 207 newVec[1].iov_base = (unsigned char *) &header; 208 newVec[1].iov_len = sizeof(header); 209 210 if (logd_fd > 0) { 211 int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); 212 if (snapshot) { 213 android_log_event_int_t buffer; 214 215 header.id = LOG_ID_EVENTS; 216 buffer.header.tag = htole32(LIBLOG_LOG_TAG); 217 buffer.payload.type = EVENT_TYPE_INT; 218 buffer.payload.data = htole32(snapshot); 219 220 newVec[2].iov_base = &buffer; 221 newVec[2].iov_len = sizeof(buffer); 222 223 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2)); 224 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { 225 atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed); 226 } 227 } 228 } 229 230 header.id = log_id; 231 232 for (payload_size = 0, i = header_length; i < nr + header_length; i++) { 233 newVec[i].iov_base = vec[i - header_length].iov_base; 234 payload_size += newVec[i].iov_len = vec[i - header_length].iov_len; 235 236 if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) { 237 newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD; 238 if (newVec[i].iov_len) { 239 ++i; 240 } 241 payload_size = LOGGER_ENTRY_MAX_PAYLOAD; 242 break; 243 } 244 } 245 pmsg_header.len += payload_size; 246 247 if (pstore_fd >= 0) { 248 TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i)); 249 } 250 251 if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ 252 /* 253 * ignore log messages we send to ourself (logd). 254 * Such log messages are often generated by libraries we depend on 255 * which use standard Android logging. 256 */ 257 return 0; 258 } 259 260 if (logd_fd < 0) { 261 return -EBADF; 262 } 263 264 /* 265 * The write below could be lost, but will never block. 266 * 267 * To logd, we drop the pmsg_header 268 * 269 * ENOTCONN occurs if logd dies. 270 * EAGAIN occurs if logd is overloaded. 271 */ 272 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); 273 if (ret < 0) { 274 ret = -errno; 275 if (ret == -ENOTCONN) { 276#if !defined(_WIN32) 277 pthread_mutex_lock(&log_init_lock); 278#endif 279 close(logd_fd); 280 logd_fd = -1; 281 ret = __write_to_log_initialize(); 282#if !defined(_WIN32) 283 pthread_mutex_unlock(&log_init_lock); 284#endif 285 286 if (ret < 0) { 287 return ret; 288 } 289 290 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); 291 if (ret < 0) { 292 ret = -errno; 293 } 294 } 295 } 296 297 if (ret > (ssize_t)sizeof(header)) { 298 ret -= sizeof(header); 299 } else if (ret == -EAGAIN) { 300 atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); 301 } 302#endif 303 304 return ret; 305} 306 307#if FAKE_LOG_DEVICE 308static const char *LOG_NAME[LOG_ID_MAX] = { 309 [LOG_ID_MAIN] = "main", 310 [LOG_ID_RADIO] = "radio", 311 [LOG_ID_EVENTS] = "events", 312 [LOG_ID_SYSTEM] = "system", 313 [LOG_ID_CRASH] = "crash", 314 [LOG_ID_KERNEL] = "kernel", 315}; 316 317const char *android_log_id_to_name(log_id_t log_id) 318{ 319 if (log_id >= LOG_ID_MAX) { 320 log_id = LOG_ID_MAIN; 321 } 322 return LOG_NAME[log_id]; 323} 324#endif 325 326static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) 327{ 328#if !defined(_WIN32) 329 pthread_mutex_lock(&log_init_lock); 330#endif 331 332 if (write_to_log == __write_to_log_init) { 333 int ret; 334 335 ret = __write_to_log_initialize(); 336 if (ret < 0) { 337#if !defined(_WIN32) 338 pthread_mutex_unlock(&log_init_lock); 339#endif 340#if (FAKE_LOG_DEVICE == 0) 341 if (pstore_fd >= 0) { 342 __write_to_log_daemon(log_id, vec, nr); 343 } 344#endif 345 return ret; 346 } 347 348 write_to_log = __write_to_log_daemon; 349 } 350 351#if !defined(_WIN32) 352 pthread_mutex_unlock(&log_init_lock); 353#endif 354 355 return write_to_log(log_id, vec, nr); 356} 357 358int __android_log_write(int prio, const char *tag, const char *msg) 359{ 360 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg); 361} 362 363int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) 364{ 365 struct iovec vec[3]; 366 char tmp_tag[32]; 367 368 if (!tag) 369 tag = ""; 370 371 /* XXX: This needs to go! */ 372 if ((bufID != LOG_ID_RADIO) && 373 (!strcmp(tag, "HTC_RIL") || 374 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 375 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 376 !strcmp(tag, "AT") || 377 !strcmp(tag, "GSM") || 378 !strcmp(tag, "STK") || 379 !strcmp(tag, "CDMA") || 380 !strcmp(tag, "PHONE") || 381 !strcmp(tag, "SMS"))) { 382 bufID = LOG_ID_RADIO; 383 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */ 384 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 385 tag = tmp_tag; 386 } 387 388#if __BIONIC__ 389 if (prio == ANDROID_LOG_FATAL) { 390 android_set_abort_message(msg); 391 } 392#endif 393 394 vec[0].iov_base = (unsigned char *) &prio; 395 vec[0].iov_len = 1; 396 vec[1].iov_base = (void *) tag; 397 vec[1].iov_len = strlen(tag) + 1; 398 vec[2].iov_base = (void *) msg; 399 vec[2].iov_len = strlen(msg) + 1; 400 401 return write_to_log(bufID, vec, 3); 402} 403 404int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap) 405{ 406 char buf[LOG_BUF_SIZE]; 407 408 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 409 410 return __android_log_write(prio, tag, buf); 411} 412 413int __android_log_print(int prio, const char *tag, const char *fmt, ...) 414{ 415 va_list ap; 416 char buf[LOG_BUF_SIZE]; 417 418 va_start(ap, fmt); 419 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 420 va_end(ap); 421 422 return __android_log_write(prio, tag, buf); 423} 424 425int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...) 426{ 427 va_list ap; 428 char buf[LOG_BUF_SIZE]; 429 430 va_start(ap, fmt); 431 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 432 va_end(ap); 433 434 return __android_log_buf_write(bufID, prio, tag, buf); 435} 436 437void __android_log_assert(const char *cond, const char *tag, 438 const char *fmt, ...) 439{ 440 char buf[LOG_BUF_SIZE]; 441 442 if (fmt) { 443 va_list ap; 444 va_start(ap, fmt); 445 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 446 va_end(ap); 447 } else { 448 /* Msg not provided, log condition. N.B. Do not use cond directly as 449 * format string as it could contain spurious '%' syntax (e.g. 450 * "%d" in "blocks%devs == 0"). 451 */ 452 if (cond) 453 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond); 454 else 455 strcpy(buf, "Unspecified assertion failed"); 456 } 457 458 __android_log_write(ANDROID_LOG_FATAL, tag, buf); 459 abort(); /* abort so we have a chance to debug the situation */ 460 /* NOTREACHED */ 461} 462 463int __android_log_bwrite(int32_t tag, const void *payload, size_t len) 464{ 465 struct iovec vec[2]; 466 467 vec[0].iov_base = &tag; 468 vec[0].iov_len = sizeof(tag); 469 vec[1].iov_base = (void*)payload; 470 vec[1].iov_len = len; 471 472 return write_to_log(LOG_ID_EVENTS, vec, 2); 473} 474 475/* 476 * Like __android_log_bwrite, but takes the type as well. Doesn't work 477 * for the general case where we're generating lists of stuff, but very 478 * handy if we just want to dump an integer into the log. 479 */ 480int __android_log_btwrite(int32_t tag, char type, const void *payload, 481 size_t len) 482{ 483 struct iovec vec[3]; 484 485 vec[0].iov_base = &tag; 486 vec[0].iov_len = sizeof(tag); 487 vec[1].iov_base = &type; 488 vec[1].iov_len = sizeof(type); 489 vec[2].iov_base = (void*)payload; 490 vec[2].iov_len = len; 491 492 return write_to_log(LOG_ID_EVENTS, vec, 3); 493} 494 495/* 496 * Like __android_log_bwrite, but used for writing strings to the 497 * event log. 498 */ 499int __android_log_bswrite(int32_t tag, const char *payload) 500{ 501 struct iovec vec[4]; 502 char type = EVENT_TYPE_STRING; 503 uint32_t len = strlen(payload); 504 505 vec[0].iov_base = &tag; 506 vec[0].iov_len = sizeof(tag); 507 vec[1].iov_base = &type; 508 vec[1].iov_len = sizeof(type); 509 vec[2].iov_base = &len; 510 vec[2].iov_len = sizeof(len); 511 vec[3].iov_base = (void*)payload; 512 vec[3].iov_len = len; 513 514 return write_to_log(LOG_ID_EVENTS, vec, 4); 515} 516