/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/proto/profile_module.h"
#include <string>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/string_utils.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/deobfuscation_mapping_table.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/proto/heap_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
#include "src/trace_processor/importers/proto/profile_packet_utils.h"
#include "src/trace_processor/importers/proto/profiler_util.h"
#include "src/trace_processor/importers/proto/stack_profile_tracker.h"
#include "src/trace_processor/sorter/trace_sorter.h"
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/stack_traces_util.h"

#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/common/perf_events.pbzero.h"
#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
#include "protos/perfetto/trace/profiling/smaps.pbzero.h"

namespace perfetto {
namespace trace_processor {

using perfetto::protos::pbzero::TracePacket;
using protozero::ConstBytes;

ProfileModule::ProfileModule(TraceProcessorContext* context)
    : context_(context) {
  RegisterForField(TracePacket::kStreamingProfilePacketFieldNumber, context);
  RegisterForField(TracePacket::kPerfSampleFieldNumber, context);
  RegisterForField(TracePacket::kProfilePacketFieldNumber, context);
  RegisterForField(TracePacket::kModuleSymbolsFieldNumber, context);
  // note: deobfuscation mappings also handled by HeapGraphModule.
  RegisterForField(TracePacket::kDeobfuscationMappingFieldNumber, context);
  RegisterForField(TracePacket::kSmapsPacketFieldNumber, context);
}

ProfileModule::~ProfileModule() = default;

ModuleResult ProfileModule::TokenizePacket(const TracePacket::Decoder& decoder,
                                           TraceBlobView* packet,
                                           int64_t /*packet_timestamp*/,
                                           PacketSequenceState* state,
                                           uint32_t field_id) {
  switch (field_id) {
    case TracePacket::kStreamingProfilePacketFieldNumber:
      return TokenizeStreamingProfilePacket(state, packet,
                                            decoder.streaming_profile_packet());
  }
  return ModuleResult::Ignored();
}

void ProfileModule::ParseTracePacketData(
    const protos::pbzero::TracePacket::Decoder& decoder,
    int64_t ts,
    const TracePacketData& data,
    uint32_t field_id) {
  switch (field_id) {
    case TracePacket::kStreamingProfilePacketFieldNumber:
      ParseStreamingProfilePacket(ts, data.sequence_state.get(),
                                  decoder.streaming_profile_packet());
      return;
    case TracePacket::kPerfSampleFieldNumber:
      ParsePerfSample(ts, data.sequence_state.get(), decoder);
      return;
    case TracePacket::kProfilePacketFieldNumber:
      ParseProfilePacket(ts, data.sequence_state.get(),
                         decoder.trusted_packet_sequence_id(),
                         decoder.profile_packet());
      return;
    case TracePacket::kModuleSymbolsFieldNumber:
      ParseModuleSymbols(decoder.module_symbols());
      return;
    case TracePacket::kDeobfuscationMappingFieldNumber:
      ParseDeobfuscationMapping(ts, data.sequence_state.get(),
                                decoder.trusted_packet_sequence_id(),
                                decoder.deobfuscation_mapping());
      return;
    case TracePacket::kSmapsPacketFieldNumber:
      ParseSmapsPacket(ts, decoder.smaps_packet());
      return;
  }
}

ModuleResult ProfileModule::TokenizeStreamingProfilePacket(
    PacketSequenceState* sequence_state,
    TraceBlobView* packet,
    ConstBytes streaming_profile_packet) {
  protos::pbzero::StreamingProfilePacket::Decoder decoder(
      streaming_profile_packet.data, streaming_profile_packet.size);

  // We have to resolve the reference timestamp of a StreamingProfilePacket
  // during tokenization. If we did this during parsing instead, the
  // tokenization of a subsequent ThreadDescriptor with a new reference
  // timestamp would cause us to later calculate timestamps based on the wrong
  // reference value during parsing. Since StreamingProfilePackets only need to
  // be sorted correctly with respect to process/thread metadata events (so that
  // pid/tid are resolved correctly during parsing), we forward the packet as a
  // whole through the sorter, using the "root" timestamp of the packet, i.e.
  // the current timestamp of the packet sequence.
  auto packet_ts =
      sequence_state->IncrementAndGetTrackEventTimeNs(/*delta_ns=*/0);
  base::StatusOr<int64_t> trace_ts = context_->clock_tracker->ToTraceTime(
      protos::pbzero::BUILTIN_CLOCK_MONOTONIC, packet_ts);
  if (trace_ts.ok())
    packet_ts = *trace_ts;

  // Increment the sequence's timestamp by all deltas.
  for (auto timestamp_it = decoder.timestamp_delta_us(); timestamp_it;
       ++timestamp_it) {
    sequence_state->IncrementAndGetTrackEventTimeNs(*timestamp_it * 1000);
  }

  context_->sorter->PushTracePacket(
      packet_ts, sequence_state->current_generation(), std::move(*packet));
  return ModuleResult::Handled();
}

void ProfileModule::ParseStreamingProfilePacket(
    int64_t timestamp,
    PacketSequenceStateGeneration* sequence_state,
    ConstBytes streaming_profile_packet) {
  protos::pbzero::StreamingProfilePacket::Decoder packet(
      streaming_profile_packet.data, streaming_profile_packet.size);

  ProcessTracker* procs = context_->process_tracker.get();
  TraceStorage* storage = context_->storage.get();
  SequenceStackProfileTracker& sequence_stack_profile_tracker =
      sequence_state->state()->sequence_stack_profile_tracker();
  ProfilePacketInternLookup intern_lookup(sequence_state);

  uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
  uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
  UniqueTid utid = procs->UpdateThread(tid, pid);

  // Iterate through timestamps and callstacks simultaneously.
  auto timestamp_it = packet.timestamp_delta_us();
  for (auto callstack_it = packet.callstack_iid(); callstack_it;
       ++callstack_it, ++timestamp_it) {
    if (!timestamp_it) {
      context_->storage->IncrementStats(stats::stackprofile_parser_error);
      PERFETTO_ELOG(
          "StreamingProfilePacket has less callstack IDs than timestamps!");
      break;
    }

    auto opt_cs_id = sequence_stack_profile_tracker.FindOrInsertCallstack(
        *callstack_it, &intern_lookup);
    if (!opt_cs_id) {
      context_->storage->IncrementStats(stats::stackprofile_parser_error);
      continue;
    }

    // Resolve the delta timestamps based on the packet's root timestamp.
    timestamp += *timestamp_it * 1000;

    tables::CpuProfileStackSampleTable::Row sample_row{
        timestamp, *opt_cs_id, utid, packet.process_priority()};
    storage->mutable_cpu_profile_stack_sample_table()->Insert(sample_row);
  }
}

void ProfileModule::ParsePerfSample(
    int64_t ts,
    PacketSequenceStateGeneration* sequence_state,
    const TracePacket::Decoder& decoder) {
  using PerfSample = protos::pbzero::PerfSample;
  const auto& sample_raw = decoder.perf_sample();
  PerfSample::Decoder sample(sample_raw.data, sample_raw.size);

  uint32_t seq_id = decoder.trusted_packet_sequence_id();
  PerfSampleTracker::SamplingStreamInfo sampling_stream =
      context_->perf_sample_tracker->GetSamplingStreamInfo(
          seq_id, sample.cpu(), sequence_state->GetTracePacketDefaults());

  // Not a sample, but an indication of data loss in the ring buffer shared with
  // the kernel.
  if (sample.kernel_records_lost() > 0) {
    PERFETTO_DCHECK(sample.pid() == 0);

    context_->storage->IncrementIndexedStats(
        stats::perf_cpu_lost_records, static_cast<int>(sample.cpu()),
        static_cast<int64_t>(sample.kernel_records_lost()));
    return;
  }

  // Sample that looked relevant for the tracing session, but had to be skipped.
  // Either we failed to look up the procfs file descriptors necessary for
  // remote stack unwinding (not unexpected in most cases), or the unwind queue
  // was out of capacity (producer lost data on its own).
  if (sample.has_sample_skipped_reason()) {
    context_->storage->IncrementStats(stats::perf_samples_skipped);

    if (sample.sample_skipped_reason() ==
        PerfSample::PROFILER_SKIP_UNWIND_ENQUEUE)
      context_->storage->IncrementStats(stats::perf_samples_skipped_dataloss);

    return;
  }

  // Not a sample, but an event from the producer.
  // TODO(rsavitski): this stat is indexed by the session id, but the older
  // stats (see above) aren't. The indexing is relevant if a trace contains more
  // than one profiling data source. So the older stats should be changed to
  // being indexed as well.
  if (sample.has_producer_event()) {
    PerfSample::ProducerEvent::Decoder producer_event(sample.producer_event());
    if (producer_event.source_stop_reason() ==
        PerfSample::ProducerEvent::PROFILER_STOP_GUARDRAIL) {
      context_->storage->SetIndexedStats(
          stats::perf_guardrail_stop_ts,
          static_cast<int>(sampling_stream.perf_session_id), ts);
    }
    return;
  }

  // Proper sample, populate the |perf_sample| table with everything except the
  // recorded counter values, which go to |counter|.
  context_->event_tracker->PushCounter(
      ts, static_cast<double>(sample.timebase_count()),
      sampling_stream.timebase_track_id);

  SequenceStackProfileTracker& stack_tracker =
      sequence_state->state()->sequence_stack_profile_tracker();
  ProfilePacketInternLookup intern_lookup(sequence_state);
  uint64_t callstack_iid = sample.callstack_iid();
  base::Optional<CallsiteId> cs_id =
      stack_tracker.FindOrInsertCallstack(callstack_iid, &intern_lookup);

  // A failed lookup of the interned callstack can mean either:
  // (a) This is a counter-only profile without callstacks. Due to an
  //     implementation quirk, these packets still set callstack_iid
  //     corresponding to a callstack with no frames. To reliably identify this
  //     case (without resorting to config parsing) we further need to rely on
  //     the fact that the implementation (callstack_trie.h) always assigns this
  //     callstack the id "1". Such callstacks should not occur outside of
  //     counter-only profiles, as there should always be at least a synthetic
  //     error frame if the unwinding completely failed.
  // (b) This is a ring-buffer profile where some of the referenced internings
  //     have been overwritten, and the build predates perf_sample_defaults and
  //     SEQ_NEEDS_INCREMENTAL_STATE sequence flag in perf_sample packets.
  //     Such packets should be discarded.
  if (!cs_id && callstack_iid != 1) {
    PERFETTO_DLOG("Discarding perf_sample since callstack_iid [%" PRIu64
                  "] references a missing/partially lost interning according "
                  "to stack_profile_tracker",
                  callstack_iid);
    return;
  }

  UniqueTid utid =
      context_->process_tracker->UpdateThread(sample.tid(), sample.pid());

  using protos::pbzero::Profiling;
  TraceStorage* storage = context_->storage.get();

  auto cpu_mode = static_cast<Profiling::CpuMode>(sample.cpu_mode());
  StringPool::Id cpu_mode_id =
      storage->InternString(ProfilePacketUtils::StringifyCpuMode(cpu_mode));

  base::Optional<StringPool::Id> unwind_error_id;
  if (sample.has_unwind_error()) {
    auto unwind_error =
        static_cast<Profiling::StackUnwindError>(sample.unwind_error());
    unwind_error_id = storage->InternString(
        ProfilePacketUtils::StringifyStackUnwindError(unwind_error));
  }
  tables::PerfSampleTable::Row sample_row(ts, utid, sample.cpu(), cpu_mode_id,
                                          cs_id, unwind_error_id,
                                          sampling_stream.perf_session_id);
  context_->storage->mutable_perf_sample_table()->Insert(sample_row);
}

void ProfileModule::ParseProfilePacket(
    int64_t ts,
    PacketSequenceStateGeneration* sequence_state,
    uint32_t seq_id,
    ConstBytes blob) {
  protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
  context_->heap_profile_tracker->SetProfilePacketIndex(seq_id, packet.index());

  for (auto it = packet.strings(); it; ++it) {
    protos::pbzero::InternedString::Decoder entry(*it);

    const char* str = reinterpret_cast<const char*>(entry.str().data);
    auto str_view = base::StringView(str, entry.str().size);
    sequence_state->state()->sequence_stack_profile_tracker().AddString(
        entry.iid(), str_view);
  }

  for (auto it = packet.mappings(); it; ++it) {
    protos::pbzero::Mapping::Decoder entry(*it);
    SequenceStackProfileTracker::SourceMapping src_mapping =
        ProfilePacketUtils::MakeSourceMapping(entry);
    sequence_state->state()->sequence_stack_profile_tracker().AddMapping(
        entry.iid(), src_mapping);
  }

  for (auto it = packet.frames(); it; ++it) {
    protos::pbzero::Frame::Decoder entry(*it);
    SequenceStackProfileTracker::SourceFrame src_frame =
        ProfilePacketUtils::MakeSourceFrame(entry);
    sequence_state->state()->sequence_stack_profile_tracker().AddFrame(
        entry.iid(), src_frame);
  }

  for (auto it = packet.callstacks(); it; ++it) {
    protos::pbzero::Callstack::Decoder entry(*it);
    SequenceStackProfileTracker::SourceCallstack src_callstack =
        ProfilePacketUtils::MakeSourceCallstack(entry);
    sequence_state->state()->sequence_stack_profile_tracker().AddCallstack(
        entry.iid(), src_callstack);
  }

  for (auto it = packet.process_dumps(); it; ++it) {
    protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(*it);

    base::StatusOr<int64_t> maybe_timestamp =
        context_->clock_tracker->ToTraceTime(
            protos::pbzero::BUILTIN_CLOCK_MONOTONIC_COARSE,
            static_cast<int64_t>(entry.timestamp()));

    // ToTraceTime() increments the clock_sync_failure error stat in this case.
    if (!maybe_timestamp.ok())
      continue;

    int64_t timestamp = *maybe_timestamp;

    int pid = static_cast<int>(entry.pid());
    context_->storage->SetIndexedStats(stats::heapprofd_last_profile_timestamp,
                                       pid, ts);

    if (entry.disconnected())
      context_->storage->IncrementIndexedStats(
          stats::heapprofd_client_disconnected, pid);
    if (entry.buffer_corrupted())
      context_->storage->IncrementIndexedStats(
          stats::heapprofd_buffer_corrupted, pid);
    if (entry.buffer_overran() ||
        entry.client_error() ==
            protos::pbzero::ProfilePacket::ProcessHeapSamples::
                CLIENT_ERROR_HIT_TIMEOUT) {
      context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
                                               pid);
    }
    if (entry.client_error()) {
      context_->storage->SetIndexedStats(stats::heapprofd_client_error, pid,
                                         entry.client_error());
    }
    if (entry.rejected_concurrent())
      context_->storage->IncrementIndexedStats(
          stats::heapprofd_rejected_concurrent, pid);
    if (entry.hit_guardrail())
      context_->storage->IncrementIndexedStats(stats::heapprofd_hit_guardrail,
                                               pid);
    if (entry.orig_sampling_interval_bytes()) {
      context_->storage->SetIndexedStats(
          stats::heapprofd_sampling_interval_adjusted, pid,
          static_cast<int64_t>(entry.sampling_interval_bytes()) -
              static_cast<int64_t>(entry.orig_sampling_interval_bytes()));
    }

    protos::pbzero::ProfilePacket::ProcessStats::Decoder stats(entry.stats());
    context_->storage->IncrementIndexedStats(
        stats::heapprofd_unwind_time_us, static_cast<int>(entry.pid()),
        static_cast<int64_t>(stats.total_unwinding_time_us()));
    context_->storage->IncrementIndexedStats(
        stats::heapprofd_unwind_samples, static_cast<int>(entry.pid()),
        static_cast<int64_t>(stats.heap_samples()));
    context_->storage->IncrementIndexedStats(
        stats::heapprofd_client_spinlock_blocked, static_cast<int>(entry.pid()),
        static_cast<int64_t>(stats.client_spinlock_blocked_us()));

    // orig_sampling_interval_bytes was introduced slightly after a bug with
    // self_max_count was fixed in the producer. We use this as a proxy
    // whether or not we are getting this data from a fixed producer or not.
    bool trustworthy_max_count = entry.orig_sampling_interval_bytes() > 0;

    for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
      protos::pbzero::ProfilePacket::HeapSample::Decoder sample(*sample_it);

      HeapProfileTracker::SourceAllocation src_allocation;
      src_allocation.pid = entry.pid();
      if (entry.heap_name().size != 0) {
        src_allocation.heap_name =
            context_->storage->InternString(entry.heap_name());
      } else {
        src_allocation.heap_name = context_->storage->InternString("malloc");
      }
      src_allocation.timestamp = timestamp;
      src_allocation.callstack_id = sample.callstack_id();
      if (sample.has_self_max()) {
        src_allocation.self_allocated = sample.self_max();
        if (trustworthy_max_count)
          src_allocation.alloc_count = sample.self_max_count();
      } else {
        src_allocation.self_allocated = sample.self_allocated();
        src_allocation.self_freed = sample.self_freed();
        src_allocation.alloc_count = sample.alloc_count();
        src_allocation.free_count = sample.free_count();
      }

      context_->heap_profile_tracker->StoreAllocation(seq_id, src_allocation);
    }
  }
  if (!packet.continued()) {
    PERFETTO_CHECK(sequence_state);
    ProfilePacketInternLookup intern_lookup(sequence_state);
    context_->heap_profile_tracker->FinalizeProfile(
        seq_id, &sequence_state->state()->sequence_stack_profile_tracker(),
        &intern_lookup);
  }
}

