Loading logcat/logcat.cpp +257 −67 Original line number Diff line number Diff line Loading @@ -30,6 +30,57 @@ static AndroidLogFormat * g_logformat; #define LOG_FILE_DIR "/dev/log/" struct queued_entry_t { union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); struct logger_entry entry __attribute__((aligned(4))); }; queued_entry_t* next; queued_entry_t() { next = NULL; } }; static int cmp(queued_entry_t* a, queued_entry_t* b) { int n = a->entry.sec - b->entry.sec; if (n != 0) { return n; } return a->entry.nsec - b->entry.nsec; } struct log_device_t { char* device; bool binary; int fd; bool printed; char label; queued_entry_t* queue; log_device_t* next; log_device_t(char* d, bool b, char l) { device = d; binary = b; label = l; next = NULL; printed = false; } void enqueue(queued_entry_t* entry) { if (this->queue == NULL) { this->queue = entry; } else { queued_entry_t** e = &this->queue; while (*e && cmp(entry, *e) >= 0) { e = &((*e)->next); } entry->next = *e; *e = entry; } } }; namespace android { Loading @@ -40,8 +91,8 @@ static int g_logRotateSizeKBytes = 0; // 0 means "no log rotat static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded" static int g_outFD = -1; static off_t g_outByteCount = 0; static int g_isBinary = 0; static int g_printBinary = 0; static int g_devCount = 0; static EventTagMap* g_eventTagMap = NULL; Loading Loading @@ -103,14 +154,37 @@ void printBinary(struct logger_entry *buf) } while (ret < 0 && errno == EINTR); } static void processBuffer(struct logger_entry *buf) static void processBuffer(log_device_t* dev, struct logger_entry *buf) { int bytesWritten; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; if (g_isBinary) { if (!dev->printed) { dev->printed = true; if (g_devCount > 1) { snprintf(binaryMsgBuf, sizeof(binaryMsgBuf), "--------- beginning of %s\n", dev->device); bytesWritten = write(g_outFD, binaryMsgBuf, strlen(binaryMsgBuf)); if (bytesWritten < 0) { perror("output error"); exit(-1); } } } if (g_devCount > 1) { binaryMsgBuf[0] = dev->label; binaryMsgBuf[1] = ' '; bytesWritten = write(g_outFD, binaryMsgBuf, 2); if (bytesWritten < 0) { perror("output error"); exit(-1); } } if (dev->binary) { err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", Loading Loading @@ -142,19 +216,83 @@ error: return; } static void readLogLines(int logfd) static void chooseFirst(log_device_t* dev, log_device_t** firstdev, queued_entry_t** firstentry) { *firstdev = NULL; *firstentry = NULL; int i=0; for (; dev; dev=dev->next) { i++; if (dev->queue) { if ((*firstentry) == NULL || cmp(dev->queue, *firstentry) < 0) { (*firstentry) = dev->queue; *firstdev = dev; } } } } static void printEntry(log_device_t* dev, queued_entry_t* entry) { if (g_printBinary) { printBinary(&entry->entry); } else { processBuffer(dev, &entry->entry); } } static void eatEntry(log_device_t* dev, queued_entry_t* entry) { if (dev->queue != entry) { perror("assertion failed: entry isn't first in queue"); exit(1); } printEntry(dev, entry); dev->queue = entry->next; delete entry; } static void readLogLines(log_device_t* devices) { while (1) { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); struct logger_entry *entry = (struct logger_entry *) buf; log_device_t* dev; int max = 0; queued_entry_t* entry; queued_entry_t* old; int ret; bool somethingForEveryone; bool sleep = true; ret = read(logfd, entry, LOGGER_ENTRY_MAX_LEN); int result; fd_set readset; for (dev=devices; dev; dev = dev->next) { if (dev->fd > max) { max = dev->fd; } } while (1) { do { timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR. FD_ZERO(&readset); for (dev=devices; dev; dev = dev->next) { FD_SET(dev->fd, &readset); } result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout); } while (result == -1 && errno == EINTR); if (result >= 0) { for (dev=devices; dev; dev = dev->next) { if (FD_ISSET(dev->fd, &readset)) { entry = new queued_entry_t; /* NOTE: driver guarantees we read exactly one full entry */ ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) if (errno == EINTR) { delete entry; goto next; } if (errno == EAGAIN) { delete entry; break; } perror("logcat read"); exit(EXIT_FAILURE); } Loading @@ -163,16 +301,41 @@ static void readLogLines(int logfd) exit(EXIT_FAILURE); } /* NOTE: driver guarantees we read exactly one full entry */ entry->entry.msg[entry->entry.len] = '\0'; entry->msg[entry->len] = '\0'; dev->enqueue(entry); } } if (g_printBinary) { printBinary(entry); if (result == 0) { // we did our short timeout trick and there's nothing new // print all that aren't the last in their list sleep = true; while (true) { chooseFirst(devices, &dev, &entry); if (!entry) { break; } eatEntry(dev, entry); } } else { (void) processBuffer(entry); // print all that aren't the last in their list while (true) { chooseFirst(devices, &dev, &entry); if (!entry) { sleep = false; break; } else if (entry->next == NULL) { sleep = false; break; } eatEntry(dev, entry); } } } next: ; } } static int clearLog(int logfd) Loading Loading @@ -277,14 +440,15 @@ extern "C" void logprint_run_tests(void); int main(int argc, char **argv) { int logfd; int err; int hasSetLogFormat = 0; int clearLog = 0; int getLogSize = 0; int mode = O_RDONLY; char *log_device = strdup("/dev/"LOGGER_LOG_MAIN); const char *forceFilters = NULL; log_device_t* devices = NULL; log_device_t* dev; bool needBinary = false; g_logformat = android_log_format_new(); Loading Loading @@ -326,14 +490,27 @@ int main (int argc, char **argv) getLogSize = 1; break; case 'b': free(log_device); log_device = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); strcpy(log_device, LOG_FILE_DIR); strcat(log_device, optarg); case 'b': { char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); strcpy(buf, LOG_FILE_DIR); strcat(buf, optarg); bool binary = strcmp(optarg, "events") == 0; if (binary) { needBinary = true; } android::g_isBinary = (strcmp(optarg, "events") == 0); if (devices) { dev = devices; while (dev->next) { dev = dev->next; } dev->next = new log_device_t(buf, binary, optarg[0]); } else { devices = new log_device_t(buf, binary, optarg[0]); } android::g_devCount++; } break; case 'B': Loading Loading @@ -460,6 +637,11 @@ int main (int argc, char **argv) } } if (!devices) { devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, LOGGER_LOG_MAIN[0]); android::g_devCount = 1; } if (android::g_logRotateSizeKBytes != 0 && android::g_outputFileName == NULL ) { Loading Loading @@ -516,16 +698,18 @@ int main (int argc, char **argv) } } logfd = open(log_device, mode); if (logfd < 0) { dev = devices; while (dev) { dev->fd = open(dev->device, mode); if (dev->fd < 0) { fprintf(stderr, "Unable to open log device '%s': %s\n", log_device, strerror(errno)); dev->device, strerror(errno)); exit(EXIT_FAILURE); } if (clearLog) { int ret; ret = android::clearLog(logfd); ret = android::clearLog(dev->fd); if (ret) { perror("ioctl"); exit(EXIT_FAILURE); Loading @@ -536,22 +720,28 @@ int main (int argc, char **argv) if (getLogSize) { int size, readable; size = android::getLogSize(logfd); size = android::getLogSize(dev->fd); if (size < 0) { perror("ioctl"); exit(EXIT_FAILURE); } readable = android::getLogReadableSize(logfd); readable = android::getLogReadableSize(dev->fd); if (readable < 0) { perror("ioctl"); exit(EXIT_FAILURE); } printf("ring buffer is %dKb (%dKb consumed), " "max entry is %db, max payload is %db\n", printf("%s: ring buffer is %dKb (%dKb consumed), " "max entry is %db, max payload is %db\n", dev->device, size / 1024, readable / 1024, (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD); } dev = dev->next; } if (getLogSize) { return 0; } Loading @@ -559,10 +749,10 @@ int main (int argc, char **argv) //LOG_EVENT_LONG(11, 0x1122334455667788LL); //LOG_EVENT_STRING(0, "whassup, doc?"); if (android::g_isBinary) if (needBinary) android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE); android::readLogLines(logfd); android::readLogLines(devices); return 0; } Loading
logcat/logcat.cpp +257 −67 Original line number Diff line number Diff line Loading @@ -30,6 +30,57 @@ static AndroidLogFormat * g_logformat; #define LOG_FILE_DIR "/dev/log/" struct queued_entry_t { union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); struct logger_entry entry __attribute__((aligned(4))); }; queued_entry_t* next; queued_entry_t() { next = NULL; } }; static int cmp(queued_entry_t* a, queued_entry_t* b) { int n = a->entry.sec - b->entry.sec; if (n != 0) { return n; } return a->entry.nsec - b->entry.nsec; } struct log_device_t { char* device; bool binary; int fd; bool printed; char label; queued_entry_t* queue; log_device_t* next; log_device_t(char* d, bool b, char l) { device = d; binary = b; label = l; next = NULL; printed = false; } void enqueue(queued_entry_t* entry) { if (this->queue == NULL) { this->queue = entry; } else { queued_entry_t** e = &this->queue; while (*e && cmp(entry, *e) >= 0) { e = &((*e)->next); } entry->next = *e; *e = entry; } } }; namespace android { Loading @@ -40,8 +91,8 @@ static int g_logRotateSizeKBytes = 0; // 0 means "no log rotat static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded" static int g_outFD = -1; static off_t g_outByteCount = 0; static int g_isBinary = 0; static int g_printBinary = 0; static int g_devCount = 0; static EventTagMap* g_eventTagMap = NULL; Loading Loading @@ -103,14 +154,37 @@ void printBinary(struct logger_entry *buf) } while (ret < 0 && errno == EINTR); } static void processBuffer(struct logger_entry *buf) static void processBuffer(log_device_t* dev, struct logger_entry *buf) { int bytesWritten; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; if (g_isBinary) { if (!dev->printed) { dev->printed = true; if (g_devCount > 1) { snprintf(binaryMsgBuf, sizeof(binaryMsgBuf), "--------- beginning of %s\n", dev->device); bytesWritten = write(g_outFD, binaryMsgBuf, strlen(binaryMsgBuf)); if (bytesWritten < 0) { perror("output error"); exit(-1); } } } if (g_devCount > 1) { binaryMsgBuf[0] = dev->label; binaryMsgBuf[1] = ' '; bytesWritten = write(g_outFD, binaryMsgBuf, 2); if (bytesWritten < 0) { perror("output error"); exit(-1); } } if (dev->binary) { err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", Loading Loading @@ -142,19 +216,83 @@ error: return; } static void readLogLines(int logfd) static void chooseFirst(log_device_t* dev, log_device_t** firstdev, queued_entry_t** firstentry) { *firstdev = NULL; *firstentry = NULL; int i=0; for (; dev; dev=dev->next) { i++; if (dev->queue) { if ((*firstentry) == NULL || cmp(dev->queue, *firstentry) < 0) { (*firstentry) = dev->queue; *firstdev = dev; } } } } static void printEntry(log_device_t* dev, queued_entry_t* entry) { if (g_printBinary) { printBinary(&entry->entry); } else { processBuffer(dev, &entry->entry); } } static void eatEntry(log_device_t* dev, queued_entry_t* entry) { if (dev->queue != entry) { perror("assertion failed: entry isn't first in queue"); exit(1); } printEntry(dev, entry); dev->queue = entry->next; delete entry; } static void readLogLines(log_device_t* devices) { while (1) { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); struct logger_entry *entry = (struct logger_entry *) buf; log_device_t* dev; int max = 0; queued_entry_t* entry; queued_entry_t* old; int ret; bool somethingForEveryone; bool sleep = true; ret = read(logfd, entry, LOGGER_ENTRY_MAX_LEN); int result; fd_set readset; for (dev=devices; dev; dev = dev->next) { if (dev->fd > max) { max = dev->fd; } } while (1) { do { timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR. FD_ZERO(&readset); for (dev=devices; dev; dev = dev->next) { FD_SET(dev->fd, &readset); } result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout); } while (result == -1 && errno == EINTR); if (result >= 0) { for (dev=devices; dev; dev = dev->next) { if (FD_ISSET(dev->fd, &readset)) { entry = new queued_entry_t; /* NOTE: driver guarantees we read exactly one full entry */ ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) if (errno == EINTR) { delete entry; goto next; } if (errno == EAGAIN) { delete entry; break; } perror("logcat read"); exit(EXIT_FAILURE); } Loading @@ -163,16 +301,41 @@ static void readLogLines(int logfd) exit(EXIT_FAILURE); } /* NOTE: driver guarantees we read exactly one full entry */ entry->entry.msg[entry->entry.len] = '\0'; entry->msg[entry->len] = '\0'; dev->enqueue(entry); } } if (g_printBinary) { printBinary(entry); if (result == 0) { // we did our short timeout trick and there's nothing new // print all that aren't the last in their list sleep = true; while (true) { chooseFirst(devices, &dev, &entry); if (!entry) { break; } eatEntry(dev, entry); } } else { (void) processBuffer(entry); // print all that aren't the last in their list while (true) { chooseFirst(devices, &dev, &entry); if (!entry) { sleep = false; break; } else if (entry->next == NULL) { sleep = false; break; } eatEntry(dev, entry); } } } next: ; } } static int clearLog(int logfd) Loading Loading @@ -277,14 +440,15 @@ extern "C" void logprint_run_tests(void); int main(int argc, char **argv) { int logfd; int err; int hasSetLogFormat = 0; int clearLog = 0; int getLogSize = 0; int mode = O_RDONLY; char *log_device = strdup("/dev/"LOGGER_LOG_MAIN); const char *forceFilters = NULL; log_device_t* devices = NULL; log_device_t* dev; bool needBinary = false; g_logformat = android_log_format_new(); Loading Loading @@ -326,14 +490,27 @@ int main (int argc, char **argv) getLogSize = 1; break; case 'b': free(log_device); log_device = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); strcpy(log_device, LOG_FILE_DIR); strcat(log_device, optarg); case 'b': { char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); strcpy(buf, LOG_FILE_DIR); strcat(buf, optarg); bool binary = strcmp(optarg, "events") == 0; if (binary) { needBinary = true; } android::g_isBinary = (strcmp(optarg, "events") == 0); if (devices) { dev = devices; while (dev->next) { dev = dev->next; } dev->next = new log_device_t(buf, binary, optarg[0]); } else { devices = new log_device_t(buf, binary, optarg[0]); } android::g_devCount++; } break; case 'B': Loading Loading @@ -460,6 +637,11 @@ int main (int argc, char **argv) } } if (!devices) { devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, LOGGER_LOG_MAIN[0]); android::g_devCount = 1; } if (android::g_logRotateSizeKBytes != 0 && android::g_outputFileName == NULL ) { Loading Loading @@ -516,16 +698,18 @@ int main (int argc, char **argv) } } logfd = open(log_device, mode); if (logfd < 0) { dev = devices; while (dev) { dev->fd = open(dev->device, mode); if (dev->fd < 0) { fprintf(stderr, "Unable to open log device '%s': %s\n", log_device, strerror(errno)); dev->device, strerror(errno)); exit(EXIT_FAILURE); } if (clearLog) { int ret; ret = android::clearLog(logfd); ret = android::clearLog(dev->fd); if (ret) { perror("ioctl"); exit(EXIT_FAILURE); Loading @@ -536,22 +720,28 @@ int main (int argc, char **argv) if (getLogSize) { int size, readable; size = android::getLogSize(logfd); size = android::getLogSize(dev->fd); if (size < 0) { perror("ioctl"); exit(EXIT_FAILURE); } readable = android::getLogReadableSize(logfd); readable = android::getLogReadableSize(dev->fd); if (readable < 0) { perror("ioctl"); exit(EXIT_FAILURE); } printf("ring buffer is %dKb (%dKb consumed), " "max entry is %db, max payload is %db\n", printf("%s: ring buffer is %dKb (%dKb consumed), " "max entry is %db, max payload is %db\n", dev->device, size / 1024, readable / 1024, (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD); } dev = dev->next; } if (getLogSize) { return 0; } Loading @@ -559,10 +749,10 @@ int main (int argc, char **argv) //LOG_EVENT_LONG(11, 0x1122334455667788LL); //LOG_EVENT_STRING(0, "whassup, doc?"); if (android::g_isBinary) if (needBinary) android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE); android::readLogLines(logfd); android::readLogLines(devices); return 0; }