xref: /aosp_15_r20/system/logging/logd/LogBufferElement.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2012-2014 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker  *
4*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker  *
8*598139dcSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker  *
10*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker  */
16*598139dcSAndroid Build Coastguard Worker 
17*598139dcSAndroid Build Coastguard Worker #include "LogBufferElement.h"
18*598139dcSAndroid Build Coastguard Worker 
19*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
20*598139dcSAndroid Build Coastguard Worker #include <endian.h>
21*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
22*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
23*598139dcSAndroid Build Coastguard Worker #include <string.h>
24*598139dcSAndroid Build Coastguard Worker #include <time.h>
25*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
26*598139dcSAndroid Build Coastguard Worker 
27*598139dcSAndroid Build Coastguard Worker #include <log/log_read.h>
28*598139dcSAndroid Build Coastguard Worker #include <private/android_logger.h>
29*598139dcSAndroid Build Coastguard Worker 
30*598139dcSAndroid Build Coastguard Worker #include "LogStatistics.h"
31*598139dcSAndroid Build Coastguard Worker #include "LogUtils.h"
32*598139dcSAndroid Build Coastguard Worker 
LogBufferElement(log_id_t log_id,log_time realtime,uid_t uid,pid_t pid,pid_t tid,uint64_t sequence,const char * msg,uint16_t len)33*598139dcSAndroid Build Coastguard Worker LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
34*598139dcSAndroid Build Coastguard Worker                                    pid_t tid, uint64_t sequence, const char* msg, uint16_t len)
35*598139dcSAndroid Build Coastguard Worker     : uid_(uid),
36*598139dcSAndroid Build Coastguard Worker       pid_(pid),
37*598139dcSAndroid Build Coastguard Worker       tid_(tid),
38*598139dcSAndroid Build Coastguard Worker       sequence_(sequence),
39*598139dcSAndroid Build Coastguard Worker       realtime_(realtime),
40*598139dcSAndroid Build Coastguard Worker       msg_len_(len),
41*598139dcSAndroid Build Coastguard Worker       log_id_(log_id) {
42*598139dcSAndroid Build Coastguard Worker     msg_ = new char[len];
43*598139dcSAndroid Build Coastguard Worker     memcpy(msg_, msg, len);
44*598139dcSAndroid Build Coastguard Worker }
45*598139dcSAndroid Build Coastguard Worker 
LogBufferElement(const LogBufferElement & elem)46*598139dcSAndroid Build Coastguard Worker LogBufferElement::LogBufferElement(const LogBufferElement& elem)
47*598139dcSAndroid Build Coastguard Worker     : uid_(elem.uid_),
48*598139dcSAndroid Build Coastguard Worker       pid_(elem.pid_),
49*598139dcSAndroid Build Coastguard Worker       tid_(elem.tid_),
50*598139dcSAndroid Build Coastguard Worker       sequence_(elem.sequence_),
51*598139dcSAndroid Build Coastguard Worker       realtime_(elem.realtime_),
52*598139dcSAndroid Build Coastguard Worker       msg_len_(elem.msg_len_),
53*598139dcSAndroid Build Coastguard Worker       log_id_(elem.log_id_) {
54*598139dcSAndroid Build Coastguard Worker     msg_ = new char[msg_len_];
55*598139dcSAndroid Build Coastguard Worker     memcpy(msg_, elem.msg_, msg_len_);
56*598139dcSAndroid Build Coastguard Worker }
57*598139dcSAndroid Build Coastguard Worker 
LogBufferElement(LogBufferElement && elem)58*598139dcSAndroid Build Coastguard Worker LogBufferElement::LogBufferElement(LogBufferElement&& elem) noexcept
59*598139dcSAndroid Build Coastguard Worker     : uid_(elem.uid_),
60*598139dcSAndroid Build Coastguard Worker       pid_(elem.pid_),
61*598139dcSAndroid Build Coastguard Worker       tid_(elem.tid_),
62*598139dcSAndroid Build Coastguard Worker       sequence_(elem.sequence_),
63*598139dcSAndroid Build Coastguard Worker       realtime_(elem.realtime_),
64*598139dcSAndroid Build Coastguard Worker       msg_len_(elem.msg_len_),
65*598139dcSAndroid Build Coastguard Worker       log_id_(elem.log_id_) {
66*598139dcSAndroid Build Coastguard Worker     msg_ = elem.msg_;
67*598139dcSAndroid Build Coastguard Worker     elem.msg_ = nullptr;
68*598139dcSAndroid Build Coastguard Worker }
69*598139dcSAndroid Build Coastguard Worker 
~LogBufferElement()70*598139dcSAndroid Build Coastguard Worker LogBufferElement::~LogBufferElement() {
71*598139dcSAndroid Build Coastguard Worker     delete[] msg_;
72*598139dcSAndroid Build Coastguard Worker }
73*598139dcSAndroid Build Coastguard Worker 
GetTag() const74*598139dcSAndroid Build Coastguard Worker uint32_t LogBufferElement::GetTag() const {
75*598139dcSAndroid Build Coastguard Worker     // Binary buffers have no tag.
76*598139dcSAndroid Build Coastguard Worker     if (!IsBinary(log_id())) {
77*598139dcSAndroid Build Coastguard Worker         return 0;
78*598139dcSAndroid Build Coastguard Worker     }
79*598139dcSAndroid Build Coastguard Worker     return MsgToTag(msg(), msg_len());
80*598139dcSAndroid Build Coastguard Worker }
81*598139dcSAndroid Build Coastguard Worker 
ToLogStatisticsElement() const82*598139dcSAndroid Build Coastguard Worker LogStatisticsElement LogBufferElement::ToLogStatisticsElement() const {
83*598139dcSAndroid Build Coastguard Worker     // Estimate the size of this element in the parent std::list<> by adding two void*'s
84*598139dcSAndroid Build Coastguard Worker     // corresponding to the next/prev pointers and aligning to 64 bit.
85*598139dcSAndroid Build Coastguard Worker     uint16_t element_in_list_size =
86*598139dcSAndroid Build Coastguard Worker             (sizeof(*this) + 2 * sizeof(void*) + sizeof(uint64_t) - 1) & -sizeof(uint64_t);
87*598139dcSAndroid Build Coastguard Worker     return LogStatisticsElement{
88*598139dcSAndroid Build Coastguard Worker             .uid = uid(),
89*598139dcSAndroid Build Coastguard Worker             .pid = pid(),
90*598139dcSAndroid Build Coastguard Worker             .tid = tid(),
91*598139dcSAndroid Build Coastguard Worker             .tag = GetTag(),
92*598139dcSAndroid Build Coastguard Worker             .realtime = realtime(),
93*598139dcSAndroid Build Coastguard Worker             .msg = msg(),
94*598139dcSAndroid Build Coastguard Worker             .msg_len = msg_len(),
95*598139dcSAndroid Build Coastguard Worker             .log_id = log_id(),
96*598139dcSAndroid Build Coastguard Worker             .total_len = static_cast<uint16_t>(element_in_list_size + msg_len()),
97*598139dcSAndroid Build Coastguard Worker     };
98*598139dcSAndroid Build Coastguard Worker }
99*598139dcSAndroid Build Coastguard Worker 
100*598139dcSAndroid Build Coastguard Worker // caller must own and free character string
tidToName(pid_t tid)101*598139dcSAndroid Build Coastguard Worker char* android::tidToName(pid_t tid) {
102*598139dcSAndroid Build Coastguard Worker     char* retval = nullptr;
103*598139dcSAndroid Build Coastguard Worker     char buffer[256];
104*598139dcSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
105*598139dcSAndroid Build Coastguard Worker     int fd = open(buffer, O_RDONLY | O_CLOEXEC);
106*598139dcSAndroid Build Coastguard Worker     if (fd >= 0) {
107*598139dcSAndroid Build Coastguard Worker         ssize_t ret = read(fd, buffer, sizeof(buffer));
108*598139dcSAndroid Build Coastguard Worker         if (ret >= (ssize_t)sizeof(buffer)) {
109*598139dcSAndroid Build Coastguard Worker             ret = sizeof(buffer) - 1;
110*598139dcSAndroid Build Coastguard Worker         }
111*598139dcSAndroid Build Coastguard Worker         while ((ret > 0) && isspace(buffer[ret - 1])) {
112*598139dcSAndroid Build Coastguard Worker             --ret;
113*598139dcSAndroid Build Coastguard Worker         }
114*598139dcSAndroid Build Coastguard Worker         if (ret > 0) {
115*598139dcSAndroid Build Coastguard Worker             buffer[ret] = '\0';
116*598139dcSAndroid Build Coastguard Worker             retval = strdup(buffer);
117*598139dcSAndroid Build Coastguard Worker         }
118*598139dcSAndroid Build Coastguard Worker         close(fd);
119*598139dcSAndroid Build Coastguard Worker     }
120*598139dcSAndroid Build Coastguard Worker 
121*598139dcSAndroid Build Coastguard Worker     // if nothing for comm, check out cmdline
122*598139dcSAndroid Build Coastguard Worker     char* name = android::pidToName(tid);
123*598139dcSAndroid Build Coastguard Worker     if (!retval) {
124*598139dcSAndroid Build Coastguard Worker         retval = name;
125*598139dcSAndroid Build Coastguard Worker         name = nullptr;
126*598139dcSAndroid Build Coastguard Worker     }
127*598139dcSAndroid Build Coastguard Worker 
128*598139dcSAndroid Build Coastguard Worker     // check if comm is truncated, see if cmdline has full representation
129*598139dcSAndroid Build Coastguard Worker     if (name) {
130*598139dcSAndroid Build Coastguard Worker         // impossible for retval to be NULL if name not NULL
131*598139dcSAndroid Build Coastguard Worker         size_t retval_len = strlen(retval);
132*598139dcSAndroid Build Coastguard Worker         size_t name_len = strlen(name);
133*598139dcSAndroid Build Coastguard Worker         // KISS: ToDo: Only checks prefix truncated, not suffix, or both
134*598139dcSAndroid Build Coastguard Worker         if ((retval_len < name_len) &&
135*598139dcSAndroid Build Coastguard Worker             !fastcmp<strcmp>(retval, name + name_len - retval_len)) {
136*598139dcSAndroid Build Coastguard Worker             free(retval);
137*598139dcSAndroid Build Coastguard Worker             retval = name;
138*598139dcSAndroid Build Coastguard Worker         } else {
139*598139dcSAndroid Build Coastguard Worker             free(name);
140*598139dcSAndroid Build Coastguard Worker         }
141*598139dcSAndroid Build Coastguard Worker     }
142*598139dcSAndroid Build Coastguard Worker     return retval;
143*598139dcSAndroid Build Coastguard Worker }
144*598139dcSAndroid Build Coastguard Worker 
FlushTo(LogWriter * writer)145*598139dcSAndroid Build Coastguard Worker bool LogBufferElement::FlushTo(LogWriter* writer) {
146*598139dcSAndroid Build Coastguard Worker     struct logger_entry entry = {};
147*598139dcSAndroid Build Coastguard Worker 
148*598139dcSAndroid Build Coastguard Worker     entry.hdr_size = sizeof(struct logger_entry);
149*598139dcSAndroid Build Coastguard Worker     entry.lid = log_id_;
150*598139dcSAndroid Build Coastguard Worker     entry.pid = pid_;
151*598139dcSAndroid Build Coastguard Worker     entry.tid = tid_;
152*598139dcSAndroid Build Coastguard Worker     entry.uid = uid_;
153*598139dcSAndroid Build Coastguard Worker     entry.sec = realtime_.tv_sec;
154*598139dcSAndroid Build Coastguard Worker     entry.nsec = realtime_.tv_nsec;
155*598139dcSAndroid Build Coastguard Worker     entry.len = msg_len_;
156*598139dcSAndroid Build Coastguard Worker 
157*598139dcSAndroid Build Coastguard Worker     return writer->Write(entry, msg_);
158*598139dcSAndroid Build Coastguard Worker }
159