libc_logging.cpp revision 0d787c1fa18c6a1f29ef9840e28a68cf077be1de
15c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner/* 25c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * Copyright (C) 2010 The Android Open Source Project 35c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * All rights reserved. 45c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * 55c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * Redistribution and use in source and binary forms, with or without 65c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * modification, are permitted provided that the following conditions 75c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * are met: 85c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * * Redistributions of source code must retain the above copyright 95c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * notice, this list of conditions and the following disclaimer. 105c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * * Redistributions in binary form must reproduce the above copyright 115c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * notice, this list of conditions and the following disclaimer in 125c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * the documentation and/or other materials provided with the 135c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * distribution. 145c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * 155c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 165c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 175c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 185c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 195c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 205c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 215c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 225c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 235c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 245c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 255c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 265c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * SUCH DAMAGE. 275c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner */ 285c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 298f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes#include <../private/libc_logging.h> // Relative path so we can #include this .cpp file for testing. 308f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes#include <../private/ScopedPthreadMutexLocker.h> 31eababde2141c7128155200b213e45291cd876e46Elliott Hughes 3218a206c81d9743481e364384affd43306911283dElliott Hughes#include <assert.h> 33eababde2141c7128155200b213e45291cd876e46Elliott Hughes#include <errno.h> 340d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes#include <fcntl.h> 358f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes#include <pthread.h> 365c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner#include <stdarg.h> 37eababde2141c7128155200b213e45291cd876e46Elliott Hughes#include <stddef.h> 388f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes#include <stdlib.h> 395c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner#include <string.h> 400d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes#include <sys/mman.h> 410d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes#include <sys/uio.h> 425c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner#include <unistd.h> 43eababde2141c7128155200b213e45291cd876e46Elliott Hughes 440d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic pthread_mutex_t gAbortMsgLock = PTHREAD_MUTEX_INITIALIZER; 450d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic pthread_mutex_t gLogInitializationLock = PTHREAD_MUTEX_INITIALIZER; 465c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 470d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. 485c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 490d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes// Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java. 500d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesenum AndroidEventLogType { 510d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes EVENT_TYPE_INT = 0, 520d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes EVENT_TYPE_LONG = 1, 530d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes EVENT_TYPE_STRING = 2, 540d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes EVENT_TYPE_LIST = 3, 5518a206c81d9743481e364384affd43306911283dElliott Hughes}; 565c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 570d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstruct BufferOutputStream { 580d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes public: 590d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes BufferOutputStream(char* buffer, size_t size) : total(0) { 600d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes buffer_ = buffer; 610d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes end_ = buffer + size - 1; 620d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes pos_ = buffer_; 630d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes pos_[0] = '\0'; 640d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 655c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 660d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes ~BufferOutputStream() { 670d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 680d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 690d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes void Send(const char* data, int len) { 7018a206c81d9743481e364384affd43306911283dElliott Hughes if (len < 0) { 710d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes len = strlen(data); 7218a206c81d9743481e364384affd43306911283dElliott Hughes } 735c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 745c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner while (len > 0) { 750d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int avail = end_ - pos_; 760d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (avail == 0) { 770d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes break; 780d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 790d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (avail > len) { 800d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes avail = len; 810d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 820d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes memcpy(pos_, data, avail); 830d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes pos_ += avail; 840d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes pos_[0] = '\0'; 850d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes len -= avail; 860d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes total += avail; 875c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 880d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 895c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 9018a206c81d9743481e364384affd43306911283dElliott Hughes int total; 915c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 920d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes private: 930d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char* buffer_; 940d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char* pos_; 950d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char* end_; 960d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes}; 975c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 980d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstruct FdOutputStream { 990d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes public: 1000d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes FdOutputStream(int fd) : total(0), fd_(fd) { 1011e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1025c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1030d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes void Send(const char* data, int len) { 1040d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (len < 0) { 1050d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes len = strlen(data); 1060d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 1078f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 1080d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes while (len > 0) { 1090d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int rc = TEMP_FAILURE_RETRY(write(fd_, data, len)); 1100d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (rc == -1) { 1110d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes break; 1120d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 1130d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes data += rc; 1140d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes len -= rc; 1150d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes total += rc; 1165c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 1171e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1185c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1190d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int total; 1205c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1210d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes private: 1220d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int fd_; 1230d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes}; 1245c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1255c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner/*** formatted output implementation 1265c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner ***/ 1275c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1285c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner/* Parse a decimal string from 'format + *ppos', 1295c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * return the value, and writes the new position past 1305c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * the decimal string in '*ppos' on exit. 1315c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * 1325c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * NOTE: Does *not* handle a sign prefix. 1335c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner */ 1340d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic unsigned parse_decimal(const char *format, int *ppos) { 1355c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner const char* p = format + *ppos; 1365c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner unsigned result = 0; 1375c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1385c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner for (;;) { 1395c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner int ch = *p; 1405c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner unsigned d = (unsigned)(ch - '0'); 1415c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1420d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (d >= 10U) { 1435c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 1440d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 1455c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 1465c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner result = result*10 + d; 1475c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner p++; 1485c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 1495c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner *ppos = p - format; 1505c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner return result; 1515c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner} 1525c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 153eababde2141c7128155200b213e45291cd876e46Elliott Hughes// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes. 154eababde2141c7128155200b213e45291cd876e46Elliott Hughes// Assumes that buf_size > 0. 15541b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughesstatic void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) { 156eababde2141c7128155200b213e45291cd876e46Elliott Hughes char* p = buf; 157eababde2141c7128155200b213e45291cd876e46Elliott Hughes char* end = buf + buf_size - 1; 158eababde2141c7128155200b213e45291cd876e46Elliott Hughes 159eababde2141c7128155200b213e45291cd876e46Elliott Hughes // Generate digit string in reverse order. 160eababde2141c7128155200b213e45291cd876e46Elliott Hughes while (value) { 161eababde2141c7128155200b213e45291cd876e46Elliott Hughes unsigned d = value % base; 162eababde2141c7128155200b213e45291cd876e46Elliott Hughes value /= base; 163eababde2141c7128155200b213e45291cd876e46Elliott Hughes if (p != end) { 164eababde2141c7128155200b213e45291cd876e46Elliott Hughes char ch; 165eababde2141c7128155200b213e45291cd876e46Elliott Hughes if (d < 10) { 166eababde2141c7128155200b213e45291cd876e46Elliott Hughes ch = '0' + d; 167eababde2141c7128155200b213e45291cd876e46Elliott Hughes } else { 168eababde2141c7128155200b213e45291cd876e46Elliott Hughes ch = (caps ? 'A' : 'a') + (d - 10); 169eababde2141c7128155200b213e45291cd876e46Elliott Hughes } 170eababde2141c7128155200b213e45291cd876e46Elliott Hughes *p++ = ch; 1715c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 172eababde2141c7128155200b213e45291cd876e46Elliott Hughes } 1735c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 174eababde2141c7128155200b213e45291cd876e46Elliott Hughes // Special case for 0. 175eababde2141c7128155200b213e45291cd876e46Elliott Hughes if (p == buf) { 176eababde2141c7128155200b213e45291cd876e46Elliott Hughes if (p != end) { 177eababde2141c7128155200b213e45291cd876e46Elliott Hughes *p++ = '0'; 1785c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 179eababde2141c7128155200b213e45291cd876e46Elliott Hughes } 180eababde2141c7128155200b213e45291cd876e46Elliott Hughes *p = '\0'; 181eababde2141c7128155200b213e45291cd876e46Elliott Hughes 182eababde2141c7128155200b213e45291cd876e46Elliott Hughes // Reverse digit string in-place. 183eababde2141c7128155200b213e45291cd876e46Elliott Hughes size_t length = p - buf; 184eababde2141c7128155200b213e45291cd876e46Elliott Hughes for (size_t i = 0, j = length - 1; i < j; ++i, --j) { 185eababde2141c7128155200b213e45291cd876e46Elliott Hughes char ch = buf[i]; 186eababde2141c7128155200b213e45291cd876e46Elliott Hughes buf[i] = buf[j]; 187eababde2141c7128155200b213e45291cd876e46Elliott Hughes buf[j] = ch; 188eababde2141c7128155200b213e45291cd876e46Elliott Hughes } 1895c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner} 1905c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 19141b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughesstatic void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) { 19241b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes // Decode the conversion specifier. 19341b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); 19441b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes int base = 10; 19541b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes if (conversion == 'x' || conversion == 'X') { 19641b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes base = 16; 19741b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } else if (conversion == 'o') { 19841b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes base = 8; 19941b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } 20041b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes bool caps = (conversion == 'X'); 2015c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 20241b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes if (is_signed && static_cast<int64_t>(value) < 0) { 20341b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes buf[0] = '-'; 20441b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes buf += 1; 20541b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes buf_size -= 1; 20641b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes value = static_cast<uint64_t>(-static_cast<int64_t>(value)); 20741b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } 20841b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes format_unsigned(buf, buf_size, value, base, caps); 2095c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner} 2105c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2110d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughestemplate <typename Out> 2120d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic void SendRepeat(Out& o, char ch, int count) { 2130d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char pad[8]; 2140d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes memset(pad, ch, sizeof(pad)); 2150d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 2160d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes const int pad_size = static_cast<int>(sizeof(pad)); 2170d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes while (count > 0) { 2180d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int avail = count; 2190d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (avail > pad_size) { 2200d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes avail = pad_size; 2210d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 2220d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes o.Send(pad, avail); 2230d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes count -= avail; 2240d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 2250d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 2260d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 2275c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner/* Perform formatted output to an output target 'o' */ 2280d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughestemplate <typename Out> 2290d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic void out_vformat(Out& o, const char* format, va_list args) { 230ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int nn = 0; 2315c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2325c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner for (;;) { 233ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int mm; 234ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int padZero = 0; 235ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int padLeft = 0; 236ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden char sign = '\0'; 237ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int width = -1; 238ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int prec = -1; 239ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden size_t bytelen = sizeof(int); 240ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden int slen; 241ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden char buffer[32]; /* temporary buffer used to format numbers */ 242ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden 2435c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner char c; 2445c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2455c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* first, find all characters that are not 0 or '%' */ 2465c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* then send them to the output directly */ 2475c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner mm = nn; 2485c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner do { 2495c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[mm]; 2505c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (c == '\0' || c == '%') 2515c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 2525c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner mm++; 2535c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } while (1); 2545c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2555c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (mm > nn) { 2560d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes o.Send(format+nn, mm-nn); 2575c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner nn = mm; 2585c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2595c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2605c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* is this it ? then exit */ 2615c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (c == '\0') 2625c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 2635c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2645c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* nope, we are at a '%' modifier */ 2655c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner nn++; // skip it 2665c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2675c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* parse flags */ 2685c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner for (;;) { 2695c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 2705c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (c == '\0') { /* single trailing '%' ? */ 2715c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = '%'; 2720d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes o.Send(&c, 1); 2735c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner return; 2745c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2755c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner else if (c == '0') { 2765c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner padZero = 1; 2775c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner continue; 2785c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2795c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner else if (c == '-') { 2805c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner padLeft = 1; 2815c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner continue; 2825c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2835c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner else if (c == ' ' || c == '+') { 2845c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner sign = c; 2855c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner continue; 2865c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2875c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 2885c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2895c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2905c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* parse field width */ 2915c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if ((c >= '0' && c <= '9')) { 2925c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner nn --; 2935c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner width = (int)parse_decimal(format, &nn); 2945c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 2955c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 2965c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 2975c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* parse precision */ 2985c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (c == '.') { 2995c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner prec = (int)parse_decimal(format, &nn); 3005c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 3015c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3025c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3035c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* length modifier */ 3045c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner switch (c) { 3055c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 'h': 3065c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(short); 3075c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (format[nn] == 'h') { 3085c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(char); 3095c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner nn += 1; 3105c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3115c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 3125c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 3135c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 'l': 3145c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(long); 3155c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (format[nn] == 'l') { 3165c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(long long); 3175c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner nn += 1; 3185c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3195c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 3205c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 3215c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 'z': 3225c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(size_t); 3235c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 3245c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 3255c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 't': 3265c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner bytelen = sizeof(ptrdiff_t); 3275c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner c = format[nn++]; 3285c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner break; 3295c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner default: 3305c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner ; 3315c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3325c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3335c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* conversion specifier */ 33441b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes const char* str = buffer; 3355c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (c == 's') { 3365c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* string */ 3375c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner str = va_arg(args, const char*); 338239e7a0756fddf3698bf72cab10d7f382421090bElliott Hughes if (str == NULL) { 339239e7a0756fddf3698bf72cab10d7f382421090bElliott Hughes str = "(null)"; 340239e7a0756fddf3698bf72cab10d7f382421090bElliott Hughes } 3415c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } else if (c == 'c') { 3425c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* character */ 3435c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* NOTE: char is promoted to int when passed through the stack */ 3445c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner buffer[0] = (char) va_arg(args, int); 3455c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner buffer[1] = '\0'; 3465c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } else if (c == 'p') { 347ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden uint64_t value = (uintptr_t) va_arg(args, void*); 3485c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner buffer[0] = '0'; 3495c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner buffer[1] = 'x'; 35041b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x'); 35141b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } else if (c == 'd' || c == 'i' || c == 'o' || c == 'x' || c == 'X') { 3525c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* integers - first read value from stack */ 3535c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner uint64_t value; 35441b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes int is_signed = (c == 'd' || c == 'i' || c == 'o'); 3555c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3565c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* NOTE: int8_t and int16_t are promoted to int when passed 3575c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * through the stack 3585c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner */ 3595c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner switch (bytelen) { 3605c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 1: value = (uint8_t) va_arg(args, int); break; 3615c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 2: value = (uint16_t) va_arg(args, int); break; 3625c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 4: value = va_arg(args, uint32_t); break; 3635c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner case 8: value = va_arg(args, uint64_t); break; 3645c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner default: return; /* should not happen */ 3655c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3665c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3675c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* sign extension, if needed */ 36841b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes if (is_signed) { 3695c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner int shift = 64 - 8*bytelen; 3705c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner value = (uint64_t)(((int64_t)(value << shift)) >> shift); 3715c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3725c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3735c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* format the number properly into our buffer */ 37441b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes format_integer(buffer, sizeof(buffer), value, c); 37541b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } else if (c == '%') { 37641b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes buffer[0] = '%'; 37741b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes buffer[1] = '\0'; 37841b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes } else { 37941b3179c9ef03ebb447cac7f5e8405dce399cb17Elliott Hughes __assert(__FILE__, __LINE__, "conversion specifier unsupported"); 3805c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3815c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3825c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner /* if we are here, 'str' points to the content that must be 3835c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner * outputted. handle padding and alignment now */ 3845c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3855c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner slen = strlen(str); 3865c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 38718a206c81d9743481e364384affd43306911283dElliott Hughes if (sign != '\0' || prec != -1) { 38818a206c81d9743481e364384affd43306911283dElliott Hughes __assert(__FILE__, __LINE__, "sign/precision unsupported"); 38918a206c81d9743481e364384affd43306911283dElliott Hughes } 39018a206c81d9743481e364384affd43306911283dElliott Hughes 3915c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (slen < width && !padLeft) { 3925c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner char padChar = padZero ? '0' : ' '; 3930d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes SendRepeat(o, padChar, width - slen); 3945c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 3955c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3960d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes o.Send(str, slen); 3975c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner 3985c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner if (slen < width && padLeft) { 3995c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner char padChar = padZero ? '0' : ' '; 4000d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes SendRepeat(o, padChar, width - slen); 4015c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 4025c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner } 4035c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner} 4048f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4050d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesint __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) { 4060d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes BufferOutputStream os(buffer, buffer_size); 4070d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_list args; 4080d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_start(args, format); 4090d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes out_vformat(os, format, args); 4100d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_end(args); 4110d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return os.total; 4120d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4130d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4140d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesint __libc_format_fd(int fd, const char* format, ...) { 4150d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes FdOutputStream os(fd); 4160d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_list args; 4170d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_start(args, format); 4180d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes out_vformat(os, format, args); 4190d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_end(args); 4200d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return os.total; 4210d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4220d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4230d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstatic int __libc_write_log(int priority, const char* tag, const char* msg) { 4240d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes static int main_log_fd = -1; 4250d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (main_log_fd == -1) { 4260d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes ScopedPthreadMutexLocker locker(&gLogInitializationLock); 4270d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY)); 4280d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (main_log_fd == -1) { 4290d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return -1; 4300d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 4310d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 4320d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4330d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes iovec vec[3]; 4340d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[0].iov_base = &priority; 4350d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[0].iov_len = 1; 4360d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[1].iov_base = const_cast<char*>(tag); 4370d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[1].iov_len = strlen(tag) + 1; 4380d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[2].iov_base = const_cast<char*>(msg); 4390d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes vec[2].iov_len = strlen(msg) + 1; 4400d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4410d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3)); 4420d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4430d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4440d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesint __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) { 4450d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char buffer[1024]; 4460d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes BufferOutputStream os(buffer, sizeof(buffer)); 4470d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes out_vformat(os, format, args); 4480d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return __libc_write_log(priority, tag, buffer); 4490d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4500d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4510d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesint __libc_format_log(int priority, const char* tag, const char* format, ...) { 4520d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_list args; 4530d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_start(args, format); 4540d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes int result = __libc_format_log_va_list(priority, tag, format, args); 4550d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_end(args); 4560d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return result; 4570d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4588f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4598f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughesstatic int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) { 4600d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes iovec vec[3]; 4618f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[0].iov_base = &tag; 4628f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[0].iov_len = sizeof(tag); 4638f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[1].iov_base = &type; 4648f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[1].iov_len = sizeof(type); 4658f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[2].iov_base = const_cast<void*>(payload); 4668f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes vec[2].iov_len = len; 4678f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4688f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes static int event_log_fd = -1; 4698f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes if (event_log_fd == -1) { 4708f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes ScopedPthreadMutexLocker locker(&gLogInitializationLock); 4718f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY)); 4728f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes } 4738f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes return TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3)); 4748f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes} 4758f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4768f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughesvoid __libc_android_log_event_int(int32_t tag, int value) { 4778f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes __libc_android_log_event(tag, EVENT_TYPE_INT, &value, sizeof(value)); 4788f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes} 4798f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4808f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughesvoid __libc_android_log_event_uid(int32_t tag) { 4818f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes __libc_android_log_event_int(tag, getuid()); 4828f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes} 4838f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes 4848f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughesvoid __fortify_chk_fail(const char *msg, uint32_t tag) { 4858f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes if (tag != 0) { 4868f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes __libc_android_log_event_uid(tag); 4878f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes } 4880d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes __libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg); 4890d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 4900d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4910d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesvoid __libc_fatal(const char* format, ...) { 4920d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes char msg[1024]; 4930d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes BufferOutputStream os(msg, sizeof(msg)); 4940d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_list args; 4950d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_start(args, format); 4960d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes out_vformat(os, format, args); 4970d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes va_end(args); 4980d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 4990d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes // TODO: log to stderr for the benefit of "adb shell" users. 5000d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 5010d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed). 5020d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes __libc_write_log(ANDROID_LOG_FATAL, "libc", msg); 5030d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 5040d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes __libc_set_abort_message(msg); 5050d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 5068f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes abort(); 5078f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes} 5080d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 5090d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesvoid __libc_set_abort_message(const char* msg) { 5100d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes size_t size = sizeof(abort_msg_t) + strlen(msg) + 1; 5110d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes void* map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5120d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (map == MAP_FAILED) { 5130d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes return; 5140d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 5150d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes 5160d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (__abort_message_ptr != NULL) { 5170d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes ScopedPthreadMutexLocker locker(&gAbortMsgLock); 5180d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes if (*__abort_message_ptr != NULL) { 5190d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes munmap(*__abort_message_ptr, (*__abort_message_ptr)->size); 5200d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 5210d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes abort_msg_t* new_abort_message = reinterpret_cast<abort_msg_t*>(map); 5220d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes new_abort_message->size = size; 5230d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes strcpy(new_abort_message->msg, msg); 5240d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes *__abort_message_ptr = new_abort_message; 5250d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes } 5260d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes} 527