blob: 7a2edef47eda20aac1834e3c497cf4f70adfb07e [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/interned_args_helper.h"
#include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h"
#include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h"
namespace base {
namespace trace_event {
namespace {
const void* const kModuleCacheForTracingKey = &kModuleCacheForTracingKey;
class ModuleCacheForTracing : public perfetto::TrackEventTlsStateUserData {
public:
ModuleCacheForTracing() = default;
~ModuleCacheForTracing() override = default;
base::ModuleCache& GetModuleCache() { return module_cache_; }
private:
base::ModuleCache module_cache_;
};
} // namespace
// static
void InternedSourceLocation::Add(
perfetto::protos::pbzero::InternedData* interned_data,
size_t iid,
const TraceSourceLocation& location) {
auto* msg = interned_data->add_source_locations();
msg->set_iid(iid);
if (location.file_name != nullptr)
msg->set_file_name(location.file_name);
if (location.function_name != nullptr)
msg->set_function_name(location.function_name);
// TODO(ssid): Add line number once it is allowed in internal proto.
// TODO(ssid): Add program counter to the proto fields when
// !BUILDFLAG(ENABLE_LOCATION_SOURCE).
// TODO(http://crbug.com760702) remove file name and just pass the program
// counter to the heap profiler macro.
// TODO(ssid): Consider writing the program counter of the current task
// (from the callback function pointer) instead of location that posted the
// task.
}
// static
void InternedLogMessage::Add(
perfetto::protos::pbzero::InternedData* interned_data,
size_t iid,
const std::string& log_message) {
auto* msg = interned_data->add_log_message_body();
msg->set_iid(iid);
msg->set_body(log_message);
}
// static
void InternedBuildId::Add(perfetto::protos::pbzero::InternedData* interned_data,
size_t iid,
const std::string& build_id) {
auto* msg = interned_data->add_build_ids();
msg->set_iid(iid);
msg->set_str(build_id);
}
// static
void InternedMappingPath::Add(
perfetto::protos::pbzero::InternedData* interned_data,
size_t iid,
const std::string& mapping_path) {
auto* msg = interned_data->add_mapping_paths();
msg->set_iid(iid);
msg->set_str(mapping_path);
}
// static
size_t InternedMapping::Get(perfetto::EventContext* ctx,
const base::ModuleCache::Module* module) {
auto* index_for_field = GetOrCreateIndexForField(ctx->GetIncrementalState());
size_t iid;
if (index_for_field->index_.LookUpOrInsert(&iid, module)) {
return iid;
}
InternedMapping::Add(ctx, iid, module);
return iid;
}
// static
void InternedMapping::Add(perfetto::EventContext* ctx,
size_t iid,
const base::ModuleCache::Module* module) {
// TODO(b/270470700): Remove TransformModuleIDToSymbolServerFormat on all
// platforms once tools/tracing is fixed.
const auto build_id = InternedBuildId::Get(
ctx, base::TransformModuleIDToSymbolServerFormat(module->GetId()));
const auto path_id =
InternedMappingPath::Get(ctx, module->GetDebugBasename().MaybeAsASCII());
auto* msg =
ctx->GetIncrementalState()->serialized_interned_data->add_mappings();
msg->set_iid(iid);
msg->set_build_id(build_id);
msg->add_path_string_ids(path_id);
}
// static
std::optional<size_t> InternedUnsymbolizedSourceLocation::Get(
perfetto::EventContext* ctx,
uintptr_t address) {
auto* index_for_field = GetOrCreateIndexForField(ctx->GetIncrementalState());
#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
ModuleCacheForTracing* module_cache = static_cast<ModuleCacheForTracing*>(
ctx->GetTlsUserData(kModuleCacheForTracingKey));
if (!module_cache) {
auto new_module_cache = std::make_unique<ModuleCacheForTracing>();
module_cache = new_module_cache.get();
ctx->SetTlsUserData(kModuleCacheForTracingKey, std::move(new_module_cache));
}
const base::ModuleCache::Module* module =
module_cache->GetModuleCache().GetModuleForAddress(address);
#else
const base::ModuleCache::Module* module =
index_for_field->module_cache_.GetModuleForAddress(address);
#endif
if (!module) {
return std::nullopt;
}
size_t iid;
if (index_for_field->index_.LookUpOrInsert(&iid, address)) {
return iid;
}
const auto mapping_id = InternedMapping::Get(ctx, module);
const uintptr_t rel_pc = address - module->GetBaseAddress();
InternedUnsymbolizedSourceLocation::Add(
ctx->GetIncrementalState()->serialized_interned_data.get(), iid,
base::trace_event::UnsymbolizedSourceLocation(mapping_id, rel_pc));
return iid;
}
// static
void InternedUnsymbolizedSourceLocation::Add(
perfetto::protos::pbzero::InternedData* interned_data,
size_t iid,
const UnsymbolizedSourceLocation& location) {
auto* msg = interned_data->add_unsymbolized_source_locations();
msg->set_iid(iid);
msg->set_mapping_id(location.mapping_id);
msg->set_rel_pc(location.rel_pc);
}
} // namespace trace_event
} // namespace base