/*
 * Copyright (C) 2021 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/util/annotated_callsites.h"

#include <iostream>

#include "perfetto/ext/base/optional.h"
#include "src/trace_processor/tables/profiler_tables.h"
#include "src/trace_processor/types/trace_processor_context.h"

namespace perfetto {
namespace trace_processor {

AnnotatedCallsites::AnnotatedCallsites(const TraceProcessorContext* context)
    : context_(*context),
      // String to identify trampoline frames. If the string does not exist in
      // TraceProcessor's StringPool (nullopt) then there will be no trampoline
      // frames in the trace so there is no point in adding it to the pool to do
      // all comparisons, instead we initialize the member to nullopt and the
      // string comparisons will all fail.
      art_jni_trampoline_(
          context->storage->string_pool().GetId("art_jni_trampoline")) {}

AnnotatedCallsites::State AnnotatedCallsites::GetState(
    base::Optional<CallsiteId> id) {
  if (!id) {
    return State::kInitial;
  }
  auto it = states_.find(*id);
  if (it != states_.end()) {
    return it->second;
  }

  State state =
      Get(*context_.storage->stack_profile_callsite_table().FindById(*id))
          .first;
  states_.emplace(*id, state);
  return state;
}

std::pair<AnnotatedCallsites::State, CallsiteAnnotation>
AnnotatedCallsites::Get(
    const tables::StackProfileCallsiteTable::ConstRowReference& callsite) {
  State state = GetState(callsite.parent_id());

  // Keep immediate callee of a JNI trampoline, but keep tagging all
  // successive libart frames as common.
  if (state == State::kKeepNext) {
    return {State::kEraseLibart, CallsiteAnnotation::kNone};
  }

  // Special-case "art_jni_trampoline" frames, keeping their immediate callee
  // even if it is in libart, as it could be a native implementation of a
  // managed method. Example for "java.lang.reflect.Method.Invoke":
  //   art_jni_trampoline
  //   art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)
  //
  // Simpleperf also relies on this frame name, so it should be fairly stable.
  // TODO(rsavitski): consider detecting standard JNI upcall entrypoints -
  // _JNIEnv::Call*. These are sometimes inlined into other DSOs, so erasing
  // only the libart frames does not clean up all of the JNI-related frames.
  auto frame = *context_.storage->stack_profile_frame_table().FindById(
      callsite.frame_id());
  // art_jni_trampoline_ could be nullopt if the string does not exist in the
  // StringPool, but that also means no frame will ever have that name.
  if (art_jni_trampoline_.has_value() &&
      frame.name() == art_jni_trampoline_.value()) {
    return {State::kKeepNext, CallsiteAnnotation::kCommonFrame};
  }

  MapType map_type = GetMapType(frame.mapping());

  // Annotate managed frames.
  if (map_type == MapType::kArtInterp ||  //
      map_type == MapType::kArtJit ||     //
      map_type == MapType::kArtAot) {
    // Now know to be in a managed callstack - erase subsequent ART frames.
    if (state == State::kInitial) {
      state = State::kEraseLibart;
    }

    if (map_type == MapType::kArtInterp)
      return {state, CallsiteAnnotation::kArtInterpreted};
    if (map_type == MapType::kArtJit)
      return {state, CallsiteAnnotation::kArtJit};
    if (map_type == MapType::kArtAot)
      return {state, CallsiteAnnotation::kArtAot};
  }

  // Mixed callstack, tag libart frames as uninteresting (common-frame).
  // Special case a subset of interpreter implementation frames as
  // "common-frame-interp" using frame name prefixes. Those functions are
  // actually executed, whereas the managed "interp" frames are synthesised as
  // their caller by the unwinding library (based on the dex_pc virtual
  // register restored using the libart's DWARF info). The heuristic covers
  // the "nterp" and "switch" interpreter implementations.
  //
  // Example:
  //  <towards root>
  //  android.view.WindowLayout.computeFrames [interp]
  //  nterp_op_iget_object_slow_path [common-frame-interp]
  //
  // This annotation is helpful when trying to answer "what mode was the
  // process in?" based on the leaf frame of the callstack. As we want to
  // classify such cases as interpreted, even though the leaf frame is
  // libart.so.
  //
  // For "switch" interpreter, we match any frame starting with
  // "art::interpreter::" according to itanium mangling.
  if (state == State::kEraseLibart && map_type == MapType::kNativeLibart) {
    NullTermStringView fname = context_.storage->GetString(frame.name());
    if (fname.StartsWith("nterp_") || fname.StartsWith("Nterp") ||
        fname.StartsWith("ExecuteNterp") ||
        fname.StartsWith("ExecuteSwitchImpl") ||
        fname.StartsWith("_ZN3art11interpreter")) {
      return {state, CallsiteAnnotation::kCommonFrameInterp};
    }
    return {state, CallsiteAnnotation::kCommonFrame};
  }

  return {state, CallsiteAnnotation::kNone};
}

AnnotatedCallsites::MapType AnnotatedCallsites::GetMapType(MappingId id) {
  auto it = map_types_.find(id);
  if (it != map_types_.end()) {
    return it->second;
  }

  return map_types_
      .emplace(id, ClassifyMap(context_.storage->GetString(
                       context_.storage->stack_profile_mapping_table()
                           .FindById(id)
                           ->name())))
      .first->second;
}

AnnotatedCallsites::MapType AnnotatedCallsites::ClassifyMap(
    NullTermStringView map) {
  if (map.empty())
    return MapType::kOther;

  // Primary mapping where modern ART puts jitted code.
  // The Zygote's JIT region is inherited by all descendant apps, so it can
  // still appear in their callstacks.
  if (map.StartsWith("/memfd:jit-cache") ||
      map.StartsWith("/memfd:jit-zygote-cache")) {
    return MapType::kArtJit;
  }

  size_t last_slash_pos = map.rfind('/');
  if (last_slash_pos != NullTermStringView::npos) {
    base::StringView suffix = map.substr(last_slash_pos);
    if (suffix.StartsWith("/libart.so") || suffix.StartsWith("/libartd.so"))
      return MapType::kNativeLibart;
  }

  size_t extension_pos = map.rfind('.');
  if (extension_pos != NullTermStringView::npos) {
    base::StringView suffix = map.substr(extension_pos);
    if (suffix.StartsWith(".so"))
      return MapType::kNativeOther;
    // unqualified dex
    if (suffix.StartsWith(".dex"))
      return MapType::kArtInterp;
    // dex with verification speedup info, produced by dex2oat
    if (suffix.StartsWith(".vdex"))
      return MapType::kArtInterp;
    // possibly uncompressed dex in a jar archive
    if (suffix.StartsWith(".jar"))
      return MapType::kArtInterp;
    // android package (zip file), this can contain uncompressed dexes or
    // native libraries that are mmap'd directly into the process. We rely on
    // libunwindstack's MapInfo::GetFullName, which suffixes the mapping with
    // "!lib.so" if it knows that the referenced piece of the archive is an
    // uncompressed ELF file. So an unadorned ".apk" is assumed to be a dex
    // file.
    if (suffix.StartsWith(".apk"))
      return MapType::kArtInterp;
    // ahead of time compiled ELFs
    if (suffix.StartsWith(".oat"))
      return MapType::kArtAot;
    // older/alternative name for .oat
    if (suffix.StartsWith(".odex"))
      return MapType::kArtAot;
  }
  return MapType::kOther;
}

}  // namespace trace_processor
}  // namespace perfetto
