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

base / trace_event / interned_args_helper.cc [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());
  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);
  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