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