void ProfileModule::ParseModuleSymbols(ConstBytes blob) {
  protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
  StringId build_id;
  // TODO(b/148109467): Remove workaround once all active Chrome versions
  // write raw bytes instead of a string as build_id.
  if (util::IsHexModuleId(module_symbols.build_id())) {
    build_id = context_->storage->InternString(module_symbols.build_id());
  } else {
    build_id = context_->storage->InternString(base::StringView(base::ToHex(
        module_symbols.build_id().data, module_symbols.build_id().size)));
  }

  auto mapping_ids = context_->global_stack_profile_tracker->FindMappingRow(
      context_->storage->InternString(module_symbols.path()), build_id);
  if (mapping_ids.empty()) {
    context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
    return;
  }
  for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
    protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);

    uint32_t symbol_set_id = context_->storage->symbol_table().row_count();

    bool has_lines = false;
    // Taking the last (i.e. the least interned) location if there're several.
    ArgsTranslationTable::SourceLocation last_location;
    for (auto line_it = address_symbols.lines(); line_it; ++line_it) {
      protos::pbzero::Line::Decoder line(*line_it);
      context_->storage->mutable_symbol_table()->Insert(
          {symbol_set_id, context_->storage->InternString(line.function_name()),
           context_->storage->InternString(line.source_file_name()),
           line.line_number()});
      last_location = ArgsTranslationTable::SourceLocation{
          line.source_file_name().ToStdString(),
          line.function_name().ToStdString(), line.line_number()};
      has_lines = true;
    }
    if (!has_lines) {
      continue;
    }
    bool frame_found = false;
    for (MappingId mapping_id : mapping_ids) {
      context_->args_translation_table->AddNativeSymbolTranslationRule(
          mapping_id, address_symbols.address(), last_location);
      std::vector<FrameId> frame_ids =
          context_->global_stack_profile_tracker->FindFrameIds(
              mapping_id, address_symbols.address());

      for (const FrameId frame_id : frame_ids) {
        auto* frames = context_->storage->mutable_stack_profile_frame_table();
        uint32_t frame_row = *frames->id().IndexOf(frame_id);
        frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
        frame_found = true;
      }
    }

    if (!frame_found) {
      context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
      continue;
    }
  }
}

