blob: 32f641b4e22ab161e04b943dafeb81d8aa7da4bb [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2012-2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tom Cherry64e90162020-05-07 14:44:43 -070017#include "LogBufferElement.h"
18
Mark Salyzyn21fb7e02015-04-20 07:26:27 -070019#include <ctype.h>
Mark Salyzynab0dcf62015-03-16 12:04:09 -070020#include <endian.h>
Mark Salyzyn21fb7e02015-04-20 07:26:27 -070021#include <fcntl.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080022#include <stdio.h>
23#include <string.h>
24#include <time.h>
25#include <unistd.h>
26
Tom Cherryc5c6d7d2020-04-17 09:38:55 -070027#include <log/log_read.h>
Mark Salyzynab0dcf62015-03-16 12:04:09 -070028#include <private/android_logger.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080029
Mark Salyzynab0dcf62015-03-16 12:04:09 -070030#include "LogCommand.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080031#include "LogReader.h"
Tom Cherryd5b38382020-05-12 13:16:41 -070032#include "LogStatistics.h"
Mark Salyzyn2ad0bd02016-02-23 08:55:43 -080033#include "LogUtils.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080034
Tom Cherry10d086e2019-08-21 14:16:34 -070035const uint64_t LogBufferElement::FLUSH_ERROR(0);
Mark Salyzynee49c6a2015-06-12 14:59:42 -070036atomic_int_fast64_t LogBufferElement::sequence(1);
Mark Salyzyn0175b072014-02-26 09:50:16 -080037
Tom Cherry10d086e2019-08-21 14:16:34 -070038LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
39 pid_t tid, const char* msg, uint16_t len)
Mark Salyzyn501c3732017-03-10 14:31:54 -080040 : mUid(uid),
41 mPid(pid),
42 mTid(tid),
Tom Cherry10d086e2019-08-21 14:16:34 -070043 mSequence(sequence.fetch_add(1, memory_order_relaxed)),
Mark Salyzyn501c3732017-03-10 14:31:54 -080044 mRealTime(realtime),
45 mMsgLen(len),
Christopher Ferris74e74f92017-08-02 17:54:27 -070046 mLogId(log_id),
47 mDropped(false) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080048 mMsg = new char[len];
49 memcpy(mMsg, msg, len);
50}
51
Mark Salyzyn501c3732017-03-10 14:31:54 -080052LogBufferElement::LogBufferElement(const LogBufferElement& elem)
Christopher Ferris74e74f92017-08-02 17:54:27 -070053 : mUid(elem.mUid),
Mark Salyzyn501c3732017-03-10 14:31:54 -080054 mPid(elem.mPid),
55 mTid(elem.mTid),
Tom Cherry10d086e2019-08-21 14:16:34 -070056 mSequence(elem.mSequence),
Mark Salyzyn501c3732017-03-10 14:31:54 -080057 mRealTime(elem.mRealTime),
58 mMsgLen(elem.mMsgLen),
Christopher Ferris74e74f92017-08-02 17:54:27 -070059 mLogId(elem.mLogId),
60 mDropped(elem.mDropped) {
Jintao Zhu245fb362018-12-19 22:20:12 +080061 if (mDropped) {
Tom Cherrybe0f4ab2019-08-23 09:09:40 -070062 mTag = elem.getTag();
Jintao Zhu245fb362018-12-19 22:20:12 +080063 } else {
64 mMsg = new char[mMsgLen];
65 memcpy(mMsg, elem.mMsg, mMsgLen);
66 }
Mark Salyzyna2c02222016-12-13 10:31:29 -080067}
68
Mark Salyzyn0175b072014-02-26 09:50:16 -080069LogBufferElement::~LogBufferElement() {
Tom Cherrybe0f4ab2019-08-23 09:09:40 -070070 if (!mDropped) {
71 delete[] mMsg;
72 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080073}
74
Christopher Ferris74e74f92017-08-02 17:54:27 -070075uint32_t LogBufferElement::getTag() const {
Tom Cherrybe0f4ab2019-08-23 09:09:40 -070076 // Binary buffers have no tag.
77 if (!isBinary()) {
78 return 0;
79 }
80
81 // Dropped messages store the tag in place of mMsg.
82 if (mDropped) {
83 return mTag;
84 }
85
86 // For non-dropped messages, we get the tag from the message header itself.
87 if (mMsgLen < sizeof(android_event_header_t)) {
88 return 0;
89 }
90
91 return reinterpret_cast<const android_event_header_t*>(mMsg)->tag;
Christopher Ferris74e74f92017-08-02 17:54:27 -070092}
93
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -070094uint16_t LogBufferElement::setDropped(uint16_t value) {
Tom Cherrybe0f4ab2019-08-23 09:09:40 -070095 if (mDropped) {
96 return mDroppedCount = value;
Christopher Ferris74e74f92017-08-02 17:54:27 -070097 }
Tom Cherrybe0f4ab2019-08-23 09:09:40 -070098
99 // The tag information is saved in mMsg data, which is in a union with mTag, used after mDropped
100 // is set to true. Therefore we save the tag value aside, delete mMsg, then set mTag to the tag
101 // value in its place.
102 auto old_tag = getTag();
103 delete[] mMsg;
104 mMsg = nullptr;
105
106 mTag = old_tag;
Christopher Ferris74e74f92017-08-02 17:54:27 -0700107 mDropped = true;
108 return mDroppedCount = value;
109}
110
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700111// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800112char* android::tidToName(pid_t tid) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700113 char* retval = nullptr;
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700114 char buffer[256];
115 snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
116 int fd = open(buffer, O_RDONLY);
117 if (fd >= 0) {
118 ssize_t ret = read(fd, buffer, sizeof(buffer));
119 if (ret >= (ssize_t)sizeof(buffer)) {
120 ret = sizeof(buffer) - 1;
121 }
122 while ((ret > 0) && isspace(buffer[ret - 1])) {
123 --ret;
124 }
125 if (ret > 0) {
126 buffer[ret] = '\0';
127 retval = strdup(buffer);
128 }
129 close(fd);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700130 }
131
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700132 // if nothing for comm, check out cmdline
Mark Salyzyn501c3732017-03-10 14:31:54 -0800133 char* name = android::pidToName(tid);
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700134 if (!retval) {
135 retval = name;
Yi Kongc8d09dd2018-07-13 17:39:22 -0700136 name = nullptr;
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700137 }
138
139 // check if comm is truncated, see if cmdline has full representation
140 if (name) {
141 // impossible for retval to be NULL if name not NULL
142 size_t retval_len = strlen(retval);
143 size_t name_len = strlen(name);
144 // KISS: ToDo: Only checks prefix truncated, not suffix, or both
Mark Salyzyn501c3732017-03-10 14:31:54 -0800145 if ((retval_len < name_len) &&
146 !fastcmp<strcmp>(retval, name + name_len - retval_len)) {
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700147 free(retval);
148 retval = name;
149 } else {
150 free(name);
151 }
152 }
153 return retval;
154}
155
156// assumption: mMsg == NULL
Tom Cherry64e90162020-05-07 14:44:43 -0700157size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* stats,
Mark Salyzyn501c3732017-03-10 14:31:54 -0800158 bool lastSame) {
Mark Salyzyn047cc072015-06-04 13:35:30 -0700159 static const char tag[] = "chatty";
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700160
Mark Salyzyn501c3732017-03-10 14:31:54 -0800161 if (!__android_log_is_loggable_len(ANDROID_LOG_INFO, tag, strlen(tag),
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700162 ANDROID_LOG_VERBOSE)) {
Mark Salyzyne59c4692014-10-02 13:07:05 -0700163 return 0;
164 }
165
Mark Salyzynb5b87962017-01-23 14:20:31 -0800166 static const char format_uid[] = "uid=%u%s%s %s %u line%s";
Tom Cherry64e90162020-05-07 14:44:43 -0700167 const char* name = stats->UidToName(mUid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800168 const char* commName = android::tidToName(mTid);
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700169 if (!commName && (mTid != mPid)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700170 commName = android::tidToName(mPid);
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700171 }
172 if (!commName) {
Tom Cherry64e90162020-05-07 14:44:43 -0700173 commName = stats->PidToName(mPid);
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700174 }
Mark Salyzynddda2122015-10-02 09:22:52 -0700175 if (name && name[0] && commName && (name[0] == commName[0])) {
176 size_t len = strlen(name + 1);
177 if (!strncmp(name + 1, commName + 1, len)) {
178 if (commName[len + 1] == '\0') {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800179 free(const_cast<char*>(commName));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700180 commName = nullptr;
Mark Salyzynddda2122015-10-02 09:22:52 -0700181 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800182 free(const_cast<char*>(name));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700183 name = nullptr;
Mark Salyzynddda2122015-10-02 09:22:52 -0700184 }
Mark Salyzyn047cc072015-06-04 13:35:30 -0700185 }
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700186 }
187 if (name) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700188 char* buf = nullptr;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700189 asprintf(&buf, "(%s)", name);
190 if (buf) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800191 free(const_cast<char*>(name));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700192 name = buf;
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700193 }
194 }
195 if (commName) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700196 char* buf = nullptr;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700197 asprintf(&buf, " %s", commName);
198 if (buf) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800199 free(const_cast<char*>(commName));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700200 commName = buf;
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700201 }
202 }
203 // identical to below to calculate the buffer size required
Mark Salyzynb5b87962017-01-23 14:20:31 -0800204 const char* type = lastSame ? "identical" : "expire";
Yi Kongc8d09dd2018-07-13 17:39:22 -0700205 size_t len = snprintf(nullptr, 0, format_uid, mUid, name ? name : "",
Christopher Ferris74e74f92017-08-02 17:54:27 -0700206 commName ? commName : "", type, getDropped(),
207 (getDropped() > 1) ? "s" : "");
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700208
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700209 size_t hdrLen;
Mark Salyzyn60636fa2016-10-24 16:22:17 -0700210 if (isBinary()) {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700211 hdrLen = sizeof(android_log_event_string_t);
212 } else {
213 hdrLen = 1 + sizeof(tag);
214 }
215
Mark Salyzyn501c3732017-03-10 14:31:54 -0800216 buffer = static_cast<char*>(calloc(1, hdrLen + len + 1));
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700217 if (!buffer) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800218 free(const_cast<char*>(name));
219 free(const_cast<char*>(commName));
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700220 return 0;
221 }
222
223 size_t retval = hdrLen + len;
Mark Salyzyn60636fa2016-10-24 16:22:17 -0700224 if (isBinary()) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800225 android_log_event_string_t* event =
226 reinterpret_cast<android_log_event_string_t*>(buffer);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700227
Mark Salyzyn47684ca2016-07-15 10:19:16 -0700228 event->header.tag = htole32(CHATTY_LOG_TAG);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700229 event->type = EVENT_TYPE_STRING;
230 event->length = htole32(len);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700231 } else {
232 ++retval;
233 buffer[0] = ANDROID_LOG_INFO;
234 strcpy(buffer + 1, tag);
235 }
236
Mark Salyzyn21fb7e02015-04-20 07:26:27 -0700237 snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
Christopher Ferris74e74f92017-08-02 17:54:27 -0700238 commName ? commName : "", type, getDropped(),
239 (getDropped() > 1) ? "s" : "");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800240 free(const_cast<char*>(name));
241 free(const_cast<char*>(commName));
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700242
243 return retval;
244}
245
Tom Cherry64e90162020-05-07 14:44:43 -0700246uint64_t LogBufferElement::flushTo(SocketClient* reader, LogStatistics* stats, bool lastSame) {
Tom Cherry441054a2019-10-15 16:53:11 -0700247 struct logger_entry entry = {};
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700248
Tom Cherry441054a2019-10-15 16:53:11 -0700249 entry.hdr_size = sizeof(struct logger_entry);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800250 entry.lid = mLogId;
251 entry.pid = mPid;
Mark Salyzynb992d0d2014-03-20 16:09:38 -0700252 entry.tid = mTid;
Mark Salyzyn7b873652015-12-03 15:38:35 -0800253 entry.uid = mUid;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800254 entry.sec = mRealTime.tv_sec;
255 entry.nsec = mRealTime.tv_nsec;
256
257 struct iovec iovec[2];
258 iovec[0].iov_base = &entry;
Mark Salyzyn7b873652015-12-03 15:38:35 -0800259 iovec[0].iov_len = entry.hdr_size;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700260
Yi Kongc8d09dd2018-07-13 17:39:22 -0700261 char* buffer = nullptr;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700262
Christopher Ferris74e74f92017-08-02 17:54:27 -0700263 if (mDropped) {
Tom Cherry64e90162020-05-07 14:44:43 -0700264 entry.len = populateDroppedMessage(buffer, stats, lastSame);
Tom Cherry10d086e2019-08-21 14:16:34 -0700265 if (!entry.len) return mSequence;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700266 iovec[1].iov_base = buffer;
267 } else {
268 entry.len = mMsgLen;
269 iovec[1].iov_base = mMsg;
270 }
271 iovec[1].iov_len = entry.len;
272
Tom Cherry10d086e2019-08-21 14:16:34 -0700273 uint64_t retval = reader->sendDatav(iovec, 1 + (entry.len != 0)) ? FLUSH_ERROR : mSequence;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700274
Mark Salyzyn501c3732017-03-10 14:31:54 -0800275 if (buffer) free(buffer);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800276
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700277 return retval;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800278}