/*
 * Copyright (C) 2019 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.
 */

syntax = "proto2";

package perfetto.protos;

// The interning fields in this file can refer to 2 different intern tables,
// depending on the message they are used in. If the interned fields are present
// in ProfilePacket proto, then the intern tables included in the ProfilePacket
// should be used. If the intered fields are present in the
// StreamingProfilePacket proto, then the intern tables included in all of the
// previous InternedData message with same sequence ID should be used.
// TODO(fmayer): Move to the intern tables to a common location.
message InternedString {
  // Interning key. Starts from 1, 0 is the same as "not set".
  optional uint64 iid = 1;

  // The actual string.
  optional bytes str = 2;
}

// Source line info.
message Line {
  optional string function_name = 1;
  optional string source_file_name = 2;
  optional uint32 line_number = 3;
}

// Symbols for a given address in a module.
message AddressSymbols {
  optional uint64 address = 1;

  // Source lines that correspond to this address.
  //
  // These are repeated because when inlining happens, multiple functions'
  // frames can be at a single address. Imagine function Foo calling the
  // std::vector<int> constructor, which gets inlined at 0xf00. We then get
  // both Foo and the std::vector<int> constructor when we symbolize the
  // address.
  repeated Line lines = 2;
}

// Symbols for addresses seen in a module.
// Used in re-symbolisation of complete traces.
message ModuleSymbols {
  // Fully qualified path to the mapping.
  // E.g. /system/lib64/libc.so.
  optional string path = 1;

  // .note.gnu.build-id on Linux (not hex encoded).
  // uuid on MacOS.
  // Module GUID on Windows.
  optional string build_id = 2;
  repeated AddressSymbols address_symbols = 3;
}

message Mapping {
  // Interning key.
  // Starts from 1, 0 is the same as "not set".
  optional uint64 iid = 1;

  // Interning key.
  // Starts from 1, 0 is the same as "not set".
  optional uint64 build_id = 2;

  // The linker may create multiple memory mappings for the same shared
  // library.
  // This is so that the ELF header is mapped as read only, while the
  // executable memory is mapped as executable only.
  // The details of this depend on the linker, a possible mapping of an ELF
  // file is this:
  //         +----------------------+
  // ELF     |xxxxxxxxxyyyyyyyyyyyyy|
  //         +---------+------------+
  //         |         |
  //         | read    | executable
  //         v mapping v mapping
  //         +----------------------+
  // Memory  |xxxxxxxxx|yyyyyyyyyyyy|
  //         +------------------+---+
  //         ^         ^        ^
  //         +         +        +
  //       start     exact    relpc
  //       offset   offset    0x1800
  //       0x0000   0x1000
  //
  // exact_offset is the offset into the library file of this mapping.
  // start_offset is the offset into the library file of the first mapping
  // for that library. For native libraries (.so files) this should be 0.

  // This is not set on Android 10.
  optional uint64 exact_offset = 8;

  optional uint64 start_offset = 3;
  optional uint64 start = 4;
  optional uint64 end = 5;

  // Libunwindstack-specific concept, not to be confused with bionic linker's
  // notion of load_bias. Needed to correct relative pc addresses (as produced
  // by libunwindstack) when doing offline resymbolisation.
  //
  // For an executable ELF PT_LOAD segment, this is:
  //   p_vaddr - p_offset
  //
  // Where p_offset means that the code is at that offset into the ELF file on
  // disk. While p_vaddr is the offset at which the code gets *mapped*, relative
  // to where the linker loads the ELF into the address space. For most ELFs,
  // the two values are identical and therefore load_bias is zero.
  optional uint64 load_bias = 6;

  // E.g. ["system", "lib64", "libc.so"]
  // id of string.
  repeated uint64 path_string_ids = 7;
}

message Frame {
  // Interning key. Starts from 1, 0 is the same as "not set".
  optional uint64 iid = 1;

  // E.g. "fopen"
  // id of string.
  optional uint64 function_name_id = 2;

  // The mapping in which this frame's instruction pointer resides.
  // iid of Mapping.iid.
  //
  // If set (non-zero), rel_pc MUST also be set. If mapping_id is 0 (not set),
  // this frame has no associated memory mapping (e.g., symbolized frames
  // without address information).
  //
  // Starts from 1, 0 is the same as "not set".
  optional uint64 mapping_id = 3;

  // Instruction pointer relative to the start of the mapping.
  // MUST be set if mapping_id is set (non-zero). Ignored if mapping_id is 0.
  optional uint64 rel_pc = 4;

  // Source file path for this frame.
  // This is typically set during online symbolization when symbol information
  // is available at trace collection time. If not set, source file paths may be
  // added later via offline symbolization (see ModuleSymbols).
  //
  // Starts from 1, 0 is the same as "not set".
  //
  // iid of InternedData.source_paths.
  optional uint64 source_path_iid = 5;

  // Line number in the source file for this frame.
  // This is typically set during online symbolization when symbol information
  // is available at trace collection time. If not set, line numbers may be
  // added later via offline symbolization (see ModuleSymbols).
  optional uint32 line_number = 6;
}

message Callstack {
  // Interning key. Starts from 1, 0 is the same as "not set".
  optional uint64 iid = 1;
  // Frames of this callstack. Bottom frame first.
  repeated uint64 frame_ids = 2;
}
