#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/trace_event/trace_log.h"
#include <cmath>
#include <limits>
#include <memory>
#include <string_view>
#include <unordered_set>
#include <utility>
#include "base/auto_reset.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/debug/leak_annotations.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/stack_allocated.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process.h"
#include "base/process/process_metrics.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/current_thread.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_id_name_manager.h"
#include "base/time/time.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "base/tracing/perfetto_platform.h"
#include "build/build_config.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h"
#include "third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h"
#include "third_party/perfetto/include/perfetto/tracing/console_interceptor.h"
#include "third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h"
#include "third_party/perfetto/protos/perfetto/config/interceptor_config.gen.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h"
#if BUILDFLAG(IS_WIN)
#include "base/trace_event/trace_event_etw_export_win.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/debug/elf_reader.h"
extern char __executable_start;
#endif
namespace base {
namespace trace_event {
namespace {
const size_t kTraceBufferChunkSize = …;
const size_t kTraceEventVectorBigBufferChunks = …;
static_assert …;
const size_t kTraceEventVectorBufferChunks = …;
static_assert …;
const size_t kTraceEventRingBufferChunks = …;
const size_t kEchoToConsoleTraceEventBufferChunks = …;
const size_t kTraceEventBufferSizeInBytes = …;
bool g_perfetto_initialized_by_tracelog = …;
TraceLog* g_trace_log_for_testing = …;
ABSL_CONST_INIT thread_local TraceLog::ThreadLocalEventBuffer*
thread_local_event_buffer = …;
ABSL_CONST_INIT thread_local bool thread_blocks_message_loop = …;
ABSL_CONST_INIT thread_local bool thread_is_in_trace_event = …;
ThreadTicks ThreadNow() { … }
template <typename T>
void InitializeMetadataEvent(TraceEvent* trace_event,
PlatformThreadId thread_id,
const char* metadata_name,
const char* arg_name,
const T& value) { … }
void MakeHandle(uint32_t chunk_seq,
size_t chunk_index,
size_t event_index,
TraceEventHandle* handle) { … }
bool DefaultIsTraceEventArgsAllowlisted(
const char* category_group_name,
const char* event_name,
base::trace_event::ArgumentNameFilterPredicate* arg_name_filter) { … }
class PerfettoProtoAppender
: public base::trace_event::ConvertableToTraceFormat::ProtoAppender { … };
void AddConvertableToTraceFormat(
base::trace_event::ConvertableToTraceFormat* value,
perfetto::protos::pbzero::DebugAnnotation* annotation) { … }
void WriteDebugAnnotations(base::trace_event::TraceEvent* trace_event,
perfetto::protos::pbzero::TrackEvent* track_event) { … }
void OnAddLegacyTraceEvent(TraceEvent* trace_event,
bool thread_will_flush,
base::trace_event::TraceEventHandle* handle) { … }
void OnUpdateLegacyTraceEventDuration(
const unsigned char* category_group_enabled,
const char* name,
TraceEventHandle handle,
PlatformThreadId thread_id,
bool explicit_timestamps,
const TimeTicks& now,
const ThreadTicks& thread_now) { … }
}
#if BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
namespace {
static constexpr char kJsonPrefix[] = …;
static constexpr char kJsonJoiner[] = …;
static constexpr char kJsonSuffix[] = …;
}
class JsonStringOutputWriter
: public perfetto::trace_processor::json::OutputWriter { … };
#endif
class TraceLog::OptionalAutoLock { … };
class TraceLog::ThreadLocalEventBuffer
: public CurrentThread::DestructionObserver,
public MemoryDumpProvider { … };
TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log)
: … { … }
TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { … }
TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
TraceEventHandle* handle) { … }
void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { … }
bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args,
ProcessMemoryDump* pmd) { … }
void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() { … }
void TraceLog::SetAddTraceEventOverrides(
const AddTraceEventOverrideFunction& add_event_override,
const OnFlushFunction& on_flush_override,
const UpdateDurationFunction& update_duration_override) { … }
struct TraceLog::RegisteredAsyncObserver { … };
TraceLogStatus::TraceLogStatus() : … { … }
TraceLogStatus::~TraceLogStatus() = default;
TraceLog* TraceLog::GetInstance() { … }
void TraceLog::ResetForTesting() { … }
TraceLog::TraceLog(int generation)
: … { … }
TraceLog::~TraceLog() { … }
void TraceLog::InitializeThreadLocalEventBufferIfSupported() { … }
bool TraceLog::OnMemoryDump(const MemoryDumpArgs& args,
ProcessMemoryDump* pmd) { … }
const unsigned char* TraceLog::GetCategoryGroupEnabled(
const char* category_group) { … }
const char* TraceLog::GetCategoryGroupName(
const unsigned char* category_group_enabled) { … }
void TraceLog::UpdateCategoryState(TraceCategory* category) { … }
void TraceLog::UpdateCategoryRegistry() { … }
void TraceLog::SetEnabled(const TraceConfig& trace_config,
uint8_t modes_to_enable) { … }
std::vector<TraceLog::TrackEventSession> TraceLog::GetTrackEventSessions()
const { … }
perfetto::DataSourceConfig TraceLog::GetCurrentTrackEventDataSourceConfig()
const { … }
void TraceLog::InitializePerfettoIfNeeded() { … }
bool TraceLog::IsPerfettoInitializedByTraceLog() const { … }
void TraceLog::SetEnabled(const TraceConfig& trace_config,
const perfetto::TraceConfig& perfetto_config) { … }
void TraceLog::SetEnabledImpl(const TraceConfig& trace_config,
const perfetto::TraceConfig& perfetto_config) { … }
void TraceLog::SetArgumentFilterPredicate(
const ArgumentFilterPredicate& argument_filter_predicate) { … }
ArgumentFilterPredicate TraceLog::GetArgumentFilterPredicate() const { … }
void TraceLog::SetMetadataFilterPredicate(
const MetadataFilterPredicate& metadata_filter_predicate) { … }
MetadataFilterPredicate TraceLog::GetMetadataFilterPredicate() const { … }
void TraceLog::SetRecordHostAppPackageName(bool record_host_app_package_name) { … }
bool TraceLog::ShouldRecordHostAppPackageName() const { … }
TraceLog::InternalTraceOptions TraceLog::GetInternalOptionsFromTraceConfig(
const TraceConfig& config) { … }
TraceConfig TraceLog::GetCurrentTraceConfig() const { … }
void TraceLog::SetDisabled() { … }
void TraceLog::SetDisabled(uint8_t modes_to_disable) { … }
void TraceLog::SetDisabledWhileLocked(uint8_t modes_to_disable) { … }
int TraceLog::GetNumTracesRecorded() { … }
void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { … }
void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) { … }
void TraceLog::AddOwnedEnabledStateObserver(
std::unique_ptr<EnabledStateObserver> listener) { … }
bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { … }
void TraceLog::AddAsyncEnabledStateObserver(
WeakPtr<AsyncEnabledStateObserver> listener) { … }
void TraceLog::RemoveAsyncEnabledStateObserver(
AsyncEnabledStateObserver* listener) { … }
bool TraceLog::HasAsyncEnabledStateObserver(
AsyncEnabledStateObserver* listener) const { … }
void TraceLog::AddIncrementalStateObserver(IncrementalStateObserver* listener) { … }
void TraceLog::RemoveIncrementalStateObserver(
IncrementalStateObserver* listener) { … }
void TraceLog::OnIncrementalStateCleared() { … }
TraceLogStatus TraceLog::GetStatus() const { … }
TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
TraceEventHandle* handle,
bool check_buffer_is_full) { … }
void TraceLog::CheckIfBufferIsFullWhileLocked() { … }
void TraceLog::Flush(const TraceLog::OutputCallback& cb,
bool use_worker_thread) { … }
void TraceLog::CancelTracing(const OutputCallback& cb) { … }
void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb,
bool use_worker_thread,
bool discard_events) { … }
#if BUILDFLAG(USE_PERFETTO_TRACE_PROCESSOR)
void TraceLog::OnTraceData(const char* data, size_t size, bool has_more) { … }
#endif
void TraceLog::ConvertTraceEventsToTraceFormat(
std::unique_ptr<TraceBuffer> logged_events,
const OutputCallback& flush_output_callback,
const ArgumentFilterPredicate& argument_filter_predicate) { … }
void TraceLog::FinishFlush(int generation, bool discard_events) { … }
void TraceLog::FlushCurrentThread(int generation, bool discard_events) { … }
void TraceLog::OnFlushTimeout(int generation, bool discard_events) { … }
void TraceLog::UseNextTraceBuffer() { … }
bool TraceLog::ShouldAddAfterUpdatingState(
char phase,
const unsigned char* category_group_enabled,
const char* name,
uint64_t id,
PlatformThreadId thread_id,
const TimeTicks timestamp,
TraceArguments* args) { … }
TraceEventHandle TraceLog::AddTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
TraceArguments* args,
unsigned int flags) { … }
TraceEventHandle TraceLog::AddTraceEventWithBindId(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
uint64_t bind_id,
TraceArguments* args,
unsigned int flags) { … }
TraceEventHandle TraceLog::AddTraceEventWithProcessId(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
ProcessId process_id,
TraceArguments* args,
unsigned int flags) { … }
TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
PlatformThreadId thread_id,
const TimeTicks& timestamp,
TraceArguments* args,
unsigned int flags) { … }
TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
uint64_t bind_id,
PlatformThreadId thread_id,
const TimeTicks& timestamp,
TraceArguments* args,
unsigned int flags) { … }
TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamps(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
uint64_t bind_id,
PlatformThreadId thread_id,
const TimeTicks& timestamp,
const ThreadTicks& thread_timestamp,
TraceArguments* args,
unsigned int flags) NO_THREAD_SAFETY_ANALYSIS { … }
void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled,
const char* name,
TraceArguments* args,
unsigned int flags) { … }
std::string TraceLog::EventToConsoleMessage(char phase,
const TimeTicks& timestamp,
TraceEvent* trace_event) { … }
void TraceLog::UpdateTraceEventDuration(
const unsigned char* category_group_enabled,
const char* name,
TraceEventHandle handle) { … }
void TraceLog::UpdateTraceEventDurationExplicit(
const unsigned char* category_group_enabled,
const char* name,
TraceEventHandle handle,
PlatformThreadId thread_id,
bool explicit_timestamps,
const TimeTicks& now,
const ThreadTicks& thread_now) { … }
uint64_t TraceLog::MangleEventId(uint64_t id) { … }
template <typename T>
void TraceLog::AddMetadataEventWhileLocked(PlatformThreadId thread_id,
const char* metadata_name,
const char* arg_name,
const T& value) { … }
void TraceLog::AddMetadataEventsWhileLocked() { … }
TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) { … }
TraceEvent* TraceLog::GetEventByHandleInternal(TraceEventHandle handle,
OptionalAutoLock* lock)
NO_THREAD_SAFETY_ANALYSIS { … }
void TraceLog::SetProcessID(ProcessId process_id) { … }
void TraceLog::SetProcessSortIndex(int sort_index) { … }
void TraceLog::OnSetProcessName(const std::string& process_name) { … }
int TraceLog::GetNewProcessLabelId() { … }
void TraceLog::UpdateProcessLabel(int label_id,
const std::string& current_label) { … }
void TraceLog::RemoveProcessLabel(int label_id) { … }
void TraceLog::SetThreadSortIndex(PlatformThreadId thread_id, int sort_index) { … }
size_t TraceLog::GetObserverCountForTest() const { … }
void TraceLog::SetCurrentThreadBlocksMessageLoop() { … }
TraceBuffer* TraceLog::CreateTraceBuffer() { … }
#if BUILDFLAG(IS_WIN)
void TraceLog::UpdateETWCategoryGroupEnabledFlags() {
for (TraceCategory& category : CategoryRegistry::GetAllCategories()) {
if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled(
category.name())) {
category.set_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
} else {
category.clear_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
}
}
}
#endif
void TraceLog::SetTraceBufferForTesting(
std::unique_ptr<TraceBuffer> trace_buffer) { … }
void TraceLog::OnSetup(const perfetto::DataSourceBase::SetupArgs& args) { … }
void TraceLog::OnStart(const perfetto::DataSourceBase::StartArgs&) { … }
void TraceLog::OnStop(const perfetto::DataSourceBase::StopArgs& args) { … }
void ConvertableToTraceFormat::EstimateTraceMemoryOverhead(
TraceEventMemoryOverhead* overhead) { … }
}
}
namespace trace_event_internal {
base::trace_event::TraceEventHandle AddTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
base::trace_event::TraceEventHandle AddTraceEventWithBindId(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
uint64_t bind_id,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
base::trace_event::TraceEventHandle AddTraceEventWithProcessId(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
base::ProcessId process_id,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
base::PlatformThreadId thread_id,
const base::TimeTicks& timestamp,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
uint64_t bind_id,
base::PlatformThreadId thread_id,
const base::TimeTicks& timestamp,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamps(
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
uint64_t id,
base::PlatformThreadId thread_id,
const base::TimeTicks& timestamp,
const base::ThreadTicks& thread_timestamp,
unsigned int flags) { … }
void AddMetadataEvent(const unsigned char* category_group_enabled,
const char* name,
base::trace_event::TraceArguments* args,
unsigned int flags) { … }
int GetNumTracesRecorded() { … }
void UpdateTraceEventDuration(const unsigned char* category_group_enabled,
const char* name,
base::trace_event::TraceEventHandle handle) { … }
void UpdateTraceEventDurationExplicit(
const unsigned char* category_group_enabled,
const char* name,
base::trace_event::TraceEventHandle handle,
base::PlatformThreadId thread_id,
bool explicit_timestamps,
const base::TimeTicks& now,
const base::ThreadTicks& thread_now) { … }
}