Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <../private/libc_logging.h> // Relative path so we can #include this .cpp file for testing.
     30 #include <../private/ScopedPthreadMutexLocker.h>
     31 
     32 #include <assert.h>
     33 #include <errno.h>
     34 #include <fcntl.h>
     35 #include <pthread.h>
     36 #include <stdarg.h>
     37 #include <stddef.h>
     38 #include <stdlib.h>
     39 #include <string.h>
     40 #include <sys/mman.h>
     41 #include <sys/uio.h>
     42 #include <unistd.h>
     43 
     44 static pthread_mutex_t gAbortMsgLock = PTHREAD_MUTEX_INITIALIZER;
     45 static pthread_mutex_t gLogInitializationLock = PTHREAD_MUTEX_INITIALIZER;
     46 
     47 __LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
     48 
     49 // Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java.
     50 enum AndroidEventLogType {
     51   EVENT_TYPE_INT      = 0,
     52   EVENT_TYPE_LONG     = 1,
     53   EVENT_TYPE_STRING   = 2,
     54   EVENT_TYPE_LIST     = 3,
     55 };
     56 
     57 struct BufferOutputStream {
     58  public:
     59   BufferOutputStream(char* buffer, size_t size) : total(0) {
     60     buffer_ = buffer;
     61     end_ = buffer + size - 1;
     62     pos_ = buffer_;
     63     pos_[0] = '\0';
     64   }
     65 
     66   ~BufferOutputStream() {
     67   }
     68 
     69   void Send(const char* data, int len) {
     70     if (len < 0) {
     71       len = strlen(data);
     72     }
     73 
     74     while (len > 0) {
     75       int avail = end_ - pos_;
     76       if (avail == 0) {
     77         break;
     78       }
     79       if (avail > len) {
     80         avail = len;
     81       }
     82       memcpy(pos_, data, avail);
     83       pos_ += avail;
     84       pos_[0] = '\0';
     85       len -= avail;
     86       total += avail;
     87     }
     88   }
     89 
     90   int total;
     91 
     92  private:
     93   char* buffer_;
     94   char* pos_;
     95   char* end_;
     96 };
     97 
     98 struct FdOutputStream {
     99  public:
    100   FdOutputStream(int fd) : total(0), fd_(fd) {
    101   }
    102 
    103   void Send(const char* data, int len) {
    104     if (len < 0) {
    105       len = strlen(data);
    106     }
    107 
    108     while (len > 0) {
    109       int rc = TEMP_FAILURE_RETRY(write(fd_, data, len));
    110       if (rc == -1) {
    111         break;
    112       }
    113       data += rc;
    114       len -= rc;
    115       total += rc;
    116     }
    117   }
    118 
    119   int total;
    120 
    121  private:
    122   int fd_;
    123 };
    124 
    125 /*** formatted output implementation
    126  ***/
    127 
    128 /* Parse a decimal string from 'format + *ppos',
    129  * return the value, and writes the new position past
    130  * the decimal string in '*ppos' on exit.
    131  *
    132  * NOTE: Does *not* handle a sign prefix.
    133  */
    134 static unsigned parse_decimal(const char *format, int *ppos) {
    135     const char* p = format + *ppos;
    136     unsigned result = 0;
    137 
    138     for (;;) {
    139         int ch = *p;
    140         unsigned d = (unsigned)(ch - '0');
    141 
    142         if (d >= 10U) {
    143             break;
    144         }
    145 
    146         result = result*10 + d;
    147         p++;
    148     }
    149     *ppos = p - format;
    150     return result;
    151 }
    152 
    153 // Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes.
    154 // Assumes that buf_size > 0.
    155 static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) {
    156   char* p = buf;
    157   char* end = buf + buf_size - 1;
    158 
    159   // Generate digit string in reverse order.
    160   while (value) {
    161     unsigned d = value % base;
    162     value /= base;
    163     if (p != end) {
    164       char ch;
    165       if (d < 10) {
    166         ch = '0' + d;
    167       } else {
    168         ch = (caps ? 'A' : 'a') + (d - 10);
    169       }
    170       *p++ = ch;
    171     }
    172   }
    173 
    174   // Special case for 0.
    175   if (p == buf) {
    176     if (p != end) {
    177       *p++ = '0';
    178     }
    179   }
    180   *p = '\0';
    181 
    182   // Reverse digit string in-place.
    183   size_t length = p - buf;
    184   for (size_t i = 0, j = length - 1; i < j; ++i, --j) {
    185     char ch = buf[i];
    186     buf[i] = buf[j];
    187     buf[j] = ch;
    188   }
    189 }
    190 
    191 static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) {
    192   // Decode the conversion specifier.
    193   int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o');
    194   int base = 10;
    195   if (conversion == 'x' || conversion == 'X') {
    196     base = 16;
    197   } else if (conversion == 'o') {
    198     base = 8;
    199   }
    200   bool caps = (conversion == 'X');
    201 
    202   if (is_signed && static_cast<int64_t>(value) < 0) {
    203     buf[0] = '-';
    204     buf += 1;
    205     buf_size -= 1;
    206     value = static_cast<uint64_t>(-static_cast<int64_t>(value));
    207   }
    208   format_unsigned(buf, buf_size, value, base, caps);
    209 }
    210 
    211 template <typename Out>
    212 static void SendRepeat(Out& o, char ch, int count) {
    213   char pad[8];
    214   memset(pad, ch, sizeof(pad));
    215 
    216   const int pad_size = static_cast<int>(sizeof(pad));
    217   while (count > 0) {
    218     int avail = count;
    219     if (avail > pad_size) {
    220       avail = pad_size;
    221     }
    222     o.Send(pad, avail);
    223     count -= avail;
    224   }
    225 }
    226 
    227 /* Perform formatted output to an output target 'o' */
    228 template <typename Out>
    229 static void out_vformat(Out& o, const char* format, va_list args) {
    230     int nn = 0;
    231 
    232     for (;;) {
    233         int mm;
    234         int padZero = 0;
    235         int padLeft = 0;
    236         char sign = '\0';
    237         int width = -1;
    238         int prec  = -1;
    239         size_t bytelen = sizeof(int);
    240         int slen;
    241         char buffer[32];  /* temporary buffer used to format numbers */
    242 
    243         char  c;
    244 
    245         /* first, find all characters that are not 0 or '%' */
    246         /* then send them to the output directly */
    247         mm = nn;
    248         do {
    249             c = format[mm];
    250             if (c == '\0' || c == '%')
    251                 break;
    252             mm++;
    253         } while (1);
    254 
    255         if (mm > nn) {
    256             o.Send(format+nn, mm-nn);
    257             nn = mm;
    258         }
    259 
    260         /* is this it ? then exit */
    261         if (c == '\0')
    262             break;
    263 
    264         /* nope, we are at a '%' modifier */
    265         nn++;  // skip it
    266 
    267         /* parse flags */
    268         for (;;) {
    269             c = format[nn++];
    270             if (c == '\0') {  /* single trailing '%' ? */
    271                 c = '%';
    272                 o.Send(&c, 1);
    273                 return;
    274             }
    275             else if (c == '0') {
    276                 padZero = 1;
    277                 continue;
    278             }
    279             else if (c == '-') {
    280                 padLeft = 1;
    281                 continue;
    282             }
    283             else if (c == ' ' || c == '+') {
    284                 sign = c;
    285                 continue;
    286             }
    287             break;
    288         }
    289 
    290         /* parse field width */
    291         if ((c >= '0' && c <= '9')) {
    292             nn --;
    293             width = (int)parse_decimal(format, &nn);
    294             c = format[nn++];
    295         }
    296 
    297         /* parse precision */
    298         if (c == '.') {
    299             prec = (int)parse_decimal(format, &nn);
    300             c = format[nn++];
    301         }
    302 
    303         /* length modifier */
    304         switch (c) {
    305         case 'h':
    306             bytelen = sizeof(short);
    307             if (format[nn] == 'h') {
    308                 bytelen = sizeof(char);
    309                 nn += 1;
    310             }
    311             c = format[nn++];
    312             break;
    313         case 'l':
    314             bytelen = sizeof(long);
    315             if (format[nn] == 'l') {
    316                 bytelen = sizeof(long long);
    317                 nn += 1;
    318             }
    319             c = format[nn++];
    320             break;
    321         case 'z':
    322             bytelen = sizeof(size_t);
    323             c = format[nn++];
    324             break;
    325         case 't':
    326             bytelen = sizeof(ptrdiff_t);
    327             c = format[nn++];
    328             break;
    329         default:
    330             ;
    331         }
    332 
    333         /* conversion specifier */
    334         const char* str = buffer;
    335         if (c == 's') {
    336             /* string */
    337             str = va_arg(args, const char*);
    338             if (str == NULL) {
    339                 str = "(null)";
    340             }
    341         } else if (c == 'c') {
    342             /* character */
    343             /* NOTE: char is promoted to int when passed through the stack */
    344             buffer[0] = (char) va_arg(args, int);
    345             buffer[1] = '\0';
    346         } else if (c == 'p') {
    347             uint64_t  value = (uintptr_t) va_arg(args, void*);
    348             buffer[0] = '0';
    349             buffer[1] = 'x';
    350             format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
    351         } else if (c == 'd' || c == 'i' || c == 'o' || c == 'x' || c == 'X') {
    352             /* integers - first read value from stack */
    353             uint64_t value;
    354             int is_signed = (c == 'd' || c == 'i' || c == 'o');
    355 
    356             /* NOTE: int8_t and int16_t are promoted to int when passed
    357              *       through the stack
    358              */
    359             switch (bytelen) {
    360             case 1: value = (uint8_t)  va_arg(args, int); break;
    361             case 2: value = (uint16_t) va_arg(args, int); break;
    362             case 4: value = va_arg(args, uint32_t); break;
    363             case 8: value = va_arg(args, uint64_t); break;
    364             default: return;  /* should not happen */
    365             }
    366 
    367             /* sign extension, if needed */
    368             if (is_signed) {
    369                 int shift = 64 - 8*bytelen;
    370                 value = (uint64_t)(((int64_t)(value << shift)) >> shift);
    371             }
    372 
    373             /* format the number properly into our buffer */
    374             format_integer(buffer, sizeof(buffer), value, c);
    375         } else if (c == '%') {
    376             buffer[0] = '%';
    377             buffer[1] = '\0';
    378         } else {
    379             __assert(__FILE__, __LINE__, "conversion specifier unsupported");
    380         }
    381 
    382         /* if we are here, 'str' points to the content that must be
    383          * outputted. handle padding and alignment now */
    384 
    385         slen = strlen(str);
    386 
    387         if (sign != '\0' || prec != -1) {
    388             __assert(__FILE__, __LINE__, "sign/precision unsupported");
    389         }
    390 
    391         if (slen < width && !padLeft) {
    392             char padChar = padZero ? '0' : ' ';
    393             SendRepeat(o, padChar, width - slen);
    394         }
    395 
    396         o.Send(str, slen);
    397 
    398         if (slen < width && padLeft) {
    399             char padChar = padZero ? '0' : ' ';
    400             SendRepeat(o, padChar, width - slen);
    401         }
    402     }
    403 }
    404 
    405 int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) {
    406   BufferOutputStream os(buffer, buffer_size);
    407   va_list args;
    408   va_start(args, format);
    409   out_vformat(os, format, args);
    410   va_end(args);
    411   return os.total;
    412 }
    413 
    414 int __libc_format_fd(int fd, const char* format, ...) {
    415   FdOutputStream os(fd);
    416   va_list args;
    417   va_start(args, format);
    418   out_vformat(os, format, args);
    419   va_end(args);
    420   return os.total;
    421 }
    422 
    423 static int __libc_write_log(int priority, const char* tag, const char* msg) {
    424   static int main_log_fd = -1;
    425   if (main_log_fd == -1) {
    426     ScopedPthreadMutexLocker locker(&gLogInitializationLock);
    427     main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
    428     if (main_log_fd == -1) {
    429       return -1;
    430     }
    431   }
    432 
    433   iovec vec[3];
    434   vec[0].iov_base = &priority;
    435   vec[0].iov_len = 1;
    436   vec[1].iov_base = const_cast<char*>(tag);
    437   vec[1].iov_len = strlen(tag) + 1;
    438   vec[2].iov_base = const_cast<char*>(msg);
    439   vec[2].iov_len = strlen(msg) + 1;
    440 
    441   return TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
    442 }
    443 
    444 int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
    445   char buffer[1024];
    446   BufferOutputStream os(buffer, sizeof(buffer));
    447   out_vformat(os, format, args);
    448   return __libc_write_log(priority, tag, buffer);
    449 }
    450 
    451 int __libc_format_log(int priority, const char* tag, const char* format, ...) {
    452   va_list args;
    453   va_start(args, format);
    454   int result = __libc_format_log_va_list(priority, tag, format, args);
    455   va_end(args);
    456   return result;
    457 }
    458 
    459 static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
    460   iovec vec[3];
    461   vec[0].iov_base = &tag;
    462   vec[0].iov_len = sizeof(tag);
    463   vec[1].iov_base = &type;
    464   vec[1].iov_len = sizeof(type);
    465   vec[2].iov_base = const_cast<void*>(payload);
    466   vec[2].iov_len = len;
    467 
    468   static int event_log_fd = -1;
    469   if (event_log_fd == -1) {
    470     ScopedPthreadMutexLocker locker(&gLogInitializationLock);
    471     event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
    472   }
    473   return TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
    474 }
    475 
    476 void __libc_android_log_event_int(int32_t tag, int value) {
    477   __libc_android_log_event(tag, EVENT_TYPE_INT, &value, sizeof(value));
    478 }
    479 
    480 void __libc_android_log_event_uid(int32_t tag) {
    481   __libc_android_log_event_int(tag, getuid());
    482 }
    483 
    484 void __fortify_chk_fail(const char *msg, uint32_t tag) {
    485   if (tag != 0) {
    486     __libc_android_log_event_uid(tag);
    487   }
    488   __libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg);
    489 }
    490 
    491 void __libc_fatal(const char* format, ...) {
    492   char msg[1024];
    493   BufferOutputStream os(msg, sizeof(msg));
    494   va_list args;
    495   va_start(args, format);
    496   out_vformat(os, format, args);
    497   va_end(args);
    498 
    499   // TODO: log to stderr for the benefit of "adb shell" users.
    500 
    501   // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
    502   __libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
    503 
    504   __libc_set_abort_message(msg);
    505 
    506   abort();
    507 }
    508 
    509 void __libc_set_abort_message(const char* msg) {
    510   size_t size = sizeof(abort_msg_t) + strlen(msg) + 1;
    511   void* map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
    512   if (map == MAP_FAILED) {
    513     return;
    514   }
    515 
    516   if (__abort_message_ptr != NULL) {
    517     ScopedPthreadMutexLocker locker(&gAbortMsgLock);
    518     if (*__abort_message_ptr != NULL) {
    519       munmap(*__abort_message_ptr, (*__abort_message_ptr)->size);
    520     }
    521     abort_msg_t* new_abort_message = reinterpret_cast<abort_msg_t*>(map);
    522     new_abort_message->size = size;
    523     strcpy(new_abort_message->msg, msg);
    524     *__abort_message_ptr = new_abort_message;
    525   }
    526 }
    527