1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_TRACING_COMMON_ETW_CONSUMER_WIN_H_
#define COMPONENTS_TRACING_COMMON_ETW_CONSUMER_WIN_H_
#include <stdint.h>
#include <memory>
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/win/event_trace_consumer.h"
#include "components/tracing/common/active_processes_win.h"
#include "components/tracing/common/inclusion_policy_win.h"
#include "components/tracing/tracing_export.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
#include "third_party/perfetto/include/perfetto/tracing/trace_writer_base.h"
namespace perfetto::protos::pbzero {
class EtwTraceEvent;
class EtwTraceEventBundle;
} // namespace perfetto::protos::pbzero
namespace tracing {
// A consumer of events from the Windows system trace provider that emits
// corresponding Perfetto trace events. An instance may be constructed on any
// sequence. Its `ConsumeEvents()` method and its destructor must be called on
// the same sequence.
class TRACING_EXPORT EtwConsumer
: public base::win::EtwTraceConsumerBase<EtwConsumer> {
public:
// Receive events in the new EVENT_RECORD format.
static constexpr bool kEnableRecordMode = true;
// Do not convert timestampts to system time.
static constexpr bool kRawTimestamp = true;
// Constructs an instance that will consume ETW events on behalf of the client
// process identified by `client_pid` and emit Perfetto events via
// `trace_writer`.
EtwConsumer(base::ProcessId client_pid,
std::unique_ptr<perfetto::TraceWriterBase> trace_writer);
EtwConsumer(const EtwConsumer&) = delete;
EtwConsumer& operator=(const EtwConsumer&) = delete;
~EtwConsumer();
// Consumes ETW events; blocking the calling thread. Returns when the ETW
// trace session is stopped.
void ConsumeEvents();
// base::win::EtwTraceConsumerBase<>:
static void ProcessEventRecord(EVENT_RECORD* event_record);
static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer);
private:
friend class EtwConsumerTest;
// The type of a member function that handles an event originating from a
// specific provider.
using EventHandlerFunction =
void (EtwConsumer::*)(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data);
// Returns the size, in bytes, of a pointer-sized value in an event based on
// the `Flags` member of an event's `EVENT_HEADER`.
static size_t GetPointerSize(uint16_t event_header_flags);
// Per-provider event handlers. `ProcessEventRecord` dispatches to these based
// on the ProviderId in the record's EventHeader.
void HandleProcessEvent(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void HandleThreadEvent(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void HandleLostEvent(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void OnProcessStart(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void OnProcessEnd(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void OnThreadStart(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void OnThreadEnd(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
size_t pointer_size,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void OnThreadSetName(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Decodes a CSwitch Event and emits a Perfetto trace event; see
// https://learn.microsoft.com/en-us/windows/win32/etw/cswitch.
// Returns true on success, or false if `packet_data` is invalid.
bool DecodeCSwitchEvent(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Decodes a ReadyThread Event and emits a Perfetto trace event; see
// https://learn.microsoft.com/en-us/windows/win32/etw/readythread.
// Returns true on success, or false if `packet_data` is invalid.
bool DecodeReadyThreadEvent(const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context,
base::span<const uint8_t> packet_data)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Returns a new perfetto trace event to be emitted for an ETW event with a
// given event header. The timestamp and cpu fields of the returned event are
// prepopulated.
perfetto::protos::pbzero::EtwTraceEvent* MakeNextEvent(
const EVENT_HEADER& header,
const ETW_BUFFER_CONTEXT& buffer_context)
VALID_CONTEXT_REQUIRED(sequence_checker_);
const ActiveProcesses& active_processes() const { return active_processes_; }
ActiveProcesses active_processes_ GUARDED_BY_CONTEXT(sequence_checker_);
InclusionPolicy inclusion_policy_ GUARDED_BY_CONTEXT(sequence_checker_){
active_processes_};
std::unique_ptr<perfetto::TraceWriterBase> trace_writer_
GUARDED_BY_CONTEXT(sequence_checker_);
perfetto::TraceWriter::TracePacketHandle packet_handle_
GUARDED_BY_CONTEXT(sequence_checker_);
raw_ptr<perfetto::protos::pbzero::EtwTraceEventBundle> etw_events_
GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace tracing
#endif // COMPONENTS_TRACING_COMMON_ETW_CONSUMER_WIN_H_
|