1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hitrace_invoker.h"
17
18 #include <cstddef>
19 #include <cstdint>
20 #include <cinttypes>
21
22 #include "hilog/log_c.h"
23 #include "hilog/log_cpp.h"
24 #include "hitrace/trace.h"
25 #include "ipc_debug.h"
26 #include "log_tags.h"
27 #include "message_parcel.h"
28 #include "process_skeleton.h"
29 #include "sys_binder.h"
30
31 namespace OHOS {
32 // the value should be equal to the set of parcel
33 using namespace OHOS::HiviewDFX;
34 static const HiLogLabel TRACE_LABEL = { LOG_CORE, LOG_ID_IPC_BINDER_INVOKER, "BinderHiTrace" };
35
IsClientTraced(int32_t handle,uint32_t flags,const HiTraceId & traceId)36 bool HitraceInvoker::IsClientTraced(int32_t handle, uint32_t flags, const HiTraceId &traceId)
37 {
38 return (traceId.IsValid() && (handle != 0) &&
39 ((flags & TF_ONE_WAY) ? traceId.IsFlagEnabled(HITRACE_FLAG_INCLUDE_ASYNC) : true));
40 }
41
TraceClientSend(int32_t handle,uint32_t code,MessageParcel & data,uint32_t & flags,const HiTraceId & traceId)42 HiTraceId HitraceInvoker::TraceClientSend(int32_t handle, uint32_t code, MessageParcel &data, uint32_t &flags,
43 const HiTraceId &traceId)
44 {
45 HiTraceId childId = traceId;
46 bool isClientTraced = IsClientTraced(handle, flags, traceId);
47 if (isClientTraced) {
48 childId = HiTraceChain::CreateSpan();
49 // add childid to parcel data
50 uint8_t idBytes[HITRACE_ID_LEN];
51 size_t idLen = (size_t)(childId.ToBytes(idBytes, HITRACE_ID_LEN));
52 if (idLen != HITRACE_ID_LEN) {
53 ZLOGE(TRACE_LABEL, "idLen not correct");
54 return childId;
55 }
56
57 size_t oldWritePosition = data.GetWritePosition();
58 if (!data.WriteBuffer(idBytes, idLen)) {
59 ZLOGE(TRACE_LABEL, "Write idBytes fail");
60 // restore Parcel data
61 data.RewindWrite(oldWritePosition);
62 return childId;
63 }
64
65 // padded size of traceid
66 if (!data.WriteUint8(data.GetWritePosition() - oldWritePosition)) {
67 ZLOGE(TRACE_LABEL, "Write idLen fail");
68 // restore Parcel data
69 data.RewindWrite(oldWritePosition);
70 return childId;
71 }
72 // tracepoint: CS(Client Send)
73 std::u16string desc = data.GetInterfaceToken();
74 HiTraceChain::Tracepoint(HITRACE_TP_CS, childId, "%{public}s handle=%{public}d,code=%{public}u,desc=%{public}s",
75 (flags & TF_ONE_WAY) ? "ASYNC" : "SYNC", handle, code,
76 ProcessSkeleton::ConvertToSecureDesc(Str16ToStr8(desc)).c_str());
77 flags |= TF_HITRACE;
78 } else {
79 if (flags & TF_HITRACE) {
80 ZLOGW(TRACE_LABEL, "business set the error flags, traceid is invalid ");
81 flags &= ~(uint32_t)TF_HITRACE;
82 }
83 }
84 return childId;
85 }
86
TraceClientReceieve(int32_t handle,uint32_t code,uint32_t flags,const HiTraceId & traceId,const HiTraceId & childId)87 void HitraceInvoker::TraceClientReceieve(int32_t handle, uint32_t code, uint32_t flags, const HiTraceId &traceId,
88 const HiTraceId &childId)
89 {
90 if (!(flags & TF_HITRACE)) {
91 return;
92 }
93 bool isClientTraced = IsClientTraced(handle, flags, traceId);
94 if (isClientTraced) {
95 if (!(flags & TF_ONE_WAY)) {
96 // restore thread trace id
97 HiTraceChain::SetId(traceId);
98 // tracepoint: CR(Client Receive)
99 HiTraceChain::Tracepoint(HITRACE_TP_CR, childId,
100 "%{public}s handle=%{public}d,code=%{public}u", "SYNC", handle, code);
101 }
102 }
103 }
104
RecoveryDataAndFlag(Parcel & data,uint32_t & flags,size_t oldReadPosition,uint8_t idLen)105 void HitraceInvoker::RecoveryDataAndFlag(Parcel &data, uint32_t &flags, size_t oldReadPosition, uint8_t idLen)
106 {
107 if (data.GetDataSize() < (idLen + PADDED_SIZE_OF_PARCEL)) {
108 return;
109 }
110 // restore data
111 data.RewindRead(oldReadPosition);
112 // padded size(4 bytes) of uint8_t
113 data.SetDataSize(data.GetDataSize() - PADDED_SIZE_OF_PARCEL - idLen);
114 flags &= ~(uint32_t)TF_HITRACE;
115 }
116
TraceServerReceieve(uint64_t handle,uint32_t code,MessageParcel & data,uint32_t & flags)117 bool HitraceInvoker::TraceServerReceieve(uint64_t handle, uint32_t code, MessageParcel &data, uint32_t &flags)
118 {
119 bool isServerTraced = (flags & TF_HITRACE) != 0;
120 if (!isServerTraced) {
121 return isServerTraced;
122 }
123 size_t oldReadPosition = data.GetReadPosition();
124 // padded size(4 bytes) of uint8_t
125 if (data.GetDataSize() < PADDED_SIZE_OF_PARCEL) {
126 ZLOGE(TRACE_LABEL, "The size of the data packet is less than 4");
127 return false;
128 }
129 data.RewindRead(data.GetDataSize() - PADDED_SIZE_OF_PARCEL);
130 // the padded size of traceid
131 uint8_t idLen = data.ReadUint8();
132 if ((idLen >= sizeof(HiTraceIdStruct)) && (idLen <= (data.GetDataSize() - PADDED_SIZE_OF_PARCEL))) {
133 // padded size(4 bytes) of uint8_t
134 data.RewindRead(data.GetDataSize() - PADDED_SIZE_OF_PARCEL - idLen);
135 const uint8_t *idBytes = data.ReadUnpadBuffer(sizeof(HiTraceIdStruct));
136 if (idBytes == nullptr) {
137 ZLOGE(TRACE_LABEL, "idBytes is null");
138 isServerTraced = false;
139 RecoveryDataAndFlag(data, flags, oldReadPosition, idLen);
140 return isServerTraced;
141 }
142 HiTraceId traceId(idBytes, sizeof(HiTraceIdStruct));
143 HiTraceChain::SetId(traceId);
144 // tracepoint: SR(Server Receive)
145 data.RewindRead(oldReadPosition);
146 std::u16string desc = data.ReadInterfaceToken();
147 HiTraceChain::Tracepoint(HITRACE_TP_SR, traceId,
148 "%{public}s handle=%{public}" PRIu64 ",code=%{public}u,desc=%{public}s",
149 (flags & TF_ONE_WAY) ? "ASYNC" : "SYNC", handle, code,
150 ProcessSkeleton::ConvertToSecureDesc(Str16ToStr8(desc)).c_str());
151 }
152 RecoveryDataAndFlag(data, flags, oldReadPosition, idLen);
153
154 return isServerTraced;
155 }
156
TraceServerSend(uint64_t handle,uint32_t code,bool isServerTraced,uint32_t flags)157 void HitraceInvoker::TraceServerSend(uint64_t handle, uint32_t code, bool isServerTraced, uint32_t flags)
158 {
159 if (isServerTraced) {
160 // tracepoint: SS(Server Send)
161 HiTraceChain::Tracepoint(HITRACE_TP_SS, HiTraceChain::GetId(),
162 "%{public}s handle=%{public}" PRIu64 ",code=%{public}u",
163 (flags & TF_ONE_WAY) ? "ASYNC" : "SYNC", handle, code);
164 }
165 HiTraceChain::ClearId();
166 }
167 } // namespace OHOS
168