Loading logd/LogAudit.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ int LogAudit::logPrint(const char *fmt, ...) { static const char comm_str[] = " comm=\""; const char *comm = strstr(str, comm_str); const char *estr = str + strlen(str); char *commfree = NULL; const char *commfree = NULL; if (comm) { estr = comm; comm += sizeof(comm_str) - 1; Loading Loading @@ -231,7 +231,7 @@ int LogAudit::logPrint(const char *fmt, ...) { // end scope for main buffer } free(commfree); free(const_cast<char *>(commfree)); free(str); if (notify) { Loading logd/LogBuffer.h +2 −2 Original line number Diff line number Diff line Loading @@ -78,9 +78,9 @@ public: std::string formatPrune() { return mPrune.format(); } // helper must be protected directly or implicitly by lock()/unlock() char *pidToName(pid_t pid) { return stats.pidToName(pid); } const char *pidToName(pid_t pid) { return stats.pidToName(pid); } uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); } char *uidToName(uid_t uid) { return stats.uidToName(uid); } const char *uidToName(uid_t uid) { return stats.uidToName(uid); } void lock() { pthread_mutex_lock(&mLogElementsLock); } void unlock() { pthread_mutex_unlock(&mLogElementsLock); } Loading logd/LogBufferElement.cpp +23 −22 Original line number Diff line number Diff line Loading @@ -113,9 +113,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, static const char format_uid[] = "uid=%u%s%s expire %u line%s"; parent->lock(); char *name = parent->uidToName(mUid); const char *name = parent->uidToName(mUid); parent->unlock(); char *commName = android::tidToName(mTid); const char *commName = android::tidToName(mTid); if (!commName && (mTid != mPid)) { commName = android::tidToName(mPid); } Loading @@ -128,28 +128,28 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, size_t len = strlen(name + 1); if (!strncmp(name + 1, commName + 1, len)) { if (commName[len + 1] == '\0') { free(commName); free(const_cast<char *>(commName)); commName = NULL; } else { free(name); free(const_cast<char *>(name)); name = NULL; } } } if (name) { char *p = NULL; asprintf(&p, "(%s)", name); if (p) { free(name); name = p; char *buf = NULL; asprintf(&buf, "(%s)", name); if (buf) { free(const_cast<char *>(name)); name = buf; } } if (commName) { char *p = NULL; asprintf(&p, " %s", commName); if (p) { free(commName); commName = p; char *buf = NULL; asprintf(&buf, " %s", commName); if (buf) { free(const_cast<char *>(commName)); commName = buf; } } // identical to below to calculate the buffer size required Loading @@ -166,18 +166,19 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, buffer = static_cast<char *>(calloc(1, hdrLen + len + 1)); if (!buffer) { free(name); free(commName); free(const_cast<char *>(name)); free(const_cast<char *>(commName)); return 0; } size_t retval = hdrLen + len; if (mLogId == LOG_ID_EVENTS) { android_log_event_string_t *e = reinterpret_cast<android_log_event_string_t *>(buffer); android_log_event_string_t *event = reinterpret_cast<android_log_event_string_t *>(buffer); e->header.tag = htole32(LOGD_LOG_TAG); e->type = EVENT_TYPE_STRING; e->length = htole32(len); event->header.tag = htole32(LOGD_LOG_TAG); event->type = EVENT_TYPE_STRING; event->length = htole32(len); } else { ++retval; buffer[0] = ANDROID_LOG_INFO; Loading @@ -187,8 +188,8 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "", commName ? commName : "", mDropped, (mDropped > 1) ? "s" : ""); free(name); free(commName); free(const_cast<char *>(name)); free(const_cast<char *>(commName)); return retval; } Loading logd/LogStatistics.cpp +190 −282 Original line number Diff line number Diff line Loading @@ -14,15 +14,12 @@ * limitations under the License. */ #include <algorithm> // std::max #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <base/stringprintf.h> #include <log/logger.h> #include <private/android_filesystem_config.h> #include "LogStatistics.h" Loading Loading @@ -63,9 +60,9 @@ char *pidToName(pid_t pid) { } void LogStatistics::add(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::add(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] += size; ++mElements[log_id]; Loading @@ -76,24 +73,24 @@ void LogStatistics::add(LogBufferElement *e) { return; } uidTable[log_id].add(e->getUid(), e); uidTable[log_id].add(element->getUid(), element); if (!enable) { return; } pidTable.add(e->getPid(), e); tidTable.add(e->getTid(), e); pidTable.add(element->getPid(), element); tidTable.add(element->getTid(), element); uint32_t tag = e->getTag(); uint32_t tag = element->getTag(); if (tag) { tagTable.add(tag, e); tagTable.add(tag, element); } } void LogStatistics::subtract(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::subtract(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] -= size; --mElements[log_id]; Loading @@ -101,40 +98,40 @@ void LogStatistics::subtract(LogBufferElement *e) { return; } uidTable[log_id].subtract(e->getUid(), e); uidTable[log_id].subtract(element->getUid(), element); if (!enable) { return; } pidTable.subtract(e->getPid(), e); tidTable.subtract(e->getTid(), e); pidTable.subtract(element->getPid(), element); tidTable.subtract(element->getTid(), element); uint32_t tag = e->getTag(); uint32_t tag = element->getTag(); if (tag) { tagTable.subtract(tag, e); tagTable.subtract(tag, element); } } // Atomically set an entry to drop // entry->setDropped(1) must follow this call, caller should do this explicitly. void LogStatistics::drop(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::drop(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] -= size; uidTable[log_id].drop(e->getUid(), e); uidTable[log_id].drop(element->getUid(), element); if (!enable) { return; } pidTable.drop(e->getPid(), e); tidTable.drop(e->getTid(), e); pidTable.drop(element->getPid(), element); tidTable.drop(element->getTid(), element); } // caller must own and free character string char *LogStatistics::uidToName(uid_t uid) { const char *LogStatistics::uidToName(uid_t uid) const { // Local hard coded favourites if (uid == AID_LOGD) { return strdup("auditd"); Loading @@ -152,7 +149,7 @@ char *LogStatistics::uidToName(uid_t uid) { // Parse /data/system/packages.list uid_t userId = uid % AID_USER; char *name = android::uidToName(userId); const char *name = android::uidToName(userId); if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) { name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP)); } Loading @@ -161,17 +158,17 @@ char *LogStatistics::uidToName(uid_t uid) { } // report uid -> pid(s) -> pidToName if unique for(pidTable_t::iterator it = pidTable.begin(); it != pidTable.end(); ++it) { for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) { const PidEntry &entry = it->second; if (entry.getUid() == uid) { const char *n = entry.getName(); const char *nameTmp = entry.getName(); if (n) { if (nameTmp) { if (!name) { name = strdup(n); } else if (fast<strcmp>(name, n)) { free(name); name = strdup(nameTmp); } else if (fast<strcmp>(name, nameTmp)) { free(const_cast<char *>(name)); name = NULL; break; } Loading @@ -183,28 +180,152 @@ char *LogStatistics::uidToName(uid_t uid) { return name; } static std::string format_line( const std::string &name, const std::string &size, const std::string &pruned) { static const size_t pruned_len = 6; static const size_t total_len = 70 + pruned_len; std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const { bool isprune = worstUidEnabledForLogid(id); return formatLine(android::base::StringPrintf( name.c_str(), android_log_id_to_name(id)), std::string("Size"), std::string(isprune ? "Pruned" : "")) + formatLine(std::string("UID PACKAGE"), std::string("BYTES"), std::string(isprune ? "NUM" : "")); } std::string UidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getKey(); std::string name = android::base::StringPrintf("%u", uid); const char *nameTmp = stat.uidToName(uid); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } ssize_t drop_len = std::max(pruned.length() + 1, pruned_len); ssize_t size_len = std::max(size.length() + 1, total_len - name.length() - drop_len - 1); return formatLine(name, size, pruned); } std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("Pruned")) + formatLine(std::string(" PID/UID COMMAND LINE"), std::string("BYTES"), std::string("NUM")); } if (pruned.length()) { return android::base::StringPrintf("%s%*s%*s\n", name.c_str(), (int)size_len, size.c_str(), (int)drop_len, pruned.c_str()); std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", getKey(), uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); } else if ((nameTmp = stat.uidToName(uid))) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } return formatLine(name, size, pruned); } std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("Pruned")) + formatLine(std::string(" TID/UID COMM"), std::string("BYTES"), std::string("NUM")); } std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", getKey(), uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); } else if ((nameTmp = stat.uidToName(uid))) { // if we do not have a PID name, lets punt to try UID name? name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); // We tried, better to not have a name at all, we still // have TID/UID by number to report in any case. } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } return formatLine(name, size, pruned); } std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const { bool isprune = worstUidEnabledForLogid(id); return formatLine(name, std::string("Size"), std::string(isprune ? "Prune" : "")) + formatLine(std::string(" TAG/UID TAGNAME"), std::string("BYTES"), std::string(isprune ? "NUM" : "")); } std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const { std::string name; uid_t uid = getUid(); if (uid == (uid_t)-1) { name = android::base::StringPrintf("%7u", getKey()); } else { return android::base::StringPrintf("%s%*s\n", name.c_str(), (int)size_len, size.c_str()); name = android::base::StringPrintf("%7u/%u", getKey(), uid); } const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; return formatLine(name, size, pruned); } std::string LogStatistics::format(uid_t uid, unsigned int logMask) { std::string LogStatistics::format(uid_t uid, unsigned int logMask) const { static const unsigned short spaces_total = 19; // Report on total logging, current and for all time Loading @@ -227,7 +348,7 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { } spaces = 4; output += android::base::StringPrintf("\nTotal"); output += "\nTotal"; log_id_for_each(id) { if (!(logMask & (1 << id))) { Loading @@ -244,7 +365,7 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { } spaces = 6; output += android::base::StringPrintf("\nNow"); output += "\nNow"; log_id_for_each(id) { if (!(logMask & (1 << id))) { Loading @@ -266,245 +387,30 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { // Report on Chattiest std::string name; // Chattiest by application (UID) static const size_t maximum_sorted_entries = 32; log_id_for_each(id) { if (!(logMask & (1 << id))) { continue; } bool headerPrinted = false; std::unique_ptr<const UidEntry *[]> sorted = sort(maximum_sorted_entries, id); ssize_t index = -1; while ((index = uidTable_t::next(index, sorted, maximum_sorted_entries)) >= 0) { const UidEntry *entry = sorted[index]; uid_t u = entry->getKey(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name; if (uid == AID_ROOT) { name = android::base::StringPrintf( "Chattiest UIDs in %s log buffer:", android_log_id_to_name(id)); } else { name = android::base::StringPrintf( "Logging for your UID in %s log buffer:", android_log_id_to_name(id)); } std::string size = "Size"; std::string pruned = "Pruned"; if (!worstUidEnabledForLogid(id)) { pruned = ""; } output += format_line(name, size, pruned); name = "UID PACKAGE"; size = "BYTES"; pruned = "LINES"; if (!worstUidEnabledForLogid(id)) { pruned = ""; } output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%u", u); char *n = uidToName(u); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n); free(n); } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } } if (enable) { // Pid table bool headerPrinted = false; std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = pidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const PidEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name; if (uid == AID_ROOT) { name = android::base::StringPrintf("Chattiest PIDs:"); } else { name = android::base::StringPrintf("Logging for this PID:"); } std::string size = "Size"; std::string pruned = "Pruned"; output += format_line(name, size, pruned); name = " PID/UID COMMAND LINE"; size = "BYTES"; pruned = "LINES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%5u/%u", entry->getKey(), u); const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); } else { char *un = uidToName(u); if (un) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); free(un); } } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:" : "Logging for your UID in %s log buffer:"; output += uidTable[id].format(*this, uid, name, id); } if (enable) { // Tid table bool headerPrinted = false; // sort() returns list of references, unique_ptr makes sure self-delete std::unique_ptr<const TidEntry *[]> sorted = tidTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = tidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const TidEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { // Only print header if we have table to print output += android::base::StringPrintf("\n\n"); std::string name = "Chattiest TIDs:"; std::string size = "Size"; std::string pruned = "Pruned"; output += format_line(name, size, pruned); name = " TID/UID COMM"; size = "BYTES"; pruned = "LINES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%5u/%u", entry->getKey(), u); const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); } else { // if we do not have a PID name, lets punt to try UID name? char *un = uidToName(u); if (un) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); free(un); } // We tried, better to not have a name at all, we still // have TID/UID by number to report in any case. } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:"; output += pidTable.format(*this, uid, name); name = "Chattiest TIDs:"; output += tidTable.format(*this, uid, name); } if (enable && (logMask & (1 << LOG_ID_EVENTS))) { // Tag table bool headerPrinted = false; std::unique_ptr<const TagEntry *[]> sorted = tagTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = tagTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const TagEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } std::string pruned = ""; if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name = "Chattiest events log buffer TAGs:"; std::string size = "Size"; output += format_line(name, size, pruned); name = " TAG/UID TAGNAME"; size = "BYTES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name; if (u == (uid_t)-1) { name = android::base::StringPrintf("%7u", entry->getKey()); } else { name = android::base::StringPrintf("%7u/%u", entry->getKey(), u); } const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", n); } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); output += format_line(name, size, pruned); } name = "Chattiest events log buffer TAGs:"; output += tagTable.format(*this, uid, name, LOG_ID_EVENTS); } return output; Loading Loading @@ -536,8 +442,10 @@ uid_t LogStatistics::pidToUid(pid_t pid) { } // caller must free character string char *LogStatistics::pidToName(pid_t pid) { const char *name = pidTable.add(pid)->second.getName(); const char *LogStatistics::pidToName(pid_t pid) const { // An inconvenient truth ... getName() can alter the object pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable); const char *name = writablePidTable.add(pid)->second.getName(); if (!name) { return NULL; } Loading Loading
logd/LogAudit.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ int LogAudit::logPrint(const char *fmt, ...) { static const char comm_str[] = " comm=\""; const char *comm = strstr(str, comm_str); const char *estr = str + strlen(str); char *commfree = NULL; const char *commfree = NULL; if (comm) { estr = comm; comm += sizeof(comm_str) - 1; Loading Loading @@ -231,7 +231,7 @@ int LogAudit::logPrint(const char *fmt, ...) { // end scope for main buffer } free(commfree); free(const_cast<char *>(commfree)); free(str); if (notify) { Loading
logd/LogBuffer.h +2 −2 Original line number Diff line number Diff line Loading @@ -78,9 +78,9 @@ public: std::string formatPrune() { return mPrune.format(); } // helper must be protected directly or implicitly by lock()/unlock() char *pidToName(pid_t pid) { return stats.pidToName(pid); } const char *pidToName(pid_t pid) { return stats.pidToName(pid); } uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); } char *uidToName(uid_t uid) { return stats.uidToName(uid); } const char *uidToName(uid_t uid) { return stats.uidToName(uid); } void lock() { pthread_mutex_lock(&mLogElementsLock); } void unlock() { pthread_mutex_unlock(&mLogElementsLock); } Loading
logd/LogBufferElement.cpp +23 −22 Original line number Diff line number Diff line Loading @@ -113,9 +113,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, static const char format_uid[] = "uid=%u%s%s expire %u line%s"; parent->lock(); char *name = parent->uidToName(mUid); const char *name = parent->uidToName(mUid); parent->unlock(); char *commName = android::tidToName(mTid); const char *commName = android::tidToName(mTid); if (!commName && (mTid != mPid)) { commName = android::tidToName(mPid); } Loading @@ -128,28 +128,28 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, size_t len = strlen(name + 1); if (!strncmp(name + 1, commName + 1, len)) { if (commName[len + 1] == '\0') { free(commName); free(const_cast<char *>(commName)); commName = NULL; } else { free(name); free(const_cast<char *>(name)); name = NULL; } } } if (name) { char *p = NULL; asprintf(&p, "(%s)", name); if (p) { free(name); name = p; char *buf = NULL; asprintf(&buf, "(%s)", name); if (buf) { free(const_cast<char *>(name)); name = buf; } } if (commName) { char *p = NULL; asprintf(&p, " %s", commName); if (p) { free(commName); commName = p; char *buf = NULL; asprintf(&buf, " %s", commName); if (buf) { free(const_cast<char *>(commName)); commName = buf; } } // identical to below to calculate the buffer size required Loading @@ -166,18 +166,19 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, buffer = static_cast<char *>(calloc(1, hdrLen + len + 1)); if (!buffer) { free(name); free(commName); free(const_cast<char *>(name)); free(const_cast<char *>(commName)); return 0; } size_t retval = hdrLen + len; if (mLogId == LOG_ID_EVENTS) { android_log_event_string_t *e = reinterpret_cast<android_log_event_string_t *>(buffer); android_log_event_string_t *event = reinterpret_cast<android_log_event_string_t *>(buffer); e->header.tag = htole32(LOGD_LOG_TAG); e->type = EVENT_TYPE_STRING; e->length = htole32(len); event->header.tag = htole32(LOGD_LOG_TAG); event->type = EVENT_TYPE_STRING; event->length = htole32(len); } else { ++retval; buffer[0] = ANDROID_LOG_INFO; Loading @@ -187,8 +188,8 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "", commName ? commName : "", mDropped, (mDropped > 1) ? "s" : ""); free(name); free(commName); free(const_cast<char *>(name)); free(const_cast<char *>(commName)); return retval; } Loading
logd/LogStatistics.cpp +190 −282 Original line number Diff line number Diff line Loading @@ -14,15 +14,12 @@ * limitations under the License. */ #include <algorithm> // std::max #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <base/stringprintf.h> #include <log/logger.h> #include <private/android_filesystem_config.h> #include "LogStatistics.h" Loading Loading @@ -63,9 +60,9 @@ char *pidToName(pid_t pid) { } void LogStatistics::add(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::add(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] += size; ++mElements[log_id]; Loading @@ -76,24 +73,24 @@ void LogStatistics::add(LogBufferElement *e) { return; } uidTable[log_id].add(e->getUid(), e); uidTable[log_id].add(element->getUid(), element); if (!enable) { return; } pidTable.add(e->getPid(), e); tidTable.add(e->getTid(), e); pidTable.add(element->getPid(), element); tidTable.add(element->getTid(), element); uint32_t tag = e->getTag(); uint32_t tag = element->getTag(); if (tag) { tagTable.add(tag, e); tagTable.add(tag, element); } } void LogStatistics::subtract(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::subtract(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] -= size; --mElements[log_id]; Loading @@ -101,40 +98,40 @@ void LogStatistics::subtract(LogBufferElement *e) { return; } uidTable[log_id].subtract(e->getUid(), e); uidTable[log_id].subtract(element->getUid(), element); if (!enable) { return; } pidTable.subtract(e->getPid(), e); tidTable.subtract(e->getTid(), e); pidTable.subtract(element->getPid(), element); tidTable.subtract(element->getTid(), element); uint32_t tag = e->getTag(); uint32_t tag = element->getTag(); if (tag) { tagTable.subtract(tag, e); tagTable.subtract(tag, element); } } // Atomically set an entry to drop // entry->setDropped(1) must follow this call, caller should do this explicitly. void LogStatistics::drop(LogBufferElement *e) { log_id_t log_id = e->getLogId(); unsigned short size = e->getMsgLen(); void LogStatistics::drop(LogBufferElement *element) { log_id_t log_id = element->getLogId(); unsigned short size = element->getMsgLen(); mSizes[log_id] -= size; uidTable[log_id].drop(e->getUid(), e); uidTable[log_id].drop(element->getUid(), element); if (!enable) { return; } pidTable.drop(e->getPid(), e); tidTable.drop(e->getTid(), e); pidTable.drop(element->getPid(), element); tidTable.drop(element->getTid(), element); } // caller must own and free character string char *LogStatistics::uidToName(uid_t uid) { const char *LogStatistics::uidToName(uid_t uid) const { // Local hard coded favourites if (uid == AID_LOGD) { return strdup("auditd"); Loading @@ -152,7 +149,7 @@ char *LogStatistics::uidToName(uid_t uid) { // Parse /data/system/packages.list uid_t userId = uid % AID_USER; char *name = android::uidToName(userId); const char *name = android::uidToName(userId); if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) { name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP)); } Loading @@ -161,17 +158,17 @@ char *LogStatistics::uidToName(uid_t uid) { } // report uid -> pid(s) -> pidToName if unique for(pidTable_t::iterator it = pidTable.begin(); it != pidTable.end(); ++it) { for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) { const PidEntry &entry = it->second; if (entry.getUid() == uid) { const char *n = entry.getName(); const char *nameTmp = entry.getName(); if (n) { if (nameTmp) { if (!name) { name = strdup(n); } else if (fast<strcmp>(name, n)) { free(name); name = strdup(nameTmp); } else if (fast<strcmp>(name, nameTmp)) { free(const_cast<char *>(name)); name = NULL; break; } Loading @@ -183,28 +180,152 @@ char *LogStatistics::uidToName(uid_t uid) { return name; } static std::string format_line( const std::string &name, const std::string &size, const std::string &pruned) { static const size_t pruned_len = 6; static const size_t total_len = 70 + pruned_len; std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const { bool isprune = worstUidEnabledForLogid(id); return formatLine(android::base::StringPrintf( name.c_str(), android_log_id_to_name(id)), std::string("Size"), std::string(isprune ? "Pruned" : "")) + formatLine(std::string("UID PACKAGE"), std::string("BYTES"), std::string(isprune ? "NUM" : "")); } std::string UidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getKey(); std::string name = android::base::StringPrintf("%u", uid); const char *nameTmp = stat.uidToName(uid); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } ssize_t drop_len = std::max(pruned.length() + 1, pruned_len); ssize_t size_len = std::max(size.length() + 1, total_len - name.length() - drop_len - 1); return formatLine(name, size, pruned); } std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("Pruned")) + formatLine(std::string(" PID/UID COMMAND LINE"), std::string("BYTES"), std::string("NUM")); } if (pruned.length()) { return android::base::StringPrintf("%s%*s%*s\n", name.c_str(), (int)size_len, size.c_str(), (int)drop_len, pruned.c_str()); std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", getKey(), uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); } else if ((nameTmp = stat.uidToName(uid))) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } return formatLine(name, size, pruned); } std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("Pruned")) + formatLine(std::string(" TID/UID COMM"), std::string("BYTES"), std::string("NUM")); } std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", getKey(), uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); } else if ((nameTmp = stat.uidToName(uid))) { // if we do not have a PID name, lets punt to try UID name? name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp); free(const_cast<char *>(nameTmp)); // We tried, better to not have a name at all, we still // have TID/UID by number to report in any case. } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; size_t dropped = getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } return formatLine(name, size, pruned); } std::string TagEntry::formatHeader(const std::string &name, log_id_t id) const { bool isprune = worstUidEnabledForLogid(id); return formatLine(name, std::string("Size"), std::string(isprune ? "Prune" : "")) + formatLine(std::string(" TAG/UID TAGNAME"), std::string("BYTES"), std::string(isprune ? "NUM" : "")); } std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const { std::string name; uid_t uid = getUid(); if (uid == (uid_t)-1) { name = android::base::StringPrintf("%7u", getKey()); } else { return android::base::StringPrintf("%s%*s\n", name.c_str(), (int)size_len, size.c_str()); name = android::base::StringPrintf("%7u/%u", getKey(), uid); } const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp); } std::string size = android::base::StringPrintf("%zu", getSizes()); std::string pruned = ""; return formatLine(name, size, pruned); } std::string LogStatistics::format(uid_t uid, unsigned int logMask) { std::string LogStatistics::format(uid_t uid, unsigned int logMask) const { static const unsigned short spaces_total = 19; // Report on total logging, current and for all time Loading @@ -227,7 +348,7 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { } spaces = 4; output += android::base::StringPrintf("\nTotal"); output += "\nTotal"; log_id_for_each(id) { if (!(logMask & (1 << id))) { Loading @@ -244,7 +365,7 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { } spaces = 6; output += android::base::StringPrintf("\nNow"); output += "\nNow"; log_id_for_each(id) { if (!(logMask & (1 << id))) { Loading @@ -266,245 +387,30 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) { // Report on Chattiest std::string name; // Chattiest by application (UID) static const size_t maximum_sorted_entries = 32; log_id_for_each(id) { if (!(logMask & (1 << id))) { continue; } bool headerPrinted = false; std::unique_ptr<const UidEntry *[]> sorted = sort(maximum_sorted_entries, id); ssize_t index = -1; while ((index = uidTable_t::next(index, sorted, maximum_sorted_entries)) >= 0) { const UidEntry *entry = sorted[index]; uid_t u = entry->getKey(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name; if (uid == AID_ROOT) { name = android::base::StringPrintf( "Chattiest UIDs in %s log buffer:", android_log_id_to_name(id)); } else { name = android::base::StringPrintf( "Logging for your UID in %s log buffer:", android_log_id_to_name(id)); } std::string size = "Size"; std::string pruned = "Pruned"; if (!worstUidEnabledForLogid(id)) { pruned = ""; } output += format_line(name, size, pruned); name = "UID PACKAGE"; size = "BYTES"; pruned = "LINES"; if (!worstUidEnabledForLogid(id)) { pruned = ""; } output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%u", u); char *n = uidToName(u); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n); free(n); } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } } if (enable) { // Pid table bool headerPrinted = false; std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = pidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const PidEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name; if (uid == AID_ROOT) { name = android::base::StringPrintf("Chattiest PIDs:"); } else { name = android::base::StringPrintf("Logging for this PID:"); } std::string size = "Size"; std::string pruned = "Pruned"; output += format_line(name, size, pruned); name = " PID/UID COMMAND LINE"; size = "BYTES"; pruned = "LINES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%5u/%u", entry->getKey(), u); const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); } else { char *un = uidToName(u); if (un) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); free(un); } } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:" : "Logging for your UID in %s log buffer:"; output += uidTable[id].format(*this, uid, name, id); } if (enable) { // Tid table bool headerPrinted = false; // sort() returns list of references, unique_ptr makes sure self-delete std::unique_ptr<const TidEntry *[]> sorted = tidTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = tidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const TidEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } if (!headerPrinted) { // Only print header if we have table to print output += android::base::StringPrintf("\n\n"); std::string name = "Chattiest TIDs:"; std::string size = "Size"; std::string pruned = "Pruned"; output += format_line(name, size, pruned); name = " TID/UID COMM"; size = "BYTES"; pruned = "LINES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name = android::base::StringPrintf("%5u/%u", entry->getKey(), u); const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); } else { // if we do not have a PID name, lets punt to try UID name? char *un = uidToName(u); if (un) { name += android::base::StringPrintf( "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); free(un); } // We tried, better to not have a name at all, we still // have TID/UID by number to report in any case. } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); std::string pruned = ""; size_t dropped = entry->getDropped(); if (dropped) { pruned = android::base::StringPrintf("%zu", dropped); } output += format_line(name, size, pruned); } name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:"; output += pidTable.format(*this, uid, name); name = "Chattiest TIDs:"; output += tidTable.format(*this, uid, name); } if (enable && (logMask & (1 << LOG_ID_EVENTS))) { // Tag table bool headerPrinted = false; std::unique_ptr<const TagEntry *[]> sorted = tagTable.sort(maximum_sorted_entries); ssize_t index = -1; while ((index = tagTable.next(index, sorted, maximum_sorted_entries)) >= 0) { const TagEntry *entry = sorted[index]; uid_t u = entry->getUid(); if ((uid != AID_ROOT) && (u != uid)) { continue; } std::string pruned = ""; if (!headerPrinted) { output += android::base::StringPrintf("\n\n"); std::string name = "Chattiest events log buffer TAGs:"; std::string size = "Size"; output += format_line(name, size, pruned); name = " TAG/UID TAGNAME"; size = "BYTES"; output += format_line(name, size, pruned); headerPrinted = true; } std::string name; if (u == (uid_t)-1) { name = android::base::StringPrintf("%7u", entry->getKey()); } else { name = android::base::StringPrintf("%7u/%u", entry->getKey(), u); } const char *n = entry->getName(); if (n) { name += android::base::StringPrintf( "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", n); } std::string size = android::base::StringPrintf("%zu", entry->getSizes()); output += format_line(name, size, pruned); } name = "Chattiest events log buffer TAGs:"; output += tagTable.format(*this, uid, name, LOG_ID_EVENTS); } return output; Loading Loading @@ -536,8 +442,10 @@ uid_t LogStatistics::pidToUid(pid_t pid) { } // caller must free character string char *LogStatistics::pidToName(pid_t pid) { const char *name = pidTable.add(pid)->second.getName(); const char *LogStatistics::pidToName(pid_t pid) const { // An inconvenient truth ... getName() can alter the object pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable); const char *name = writablePidTable.add(pid)->second.getName(); if (!name) { return NULL; } Loading