void ProfileModule::ParseDeobfuscationMapping(int64_t,
                                              PacketSequenceStateGeneration*,
                                              uint32_t /* seq_id */,
                                              ConstBytes blob) {
  DeobfuscationMappingTable deobfuscation_mapping_table;
  protos::pbzero::DeobfuscationMapping::Decoder deobfuscation_mapping(
      blob.data, blob.size);
  if (deobfuscation_mapping.package_name().size == 0)
    return;

  auto opt_package_name_id = context_->storage->string_pool().GetId(
      deobfuscation_mapping.package_name());
  auto opt_memfd_id = context_->storage->string_pool().GetId("memfd");
  if (!opt_package_name_id && !opt_memfd_id)
    return;

  for (auto class_it = deobfuscation_mapping.obfuscated_classes(); class_it;
       ++class_it) {
    protos::pbzero::ObfuscatedClass::Decoder cls(*class_it);
    base::FlatHashMap<StringId, StringId> obfuscated_to_deobfuscated_members;
    for (auto member_it = cls.obfuscated_methods(); member_it; ++member_it) {
      protos::pbzero::ObfuscatedMember::Decoder member(*member_it);
      std::string merged_obfuscated = cls.obfuscated_name().ToStdString() +
                                      "." +
                                      member.obfuscated_name().ToStdString();
      auto merged_obfuscated_id = context_->storage->string_pool().GetId(
          base::StringView(merged_obfuscated));
      if (!merged_obfuscated_id)
        continue;
      std::string merged_deobfuscated =
          FullyQualifiedDeobfuscatedName(cls, member);

      std::vector<tables::StackProfileFrameTable::Id> frames;
      if (opt_package_name_id) {
        const std::vector<tables::StackProfileFrameTable::Id>* pkg_frames =
            context_->global_stack_profile_tracker->JavaFramesForName(
                {*merged_obfuscated_id, *opt_package_name_id});
        if (pkg_frames) {
          frames.insert(frames.end(), pkg_frames->begin(), pkg_frames->end());
        }
      }
      if (opt_memfd_id) {
        const std::vector<tables::StackProfileFrameTable::Id>* memfd_frames =
            context_->global_stack_profile_tracker->JavaFramesForName(
                {*merged_obfuscated_id, *opt_memfd_id});
        if (memfd_frames) {
          frames.insert(frames.end(), memfd_frames->begin(),
                        memfd_frames->end());
        }
      }

      for (tables::StackProfileFrameTable::Id frame_id : frames) {
        auto* frames_tbl =
            context_->storage->mutable_stack_profile_frame_table();
        frames_tbl->mutable_deobfuscated_name()->Set(
            *frames_tbl->id().IndexOf(frame_id),
            context_->storage->InternString(
                base::StringView(merged_deobfuscated)));
      }
      obfuscated_to_deobfuscated_members[context_->storage->InternString(
          member.obfuscated_name())] =
          context_->storage->InternString(member.deobfuscated_name());
    }
    // Members can contain a class name (e.g "ClassA.FunctionF")
    deobfuscation_mapping_table.AddClassTranslation(
        DeobfuscationMappingTable::PackageId{
            deobfuscation_mapping.package_name().ToStdString(),
            deobfuscation_mapping.version_code()},
        context_->storage->InternString(cls.obfuscated_name()),
        context_->storage->InternString(cls.deobfuscated_name()),
        std::move(obfuscated_to_deobfuscated_members));
  }
  context_->args_translation_table->AddDeobfuscationMappingTable(
      std::move(deobfuscation_mapping_table));
}

