xref: /aosp_15_r20/external/cronet/base/trace_event/trace_logging_minimal_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/trace_event/trace_logging_minimal_win.h"
6 
7 #include <evntrace.h>
8 
9 #include "base/check_op.h"
10 #include "base/logging.h"
11 #include "base/numerics/checked_math.h"
12 
13 TlmProvider::TlmProvider() noexcept = default;
14 
~TlmProvider()15 TlmProvider::~TlmProvider() {
16   Unregister();
17 }
18 
TlmProvider(const char * provider_name,const GUID & provider_guid,base::RepeatingCallback<void (EventControlCode)> on_updated_callback)19 TlmProvider::TlmProvider(const char* provider_name,
20                          const GUID& provider_guid,
21                          base::RepeatingCallback<void(EventControlCode)>
22                              on_updated_callback) noexcept {
23   ULONG status =
24       Register(provider_name, provider_guid, std::move(on_updated_callback));
25   LOG_IF(ERROR, status != ERROR_SUCCESS) << "Provider resistration failure";
26 }
27 
28 // Appends a nul-terminated string to a metadata block.
29 // Returns new meta_data_index value, or -1 for overflow.
AppendNameToMetadata(char * metadata,uint16_t metadata_size,uint16_t metadata_index,std::string_view name) const30 uint16_t TlmProvider::AppendNameToMetadata(
31     char* metadata,
32     uint16_t metadata_size,
33     uint16_t metadata_index,
34     std::string_view name) const noexcept {
35   uint16_t index = metadata_index;
36   DCHECK_LE(index, metadata_size);
37 
38   const size_t cch = name.size();
39   if (cch + 1 > static_cast<unsigned>(metadata_size - index)) {
40     return static_cast<uint16_t>(-1);
41   }
42 
43   memcpy(metadata + index, name.data(), cch);
44   metadata[index + cch] = 0;
45   index += static_cast<uint16_t>(cch) + 1;
46   return index;
47 }
48 
Unregister()49 void TlmProvider::Unregister() noexcept {
50   if (reg_handle_ == 0)
51     return;
52 
53   ULONG status = EventUnregister(reg_handle_);
54   LOG_IF(ERROR, status != ERROR_SUCCESS) << "Provider unregistration failure";
55   reg_handle_ = 0;
56   level_plus1_ = 0;
57 }
58 
Register(const char * provider_name,const GUID & provider_guid,base::RepeatingCallback<void (EventControlCode)> on_updated_callback)59 ULONG TlmProvider::Register(const char* provider_name,
60                             const GUID& provider_guid,
61                             base::RepeatingCallback<void(EventControlCode)>
62                                 on_updated_callback) noexcept {
63   // Calling Register when already registered is a fatal error.
64   CHECK_EQ(reg_handle_, 0ULL);
65 
66   // provider_metadata_ for tracelogging has the following format:
67   //     UINT16 metadata_size;
68   //     char NullTerminatedUtf8ProviderName[];
69   //     ( + optional extension data, not used here)
70 
71   // Append the provider name starting at offset 2 (skip MetadataSize).
72   provider_metadata_size_ = AppendNameToMetadata(
73       provider_metadata_, kMaxProviderMetadataSize, 2, provider_name);
74   if (provider_metadata_size_ > kMaxProviderMetadataSize)
75     return ERROR_BUFFER_OVERFLOW;
76 
77   // Fill in MetadataSize field at offset 0.
78   *reinterpret_cast<uint16_t*>(provider_metadata_) = provider_metadata_size_;
79 
80   on_updated_callback_ = std::move(on_updated_callback);
81   ULONG status =
82       EventRegister(&provider_guid, StaticEnableCallback, this, &reg_handle_);
83   if (status != ERROR_SUCCESS)
84     return status;
85 
86   // Best-effort, ignore failure.
87   return ::EventSetInformation(reg_handle_, EventProviderSetTraits,
88                                provider_metadata_, provider_metadata_size_);
89 }
90 
IsEnabled() const91 bool TlmProvider::IsEnabled() const noexcept {
92   return 0 < level_plus1_;
93 }
94 
IsEnabled(uint8_t level) const95 bool TlmProvider::IsEnabled(uint8_t level) const noexcept {
96   return level < level_plus1_;
97 }
98 
IsEnabled(uint8_t level,uint64_t keyword) const99 bool TlmProvider::IsEnabled(uint8_t level, uint64_t keyword) const noexcept {
100   return level < level_plus1_ && KeywordEnabled(keyword);
101 }
102 
IsEnabled(const EVENT_DESCRIPTOR & event_descriptor) const103 bool TlmProvider::IsEnabled(
104     const EVENT_DESCRIPTOR& event_descriptor) const noexcept {
105   return event_descriptor.Level < level_plus1_ &&
106          KeywordEnabled(event_descriptor.Keyword);
107 }
108 
StaticEnableCallback(const GUID * source_id,ULONG is_enabled,UCHAR level,ULONGLONG match_any_keyword,ULONGLONG match_all_keyword,PEVENT_FILTER_DESCRIPTOR filter_data,PVOID callback_context)109 void TlmProvider::StaticEnableCallback(const GUID* source_id,
110                                        ULONG is_enabled,
111                                        UCHAR level,
112                                        ULONGLONG match_any_keyword,
113                                        ULONGLONG match_all_keyword,
114                                        PEVENT_FILTER_DESCRIPTOR filter_data,
115                                        PVOID callback_context) {
116   if (!callback_context)
117     return;
118 
119   TlmProvider* provider = static_cast<TlmProvider*>(callback_context);
120   switch (is_enabled) {
121     case EVENT_CONTROL_CODE_DISABLE_PROVIDER:
122       provider->level_plus1_ = 0;
123       break;
124     case EVENT_CONTROL_CODE_ENABLE_PROVIDER:
125       provider->level_plus1_ =
126           level != 0 ? static_cast<unsigned>(level) + 1u : 256u;
127       break;
128   }
129   provider->keyword_any_ = match_any_keyword;
130   provider->keyword_all_ = match_all_keyword;
131 
132   if (provider->on_updated_callback_ &&
133       is_enabled <= static_cast<size_t>(EventControlCode::kHighest)) {
134     provider->on_updated_callback_.Run(
135         static_cast<EventControlCode>(is_enabled));
136   }
137 }
138 
EventBegin(char * metadata,std::string_view event_name) const139 uint16_t TlmProvider::EventBegin(char* metadata,
140                                  std::string_view event_name) const noexcept {
141   // EventMetadata for tracelogging has the following format
142   //     UINT16 MetadataSize;
143   //     BYTE SpecialFlags[]; // Not used, so always size 1.
144   //     char NullTerminatedUtf8EventName[];
145   //     ( + field definitions)
146 
147   uint16_t index = 2;  // Skip MetadataSize field.
148 
149   metadata[index] = 0;  // Set SpecialFlags[0] = 0.
150   index++;              // sizeof(SpecialFlags) == 1.
151 
152   index =
153       AppendNameToMetadata(metadata, kMaxEventMetadataSize, index, event_name);
154   return index;
155 }
156 
EventAddField(char * metadata,uint16_t * metadata_index,uint8_t in_type,uint8_t out_type,const char * field_name) const157 char TlmProvider::EventAddField(char* metadata,
158                                 uint16_t* metadata_index,
159                                 uint8_t in_type,
160                                 uint8_t out_type,
161                                 const char* field_name) const noexcept {
162   DCHECK_LT(in_type, 0x80);
163   DCHECK_LT(out_type, 0x80);
164 
165   // FieldDefinition =
166   //     char NullTerminatedUtf8FieldName[];
167   //     BYTE InType;
168   //     BYTE OutType; // Only present if high bit set in InType.
169   //     ( + optional extension data not used here)
170 
171   if (*metadata_index >= kMaxEventMetadataSize)
172     return 0;
173 
174   *metadata_index = AppendNameToMetadata(metadata, kMaxEventMetadataSize,
175                                          *metadata_index, field_name);
176   if (*metadata_index >= kMaxEventMetadataSize)
177     return 0;
178 
179   if (out_type == 0) {
180     // 1-byte encoding: inType + TlgOutNULL.
181     if (1 > kMaxEventMetadataSize - *metadata_index) {
182       *metadata_index = static_cast<uint16_t>(-1);
183       return 0;
184     }
185 
186     metadata[*metadata_index] = static_cast<char>(in_type);
187     *metadata_index += 1;
188     return 0;
189   }
190   // 2-byte encoding: in_type + out_type.
191   if (kMaxEventMetadataSize - *metadata_index < 2) {
192     *metadata_index = static_cast<uint16_t>(-1);
193     return 0;
194   }
195 
196   // Set high bit to indicate presence of OutType.
197   metadata[*metadata_index] = static_cast<char>(in_type | 0x80);
198   *metadata_index += 1;
199   metadata[*metadata_index] = static_cast<char>(out_type);
200   *metadata_index += 1;
201   return 0;
202 }
203 
EventEnd(char * metadata,uint16_t meta_data_index,EVENT_DATA_DESCRIPTOR * descriptors,uint32_t descriptors_index,const EVENT_DESCRIPTOR & event_descriptor) const204 ULONG TlmProvider::EventEnd(
205     char* metadata,
206     uint16_t meta_data_index,
207     EVENT_DATA_DESCRIPTOR* descriptors,
208     uint32_t descriptors_index,
209     const EVENT_DESCRIPTOR& event_descriptor) const noexcept {
210   if (meta_data_index > kMaxEventMetadataSize) {
211     return ERROR_BUFFER_OVERFLOW;
212   }
213 
214   // Fill in EventMetadata's MetadataSize field.
215   *reinterpret_cast<uint16_t*>(metadata) = meta_data_index;
216 
217   descriptors[0].Ptr = reinterpret_cast<ULONG_PTR>(provider_metadata_);
218   descriptors[0].Size = provider_metadata_size_;
219   descriptors[0].Reserved = EVENT_DATA_DESCRIPTOR_TYPE_PROVIDER_METADATA;
220 
221   descriptors[1].Ptr = reinterpret_cast<ULONG_PTR>(metadata);
222   descriptors[1].Size = meta_data_index;
223   descriptors[1].Reserved = EVENT_DATA_DESCRIPTOR_TYPE_EVENT_METADATA;
224 
225   return EventWrite(reg_handle_, &event_descriptor, descriptors_index,
226                     descriptors);
227 }
228 
KeywordEnabled(uint64_t keyword) const229 bool TlmProvider::KeywordEnabled(uint64_t keyword) const noexcept {
230   return keyword == 0 ||
231          ((keyword & keyword_any_) && (keyword & keyword_all_) == keyword_all_);
232 }
233 
TlmInt64Field(const char * name,const int64_t value)234 TlmInt64Field::TlmInt64Field(const char* name, const int64_t value) noexcept
235     : TlmFieldBase(name), value_(value) {
236   DCHECK_NE(Name(), nullptr);
237 }
Value() const238 int64_t TlmInt64Field::Value() const noexcept {
239   return value_;
240 }
FillEventDescriptor(EVENT_DATA_DESCRIPTOR * descriptors) const241 void TlmInt64Field::FillEventDescriptor(
242     EVENT_DATA_DESCRIPTOR* descriptors) const noexcept {
243   EventDataDescCreate(&descriptors[0], (void*)&value_, sizeof(value_));
244 }
245 
TlmUInt64Field(const char * name,const uint64_t value)246 TlmUInt64Field::TlmUInt64Field(const char* name, const uint64_t value) noexcept
247     : TlmFieldBase(name), value_(value) {
248   DCHECK_NE(Name(), nullptr);
249 }
Value() const250 uint64_t TlmUInt64Field::Value() const noexcept {
251   return value_;
252 }
FillEventDescriptor(EVENT_DATA_DESCRIPTOR * descriptors) const253 void TlmUInt64Field::FillEventDescriptor(
254     EVENT_DATA_DESCRIPTOR* descriptors) const noexcept {
255   EventDataDescCreate(&descriptors[0], (void*)&value_, sizeof(value_));
256 }
257 
TlmMbcsStringField(const char * name,const char * value)258 TlmMbcsStringField::TlmMbcsStringField(const char* name,
259                                        const char* value) noexcept
260     : TlmFieldBase(name), value_(value) {
261   DCHECK_NE(Name(), nullptr);
262   DCHECK_NE(value_, nullptr);
263 }
264 
Value() const265 const char* TlmMbcsStringField::Value() const noexcept {
266   return value_;
267 }
268 
FillEventDescriptor(EVENT_DATA_DESCRIPTOR * descriptors) const269 void TlmMbcsStringField::FillEventDescriptor(
270     EVENT_DATA_DESCRIPTOR* descriptors) const noexcept {
271   EventDataDescCreate(&descriptors[0], value_,
272                       base::checked_cast<ULONG>(strlen(value_) + 1));
273 }
274 
TlmUtf8StringField(const char * name,const char * value)275 TlmUtf8StringField::TlmUtf8StringField(const char* name,
276                                        const char* value) noexcept
277     : TlmFieldBase(name), value_(value) {
278   DCHECK_NE(Name(), nullptr);
279   DCHECK_NE(value_, nullptr);
280 }
281 
Value() const282 const char* TlmUtf8StringField::Value() const noexcept {
283   return value_;
284 }
285 
FillEventDescriptor(EVENT_DATA_DESCRIPTOR * descriptors) const286 void TlmUtf8StringField::FillEventDescriptor(
287     EVENT_DATA_DESCRIPTOR* descriptors) const noexcept {
288   EventDataDescCreate(&descriptors[0], value_,
289                       base::checked_cast<ULONG>(strlen(value_) + 1));
290 }
291