void ProfileModule::ParseSmapsPacket(int64_t ts, ConstBytes blob) {
  protos::pbzero::SmapsPacket::Decoder sp(blob.data, blob.size);
  auto upid = context_->process_tracker->GetOrCreateProcess(sp.pid());

  for (auto it = sp.entries(); it; ++it) {
    protos::pbzero::SmapsEntry::Decoder e(*it);
    context_->storage->mutable_profiler_smaps_table()->Insert(
        {upid, ts, context_->storage->InternString(e.path()),
         static_cast<int64_t>(e.size_kb()),
         static_cast<int64_t>(e.private_dirty_kb()),
         static_cast<int64_t>(e.swap_kb()),
         context_->storage->InternString(e.file_name()),
         static_cast<int64_t>(e.start_address()),
         static_cast<int64_t>(e.module_timestamp()),
         context_->storage->InternString(e.module_debugid()),
         context_->storage->InternString(e.module_debug_path()),
         static_cast<int32_t>(e.protection_flags()),
         static_cast<int64_t>(e.private_clean_resident_kb()),
         static_cast<int64_t>(e.shared_dirty_resident_kb()),
         static_cast<int64_t>(e.shared_clean_resident_kb()),
         static_cast<int64_t>(e.locked_kb()),
         static_cast<int64_t>(e.proportional_resident_kb())});
  }
}

void ProfileModule::NotifyEndOfFile() {
  for (auto it = context_->storage->stack_profile_mapping_table().IterateRows();
       it; ++it) {
    NullTermStringView path = context_->storage->GetString(it.name());
    NullTermStringView build_id = context_->storage->GetString(it.build_id());

    if (path.StartsWith("/data/local/tmp/") && build_id.empty()) {
      context_->storage->IncrementStats(
          stats::symbolization_tmp_build_id_not_found);
    }
  }
}

}  // namespace trace_processor
}  // namespace perfetto
