17e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
27e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Use of this source code is governed by a BSD-style license that can be
37e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// found in the LICENSE file.
47e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
57e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_reader.h"
67e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
77e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <byteswap.h>
87e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <limits.h>
97e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <bitset>
117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstdio>
127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstdlib>
137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstring>
147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <vector>
157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#define LOG_TAG "perf_reader"
177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "base/logging.h"
197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "quipper_string.h"
217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_utils.h"
227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace quipper {
247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstruct BufferWithSize {
267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  char* ptr;
277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size;
287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh};
297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// If the buffer is read-only, it is not sufficient to mark the previous struct
317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// as const, as this only means that the pointer cannot be changed, and says
327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// nothing about the contents of the buffer.  So, we need another struct.
337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstruct ConstBufferWithSize {
347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const char* ptr;
357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size;
367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh};
377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace {
397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// The type of the number of string data, found in the command line metadata in
417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// the perf data file.
427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef u32 num_string_data_type;
437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Types of the event desc fields that are not found in other structs.
457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef u32 event_desc_num_events;
467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef u32 event_desc_attr_size;
477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef u32 event_desc_num_unique_ids;
487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// The type of the number of nodes field in NUMA topology.
507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef u32 numa_topology_num_nodes_type;
517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// A mask that is applied to metadata_mask_ in order to get a mask for
537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// only the metadata supported by quipper.
547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint32_t kSupportedMetadataMask =
557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_TRACING_DATA |
567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_BUILD_ID |
577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_HOSTNAME |
587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_OSRELEASE |
597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_VERSION |
607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_ARCH |
617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_NRCPUS |
627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_CPUDESC |
637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_CPUID |
647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_TOTAL_MEM |
657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_CMDLINE |
667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_EVENT_DESC |
677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_CPU_TOPOLOGY |
687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_NUMA_TOPOLOGY |
697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    1 << HEADER_BRANCH_STACK;
707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// By default, the build ID event has PID = -1.
727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint32_t kDefaultBuildIDEventPid = static_cast<uint32_t>(-1);
737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtemplate <class T>
757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid ByteSwap(T* input) {
767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  switch (sizeof(T)) {
777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case sizeof(uint8_t):
787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(WARNING) << "Attempting to byte swap on a single byte.";
797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case sizeof(uint16_t):
817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *input = bswap_16(*input);
827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case sizeof(uint32_t):
847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *input = bswap_32(*input);
857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case sizeof(uint64_t):
877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *input = bswap_64(*input);
887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  default:
907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(FATAL) << "Invalid size for byte swap: " << sizeof(T) << " bytes";
917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshu64 MaybeSwap(u64 value, bool swap) {
967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap)
977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return bswap_64(value);
987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return value;
997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshu32 MaybeSwap(u32 value, bool swap) {
1027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap)
1037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return bswap_32(value);
1047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return value;
1057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshu8 ReverseByte(u8 x) {
1087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  x = (x & 0xf0) >> 4 | (x & 0x0f) << 4;  // exchange nibbles
1097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  x = (x & 0xcc) >> 2 | (x & 0x33) << 2;  // exchange pairs
1107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  x = (x & 0xaa) >> 1 | (x & 0x55) << 1;  // exchange neighbors
1117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return x;
1127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// If field points to the start of a bitfield padded to len bytes, this
1157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// performs an endian swap of the bitfield, assuming the compiler that produced
1167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// it conforms to the same ABI (bitfield layout is not completely specified by
1177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// the language).
1187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid SwapBitfieldOfBits(u8* field, size_t len) {
1197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < len; i++) {
1207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    field[i] = ReverseByte(field[i]);
1217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// The code currently assumes that the compiler will not add any padding to the
1257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// various structs.  These CHECKs make sure that this is true.
1267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid CheckNoEventHeaderPadding() {
1277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_event_header header;
1287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(sizeof(header),
1297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(header.type) + sizeof(header.misc) + sizeof(header.size));
1307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid CheckNoPerfEventAttrPadding() {
1337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_event_attr attr;
1347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(sizeof(attr),
1357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           (reinterpret_cast<u64>(&attr.__reserved_2) -
1367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            reinterpret_cast<u64>(&attr)) +
1377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(attr.__reserved_2));
1387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid CheckNoEventTypePadding() {
1417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_trace_event_type event_type;
1427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(sizeof(event_type),
1437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(event_type.event_id) + sizeof(event_type.name));
1447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid CheckNoBuildIDEventPadding() {
1477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  build_id_event event;
1487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(sizeof(event),
1497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(event.header.type) + sizeof(event.header.misc) +
1507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(event.header.size) + sizeof(event.pid) +
1517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           sizeof(event.build_id));
1527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Creates/updates a build id event with |build_id| and |filename|.
1557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Passing "" to |build_id| or |filename| will leave the corresponding field
1567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// unchanged (in which case |event| must be non-null).
1577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// If |event| is null or is not large enough, a new event will be created.
1587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// In this case, if |event| is non-null, it will be freed.
1597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Otherwise, updates the fields of the existing event.
1607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// |new_misc| indicates kernel vs user space, and is only used to fill in the
1617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// |header.misc| field of new events.
1627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// In either case, returns a pointer to the event containing the updated data,
1637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// or NULL in the case of a failure.
1647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbuild_id_event* CreateOrUpdateBuildID(const string& build_id,
1657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      const string& filename,
1667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      uint16_t new_misc,
1677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      build_id_event* event) {
1687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // When creating an event from scratch, build id and filename must be present.
1697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!event && (build_id.empty() || filename.empty()))
1707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return NULL;
1717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t new_len = GetUint64AlignedStringLength(
1727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      filename.empty() ? event->filename : filename);
1737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // If event is null, or we don't have enough memory, allocate more memory, and
1757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // switch the new pointer with the existing pointer.
1767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t new_size = sizeof(*event) + new_len;
1777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!event || new_size > event->header.size) {
1787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_event* new_event = CallocMemoryForBuildID(new_size);
1797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event) {
1817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Copy over everything except the filename and free the event.
1827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // It is guaranteed that we are changing the filename - otherwise, the old
1837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // size and the new size would be equal.
1847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *new_event = *event;
1857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      free(event);
1867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else {
1877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Fill in the fields appropriately.
1887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      new_event->header.type = HEADER_BUILD_ID;
1897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      new_event->header.misc = new_misc;
1907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      new_event->pid = kDefaultBuildIDEventPid;
1917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
1927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event = new_event;
1937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Here, event is the pointer to the build_id_event that we are keeping.
1967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Update the event's size, build id, and filename.
1977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!build_id.empty() &&
1987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      !StringToHex(build_id, event->build_id, arraysize(event->build_id))) {
1997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    free(event);
2007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return NULL;
2017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!filename.empty())
2047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK_GT(snprintf(event->filename, new_len, "%s", filename.c_str()), 0);
2057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  event->header.size = new_size;
2077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return event;
2087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Reads |size| bytes from |buffer| into |dest| and advances |src_offset|.
2117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool ReadDataFromBuffer(const ConstBufferWithSize& buffer,
2127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                        size_t size,
2137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                        const string& value_name,
2147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                        size_t* src_offset,
2157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                        void* dest) {
2167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t end_offset = *src_offset + size / sizeof(*buffer.ptr);
2177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (buffer.size < end_offset) {
2187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Not enough bytes to read " << value_name
2197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << ". Requested " << size << " bytes";
2207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memcpy(dest, buffer.ptr + *src_offset, size);
2237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  *src_offset = end_offset;
2247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
2257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Reads a CStringWithLength from |buffer| into |dest|, and advances the offset.
2287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool ReadStringFromBuffer(const ConstBufferWithSize& buffer,
2297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          bool is_cross_endian,
2307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          size_t* offset,
2317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          CStringWithLength* dest) {
2327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(buffer, sizeof(dest->len), "string length",
2337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          offset, &dest->len)) {
2347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian)
2377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&dest->len);
2387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (buffer.size < *offset + dest->len) {
2407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Not enough bytes to read string";
2417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  dest->str = string(buffer.ptr + *offset);
2447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  *offset += dest->len / sizeof(*buffer.ptr);
2457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
2467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Read read info from perf data.  Corresponds to sample format type
2497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// PERF_SAMPLE_READ.
2507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint64_t* ReadReadInfo(const uint64_t* array,
2517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                           bool swap_bytes,
2527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                           uint64_t read_format,
2537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                           struct perf_sample* sample) {
2547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
2557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->read.time_enabled = *array++;
2567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
2577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->read.time_running = *array++;
2587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (read_format & PERF_FORMAT_ID)
2597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->read.one.id = *array++;
2607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap_bytes) {
2627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&sample->read.time_enabled);
2637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&sample->read.time_running);
2647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&sample->read.one.id);
2657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return array;
2687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Read call chain info from perf data.  Corresponds to sample format type
2717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// PERF_SAMPLE_CALLCHAIN.
2727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint64_t* ReadCallchain(const uint64_t* array,
2737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            bool swap_bytes,
2747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            struct perf_sample* sample) {
2757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Make sure there is no existing allocated memory in |sample->callchain|.
2767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(static_cast<void*>(NULL), sample->callchain);
2777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // The callgraph data consists of a uint64_t value |nr| followed by |nr|
2797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // addresses.
2807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t callchain_size = *array++;
2817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap_bytes)
2827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&callchain_size);
2837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  struct ip_callchain* callchain =
2847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      reinterpret_cast<struct ip_callchain*>(new uint64_t[callchain_size + 1]);
2857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  callchain->nr = callchain_size;
2867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < callchain_size; ++i) {
2877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    callchain->ips[i] = *array++;
2887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (swap_bytes)
2897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&callchain->ips[i]);
2907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  sample->callchain = callchain;
2927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return array;
2947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Read raw info from perf data.  Corresponds to sample format type
2977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// PERF_SAMPLE_RAW.
2987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint64_t* ReadRawData(const uint64_t* array,
2997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          bool swap_bytes,
3007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          struct perf_sample* sample) {
3017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // First read the size.
3027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const uint32_t* ptr = reinterpret_cast<const uint32_t*>(array);
3037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  sample->raw_size = *ptr++;
3047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap_bytes)
3057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&sample->raw_size);
3067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Allocate space for and read the raw data bytes.
3087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  sample->raw_data = new uint8_t[sample->raw_size];
3097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memcpy(sample->raw_data, ptr, sample->raw_size);
3107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Determine the bytes that were read, and align to the next 64 bits.
3127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  int bytes_read = AlignSize(sizeof(sample->raw_size) + sample->raw_size,
3137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             sizeof(uint64_t));
3147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  array += bytes_read / sizeof(uint64_t);
3157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return array;
3177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
3187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Read call chain info from perf data.  Corresponds to sample format type
3207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// PERF_SAMPLE_CALLCHAIN.
3217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint64_t* ReadBranchStack(const uint64_t* array,
3227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              bool swap_bytes,
3237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              struct perf_sample* sample) {
3247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Make sure there is no existing allocated memory in
3257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // |sample->branch_stack|.
3267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(static_cast<void*>(NULL), sample->branch_stack);
3277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // The branch stack data consists of a uint64_t value |nr| followed by |nr|
3297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // branch_entry structs.
3307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t branch_stack_size = *array++;
3317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (swap_bytes)
3327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&branch_stack_size);
3337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  struct branch_stack* branch_stack =
3347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      reinterpret_cast<struct branch_stack*>(
3357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh          new uint8_t[sizeof(uint64_t) +
3367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    branch_stack_size * sizeof(struct branch_entry)]);
3377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  branch_stack->nr = branch_stack_size;
3387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < branch_stack_size; ++i) {
3397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    memcpy(&branch_stack->entries[i], array, sizeof(struct branch_entry));
3407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array += sizeof(struct branch_entry) / sizeof(*array);
3417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (swap_bytes) {
3427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&branch_stack->entries[i].from);
3437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&branch_stack->entries[i].to);
3447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  sample->branch_stack = branch_stack;
3477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return array;
3497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
3507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t ReadPerfSampleFromData(const perf_event_type event_type,
3527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              const uint64_t* array,
3537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              const uint64_t sample_fields,
3547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              const uint64_t read_format,
3557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              bool swap_bytes,
356e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh                              const perf_event_attr &attr0,
357e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh                              size_t n_attrs,
3587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              struct perf_sample* sample) {
3597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const uint64_t* initial_array_ptr = array;
3607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  union {
3627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t val32[sizeof(uint64_t) / sizeof(uint32_t)];
3637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t val64;
3647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  };
3657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // See structure for PERF_RECORD_SAMPLE in kernel/perf_event.h
3677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // and compare sample_id when sample_id_all is set.
3687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // NB: For sample_id, sample_fields has already been masked to the set
3707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // of fields in that struct by GetSampleFieldsForEventType. That set
3717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // of fields is mostly in the same order as PERF_RECORD_SAMPLE, with
3727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // the exception of PERF_SAMPLE_IDENTIFIER.
3737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // PERF_SAMPLE_IDENTIFIER is in a different location depending on
3757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // if this is a SAMPLE event or the sample_id of another event.
3767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_type == PERF_RECORD_SAMPLE) {
3777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // { u64                   id;       } && PERF_SAMPLE_IDENTIFIER
3787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
3797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample->id = MaybeSwap(*array++, swap_bytes);
3807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   ip;       } && PERF_SAMPLE_IP
3847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_IP) {
3857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->ip = MaybeSwap(*array++, swap_bytes);
3867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   pid, tid; } && PERF_SAMPLE_TID
3897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_TID) {
3907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val64 = *array++;
3917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->pid = MaybeSwap(val32[0], swap_bytes);
3927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->tid = MaybeSwap(val32[1], swap_bytes);
3937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   time;     } && PERF_SAMPLE_TIME
3967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_TIME) {
3977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->time = MaybeSwap(*array++, swap_bytes);
3987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   addr;     } && PERF_SAMPLE_ADDR
4017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_ADDR) {
4027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->addr = MaybeSwap(*array++, swap_bytes);
4037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   id;       } && PERF_SAMPLE_ID
4067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_ID) {
4077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->id = MaybeSwap(*array++, swap_bytes);
4087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   stream_id;} && PERF_SAMPLE_STREAM_ID
4117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_STREAM_ID) {
4127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->stream_id = MaybeSwap(*array++, swap_bytes);
4137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   cpu, res; } && PERF_SAMPLE_CPU
4167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_CPU) {
4177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val64 = *array++;
4187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->cpu = MaybeSwap(val32[0], swap_bytes);
4197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // sample->res = MaybeSwap(*val32[1], swap_bytes);  // not implemented?
4207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // This is the location of PERF_SAMPLE_IDENTIFIER in struct sample_id.
4237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_type != PERF_RECORD_SAMPLE) {
4247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // { u64                   id;       } && PERF_SAMPLE_IDENTIFIER
4257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
4267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample->id = MaybeSwap(*array++, swap_bytes);
4277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
4287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
4317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // The remaining fields are only in PERF_RECORD_SAMPLE
4327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
4337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   period;   } && PERF_SAMPLE_PERIOD
4357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_PERIOD) {
4367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample->period = MaybeSwap(*array++, swap_bytes);
4377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { struct read_format    values;   } && PERF_SAMPLE_READ
4407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_READ) {
4417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // TODO(cwp-team): support grouped read info.
4427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_format & PERF_FORMAT_GROUP)
4437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return 0;
4447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array = ReadReadInfo(array, swap_bytes, read_format, sample);
4457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   nr,
4487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   u64                   ips[nr];  } && PERF_SAMPLE_CALLCHAIN
4497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_CALLCHAIN) {
4507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array = ReadCallchain(array, swap_bytes, sample);
4517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   size;
4547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   char                  data[size];}&& PERF_SAMPLE_RAW
4557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_RAW) {
4567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array = ReadRawData(array, swap_bytes, sample);
4577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   nr;
4607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
4617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_BRANCH_STACK) {
4627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array = ReadBranchStack(array, swap_bytes, sample);
4637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
465e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  // { u64                   abi,
466e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //   u64                   regs[nr];  } && PERF_SAMPLE_REGS_USER
467e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  if (sample_fields & PERF_SAMPLE_REGS_USER) {
468e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    uint64_t abi = MaybeSwap(*array++, swap_bytes);
469e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    if (abi != 0) {
470e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      assert(n_attrs == 1);
471e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      uint64_t reg_mask = attr0.sample_regs_user;
472e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      size_t bit_nr = 0;
473e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      for (size_t i = 0; i < 64; ++i) {
474e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh        if ((reg_mask >> i) & 1) {
475e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh          bit_nr++;
476e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh        }
477e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      }
478e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      array += bit_nr;
479e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    }
480e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  }
481e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh
482e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  // { u64                   size,
483e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //   u64                   regs[nr];  } && PERF_SAMPLE_STACK_USER
484e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  if (sample_fields & PERF_SAMPLE_STACK_USER) {
485e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    uint64_t size = MaybeSwap(*array++, swap_bytes);
486e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    if (size != 0) {
487e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      array += (size / sizeof(uint64_t));
488e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      array += 1;  // for dyn_size
489e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    }
490e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  }
491e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh
4927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  static const u64 kUnimplementedSampleFields =
4937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      PERF_SAMPLE_WEIGHT     |
4947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      PERF_SAMPLE_DATA_SRC   |
4957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      PERF_SAMPLE_TRANSACTION;
4967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & kUnimplementedSampleFields) {
4987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(WARNING) << "Unimplemented sample fields 0x"
4997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << std::hex << (sample_fields & kUnimplementedSampleFields);
5007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & ~(PERF_SAMPLE_MAX-1)) {
5037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(WARNING) << "Unrecognized sample fields 0x"
5047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << std::hex << (sample_fields & ~(PERF_SAMPLE_MAX-1));
5057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (array - initial_array_ptr) * sizeof(uint64_t);
5087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
5097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t WritePerfSampleToData(const perf_event_type event_type,
5117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             const struct perf_sample& sample,
5127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             const uint64_t sample_fields,
5137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             const uint64_t read_format,
5147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             uint64_t* array) {
5157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const uint64_t* initial_array_ptr = array;
5167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  union {
5187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t val32[sizeof(uint64_t) / sizeof(uint32_t)];
5197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t val64;
5207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  };
5217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // See notes at the top of ReadPerfSampleFromData regarding the structure
5237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // of PERF_RECORD_SAMPLE, sample_id, and PERF_SAMPLE_IDENTIFIER, as they
5247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // all apply here as well.
5257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // PERF_SAMPLE_IDENTIFIER is in a different location depending on
5277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // if this is a SAMPLE event or the sample_id of another event.
5287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_type == PERF_RECORD_SAMPLE) {
5297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // { u64                   id;       } && PERF_SAMPLE_IDENTIFIER
5307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
5317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.id;
5327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
5337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   ip;       } && PERF_SAMPLE_IP
5367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_IP) {
5377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.ip;
5387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   pid, tid; } && PERF_SAMPLE_TID
5417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_TID) {
5427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val32[0] = sample.pid;
5437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val32[1] = sample.tid;
5447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = val64;
5457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   time;     } && PERF_SAMPLE_TIME
5487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_TIME) {
5497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.time;
5507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   addr;     } && PERF_SAMPLE_ADDR
5537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_ADDR) {
5547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.addr;
5557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   id;       } && PERF_SAMPLE_ID
5587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_ID) {
5597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.id;
5607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   stream_id;} && PERF_SAMPLE_STREAM_ID
5637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_STREAM_ID) {
5647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.stream_id;
5657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   cpu, res; } && PERF_SAMPLE_CPU
5687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_CPU) {
5697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val32[0] = sample.cpu;
5707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // val32[1] = sample.res;  // not implemented?
5717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    val32[1] = 0;
5727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = val64;
5737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // This is the location of PERF_SAMPLE_IDENTIFIER in struct sample_id.
5767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_type != PERF_RECORD_SAMPLE) {
5777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // { u64                   id;       } && PERF_SAMPLE_IDENTIFIER
5787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
5797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.id;
5807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
5817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
5847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // The remaining fields are only in PERF_RECORD_SAMPLE
5857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
5867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   period;   } && PERF_SAMPLE_PERIOD
5887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_PERIOD) {
5897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *array++ = sample.period;
5907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { struct read_format    values;   } && PERF_SAMPLE_READ
5937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_READ) {
5947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // TODO(cwp-team): support grouped read info.
5957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_format & PERF_FORMAT_GROUP)
5967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return 0;
5977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
5987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.read.time_enabled;
5997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
6007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.read.time_running;
6017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_format & PERF_FORMAT_ID)
6027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.read.one.id;
6037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
6047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   nr,
6067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   u64                   ips[nr];  } && PERF_SAMPLE_CALLCHAIN
6077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_CALLCHAIN) {
6087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!sample.callchain) {
6097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Expecting callchain data, but none was found.";
6107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else {
6117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.callchain->nr;
6127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      for (size_t i = 0; i < sample.callchain->nr; ++i)
6137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        *array++ = sample.callchain->ips[i];
6147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
6157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
6167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u32                   size;
6187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   char                  data[size];}&& PERF_SAMPLE_RAW
6197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_RAW) {
6207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t* ptr = reinterpret_cast<uint32_t*>(array);
6217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *ptr++ = sample.raw_size;
6227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    memcpy(ptr, sample.raw_data, sample.raw_size);
6237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Update the data read pointer after aligning to the next 64 bytes.
6257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    int num_bytes = AlignSize(sizeof(sample.raw_size) + sample.raw_size,
6267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              sizeof(uint64_t));
6277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array += num_bytes / sizeof(uint64_t);
6287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
6297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // { u64                   nr;
6317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
6327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_fields & PERF_SAMPLE_BRANCH_STACK) {
6337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!sample.branch_stack) {
6347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Expecting branch stack data, but none was found.";
6357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else {
6367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *array++ = sample.branch_stack->nr;
6377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      for (size_t i = 0; i < sample.branch_stack->nr; ++i) {
6387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        *array++ = sample.branch_stack->entries[i].from;
6397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        *array++ = sample.branch_stack->entries[i].to;
6407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        memcpy(array++, &sample.branch_stack->entries[i].flags,
6417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               sizeof(uint64_t));
6427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      }
6437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
6447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
6457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
646e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //
647e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  // Unsupported sample types.
648e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //
649e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  CHECK(!(sample_fields & PERF_SAMPLE_STACK_USER|PERF_SAMPLE_REGS_USER));
650e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh
6517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (array - initial_array_ptr) * sizeof(uint64_t);
6527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace
6557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshPerfReader::~PerfReader() {
6577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Free allocated memory.
6587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < build_id_events_.size(); ++i)
6597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (build_id_events_[i])
6607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      free(build_id_events_[i]);
6617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfReader::PerfizeBuildIDString(string* build_id) {
6647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  build_id->resize(kBuildIDStringLength, '0');
6657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfReader::UnperfizeBuildIDString(string* build_id) {
6687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const size_t kPaddingSize = 8;
6697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const string kBuildIDPadding = string(kPaddingSize, '0');
6707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Remove kBuildIDPadding from the end of build_id until we cannot remove any
6727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // more, or removing more would cause the build id to be empty.
6737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while (build_id->size() > kPaddingSize &&
6747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh         build_id->substr(build_id->size() - kPaddingSize) == kBuildIDPadding) {
6757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id->resize(build_id->size() - kPaddingSize);
6767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
6777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadFile(const string& filename) {
6807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::vector<char> data;
6817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadFileToData(filename, &data))
6827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
6837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ReadFromVector(data);
6847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadFromVector(const std::vector<char>& data) {
6877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ReadFromPointer(&data[0], data.size());
6887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadFromString(const string& str) {
6917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ReadFromPointer(str.c_str(), str.size());
6927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
6937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadFromPointer(const char* perf_data, size_t size) {
6957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const ConstBufferWithSize data = { perf_data, size };
6967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
6977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (data.size == 0)
6987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
6997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadHeader(data))
7007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
7017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Check if it is normal perf data.
7037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (header_.size == sizeof(header_)) {
7047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    DLOG(INFO) << "Perf data is in normal format.";
7057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    metadata_mask_ = header_.adds_features[0];
7067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return (ReadAttrs(data) && ReadEventTypes(data) && ReadData(data)
7077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            && ReadMetadata(data));
7087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Otherwise it is piped data.
7117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  LOG(ERROR) << "Internal error: no support for piped data";
7127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return false;
7137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::Localize(
7167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const std::map<string, string>& build_ids_to_filenames) {
7177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::map<string, string> perfized_build_ids_to_filenames;
7187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::map<string, string>::const_iterator it;
7197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (it = build_ids_to_filenames.begin();
7207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh       it != build_ids_to_filenames.end();
7217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh       ++it) {
7227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string build_id = it->first;
7237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    PerfizeBuildIDString(&build_id);
7247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    perfized_build_ids_to_filenames[build_id] = it->second;
7257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::map<string, string> filename_map;
7287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < build_id_events_.size(); ++i) {
7297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_event* event = build_id_events_[i];
7307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string build_id = HexToString(event->build_id, kBuildIDArraySize);
7317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (perfized_build_ids_to_filenames.find(build_id) ==
7327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        perfized_build_ids_to_filenames.end()) {
7337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
7347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
7357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string new_name = perfized_build_ids_to_filenames.at(build_id);
7377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    filename_map[string(event->filename)] = new_name;
7387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_event* new_event = CreateOrUpdateBuildID("", new_name, 0, event);
7397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK(new_event);
7407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_events_[i] = new_event;
7417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  LocalizeUsingFilenames(filename_map);
7447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
7457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::LocalizeUsingFilenames(
7487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const std::map<string, string>& filename_map) {
7497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  LocalizeMMapFilenames(filename_map);
7507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < build_id_events_.size(); ++i) {
7517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_event* event = build_id_events_[i];
7527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string old_name = event->filename;
7537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (filename_map.find(event->filename) != filename_map.end()) {
7557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      const string& new_name = filename_map.at(old_name);
7567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      build_id_event* new_event = CreateOrUpdateBuildID("", new_name, 0, event);
7577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      CHECK(new_event);
7587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      build_id_events_[i] = new_event;
7597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
7607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
7627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfReader::GetFilenames(std::vector<string>* filenames) const {
7657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::set<string> filename_set;
7667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  GetFilenamesAsSet(&filename_set);
7677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  filenames->clear();
7687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  filenames->insert(filenames->begin(), filename_set.begin(),
7697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    filename_set.end());
7707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfReader::GetFilenamesAsSet(std::set<string>* filenames) const {
7737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  filenames->clear();
7747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < events_.size(); ++i) {
7757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const event_t& event = *events_[i];
7767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event.header.type == PERF_RECORD_MMAP)
7777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      filenames->insert(event.mmap.filename);
7787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event.header.type == PERF_RECORD_MMAP2)
7797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      filenames->insert(event.mmap2.filename);
7807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfReader::GetFilenamesToBuildIDs(
7847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    std::map<string, string>* filenames_to_build_ids) const {
7857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  filenames_to_build_ids->clear();
7867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < build_id_events_.size(); ++i) {
7877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const build_id_event& event = *build_id_events_[i];
7887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string build_id = HexToString(event.build_id, kBuildIDArraySize);
7897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    (*filenames_to_build_ids)[event.filename] = build_id;
7907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
7917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
7927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
7937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::IsSupportedEventType(uint32_t type) {
7947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  switch (type) {
7957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_SAMPLE:
7967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP:
7977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP2:
7987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_FORK:
7997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_EXIT:
8007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_COMM:
8017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_LOST:
8027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_THROTTLE:
8037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_UNTHROTTLE:
804e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
80518b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  case SIMPLE_PERF_RECORD_DSO:
80618b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  case SIMPLE_PERF_RECORD_SYMBOL:
80718b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  case SIMPLE_PERF_RECORD_SPLIT:
80818b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  case SIMPLE_PERF_RECORD_SPLIT_END:
8097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return true;
8107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_READ:
8117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MAX:
8127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
8137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  default:
8147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(FATAL) << "Unknown event type " << type;
8157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
8167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
8187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadPerfSampleInfo(const event_t& event,
8207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                    struct perf_sample* sample) const {
8217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK(sample);
8227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!IsSupportedEventType(event.header.type)) {
8247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Unsupported event type " << event.header.type;
8257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
8267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
828e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  // We want to completely ignore these records
82918b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  if (event.header.type == SIMPLE_PERF_RECORD_KERNEL_SYMBOL ||
83018b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_DSO ||
83118b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SYMBOL ||
83218b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SPLIT ||
83318b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SPLIT_END)
834e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    return true;
835e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh
8367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t sample_format = GetSampleFieldsForEventType(event.header.type,
8377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                                       sample_type_);
8387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t offset = GetPerfSampleDataOffset(event);
8397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size_read = ReadPerfSampleFromData(
8407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      static_cast<perf_event_type>(event.header.type),
8417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      reinterpret_cast<const uint64_t*>(&event) + offset / sizeof(uint64_t),
8427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample_format,
8437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      read_format_,
8447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      is_cross_endian_,
845e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      attrs_[0].attr,
846e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      attrs_.size(),
8477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample);
8487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t expected_size = event.header.size - offset;
8507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (size_read != expected_size) {
8517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Read " << size_read << " bytes, expected "
8527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << expected_size << " bytes.";
8537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (size_read == expected_size);
8567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
8577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::WritePerfSampleInfo(const perf_sample& sample,
8597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                     event_t* event) const {
8607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK(event);
8617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!IsSupportedEventType(event->header.type)) {
8637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Unsupported event type " << event->header.type;
8647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
8657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t sample_format = GetSampleFieldsForEventType(event->header.type,
8687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                                       sample_type_);
8697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t offset = GetPerfSampleDataOffset(*event);
8707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t expected_size = event->header.size - offset;
8727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memset(reinterpret_cast<uint8_t*>(event) + offset, 0, expected_size);
8737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size_written = WritePerfSampleToData(
8747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      static_cast<perf_event_type>(event->header.type),
8757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample,
8767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sample_format,
8777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      read_format_,
8787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      reinterpret_cast<uint64_t*>(event) + offset / sizeof(uint64_t));
8797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (size_written != expected_size) {
8807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Wrote " << size_written << " bytes, expected "
8817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << expected_size << " bytes.";
8827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (size_written == expected_size);
8857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
8867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
8877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadHeader(const ConstBufferWithSize& data) {
8887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CheckNoEventHeaderPadding();
8897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t offset = 0;
8907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(piped_header_), "header magic",
8917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          &offset, &piped_header_)) {
8927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
8937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
8947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (piped_header_.magic != kPerfMagic &&
8957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      piped_header_.magic != bswap_64(kPerfMagic)) {
8967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Read wrong magic. Expected: 0x" << std::hex << kPerfMagic
8977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << " or 0x" << std::hex << bswap_64(kPerfMagic)
8987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << " Got: 0x" << std::hex << piped_header_.magic;
8997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  is_cross_endian_ = (piped_header_.magic != kPerfMagic);
9027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
9037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&piped_header_.size);
9047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Header can be a piped header.
9067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (piped_header_.size == sizeof(piped_header_))
9077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return true;
9087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Re-read full header
9107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  offset = 0;
9117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(header_), "header data",
9127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          &offset, &header_)) {
9137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
9167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&header_.size);
9177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  DLOG(INFO) << "event_types.size: " << header_.event_types.size;
9197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  DLOG(INFO) << "event_types.offset: " << header_.event_types.offset;
9207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
9227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
9237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadAttrs(const ConstBufferWithSize& data) {
9257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t num_attrs = header_.attrs.size / header_.attr_size;
9267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t offset = header_.attrs.offset;
9277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < num_attrs; i++) {
9287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadAttr(data, &offset))
9297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
9307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
9327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
9337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadAttr(const ConstBufferWithSize& data, size_t* offset) {
9357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfFileAttr attr;
9367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadEventAttr(data, offset, &attr.attr))
9377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_file_section ids;
9407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(ids), "ID section info", offset, &ids))
9417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_) {
9437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&ids.offset);
9447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&ids.size);
9457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t num_ids = ids.size / sizeof(decltype(attr.ids)::value_type);
9487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Convert the offset from u64 to size_t.
9497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t ids_offset = ids.offset;
9507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadUniqueIDs(data, num_ids, &ids_offset, &attr.ids))
9517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  attrs_.push_back(attr);
9537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
9547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
9557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshu32 PerfReader::ReadPerfEventAttrSize(const ConstBufferWithSize& data,
9577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      size_t attr_offset) {
9587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  static_assert(std::is_same<decltype(perf_event_attr::size), u32>::value,
9597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                "ReadPerfEventAttrSize return type should match "
9607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                "perf_event_attr.size");
9617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  u32 attr_size;
9627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t attr_size_offset = attr_offset + offsetof(perf_event_attr, size);
9637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(perf_event_attr::size),
9647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          "attr.size", &attr_size_offset, &attr_size)) {
9657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return kuint32max;
9667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return MaybeSwap(attr_size, is_cross_endian_);
9687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
9697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadEventAttr(const ConstBufferWithSize& data, size_t* offset,
9717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                               perf_event_attr* attr) {
9727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CheckNoPerfEventAttrPadding();
9737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::memset(attr, 0, sizeof(*attr));
9757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //*attr = {0};
9767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // read just size first
9787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  u32 attr_size = ReadPerfEventAttrSize(data, *offset);
9797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (attr_size == kuint32max) {
9807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // now read the the struct.
9847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, attr_size, "attribute", offset,
9857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          reinterpret_cast<char*>(attr))) {
9867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
9877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
9887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_) {
9907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Depending on attr->size, some of these might not have actually been
9917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // read. This is okay: they are zero.
9927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->type);
9937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->size);
9947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->config);
9957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->sample_period);
9967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->sample_type);
9977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->read_format);
9987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
9997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // NB: This will also reverse precise_ip : 2 as if it was two fields:
10007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    auto *const bitfield_start = &attr->read_format + 1;
10017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    SwapBitfieldOfBits(reinterpret_cast<u8*>(bitfield_start),
10027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                       sizeof(u64));
10037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // ... So swap it back:
10047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const auto tmp = attr->precise_ip;
10057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    attr->precise_ip = (tmp & 0x2) >> 1 | (tmp & 0x1) << 1;
10067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->wakeup_events);  // union with wakeup_watermark
10087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->bp_type);
10097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->bp_addr);        // union with config1
10107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->bp_len);         // union with config2
10117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->branch_sample_type);
10127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->sample_regs_user);
10137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&attr->sample_stack_user);
10147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(attr_size, attr->size);
10177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // The actual perf_event_attr data size might be different from the size of
10187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // the struct definition.  Check against perf_event_attr's |size| field.
10197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  attr->size = sizeof(*attr);
10207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Assign sample type if it hasn't been assigned, otherwise make sure all
10227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // subsequent attributes have the same sample type bits set.
10237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_type_ == 0) {
10247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    sample_type_ = attr->sample_type;
10257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  } else {
10267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK_EQ(sample_type_, attr->sample_type)
10277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        << "Event type sample format does not match sample format of other "
10287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        << "event type.";
10297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (read_format_ == 0) {
10327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    read_format_ = attr->read_format;
10337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  } else {
10347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK_EQ(read_format_, attr->read_format)
10357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        << "Event type read format does not match read format of other event "
10367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        << "types.";
10377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
10407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
10417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadUniqueIDs(const ConstBufferWithSize& data, size_t num_ids,
10437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                               size_t* offset, std::vector<u64>* ids) {
10447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  ids->resize(num_ids);
10457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t j = 0; j < num_ids; j++) {
10467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, sizeof(ids->at(j)), "ID", offset,
10477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &ids->at(j))) {
10487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
10497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
10507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_)
10517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&ids->at(j));
10527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
10547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
10557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadEventTypes(const ConstBufferWithSize& data) {
10577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t num_event_types = header_.event_types.size /
10587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      sizeof(struct perf_trace_event_type);
10597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(sizeof(perf_trace_event_type) * num_event_types,
10607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           header_.event_types.size);
10617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t offset = header_.event_types.offset;
10627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < num_event_types; ++i) {
10637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadEventType(data, &offset))
10647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
10657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
10677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
10687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadEventType(const ConstBufferWithSize& data,
10707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                               size_t* offset) {
10717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CheckNoEventTypePadding();
10727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_trace_event_type type;
10737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memset(&type, 0, sizeof(type));
10747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(type.event_id), "event id",
10757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          offset, &type.event_id)) {
10767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
10777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
10787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const char* event_name = reinterpret_cast<const char*>(data.ptr + *offset);
10797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_GT(snprintf(type.name, sizeof(type.name), "%s", event_name), 0);
10807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  *offset += sizeof(type.name);
10817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  event_types_.push_back(type);
10827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
10837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
10847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadData(const ConstBufferWithSize& data) {
10867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  u64 data_remaining_bytes = header_.data.size;
10877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t offset = header_.data.offset;
10887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while (data_remaining_bytes != 0) {
10897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (data.size < offset) {
10907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Not enough data to read a perf event.";
10917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
10927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
10937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
10947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const event_t* event = reinterpret_cast<const event_t*>(data.ptr + offset);
10957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadPerfEventBlock(*event))
10967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
10977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    data_remaining_bytes -= event->header.size;
10987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset += event->header.size;
10997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
11007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  DLOG(INFO) << "Number of events stored: "<< events_.size();
11027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
11037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
11047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadMetadata(const ConstBufferWithSize& data) {
11067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t offset = header_.data.offset + header_.data.size;
11077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
11097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if ((metadata_mask_ & (1 << type)) == 0)
11107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
11117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (data.size < offset) {
11137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Not enough data to read offset and size of metadata.";
11147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
11157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
11167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    u64 metadata_offset, metadata_size;
11187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, sizeof(metadata_offset), "metadata offset",
11197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &offset, &metadata_offset) ||
11207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        !ReadDataFromBuffer(data, sizeof(metadata_size), "metadata size",
11217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &offset, &metadata_size)) {
11227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
11237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
11247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (data.size < metadata_offset + metadata_size) {
11267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Not enough data to read metadata.";
11277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
11287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
11297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    switch (type) {
11317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_TRACING_DATA:
11327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadTracingMetadata(data, metadata_offset, metadata_size)) {
11337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      }
11357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_BUILD_ID:
11377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadBuildIDMetadata(data, type, metadata_offset, metadata_size))
11387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_HOSTNAME:
11417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_OSRELEASE:
11427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_VERSION:
11437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_ARCH:
11447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_CPUDESC:
11457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_CPUID:
11467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_CMDLINE:
11477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadStringMetadata(data, type, metadata_offset, metadata_size))
11487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_NRCPUS:
11517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadUint32Metadata(data, type, metadata_offset, metadata_size))
11527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_TOTAL_MEM:
11557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadUint64Metadata(data, type, metadata_offset, metadata_size))
11567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_EVENT_DESC:
11597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_CPU_TOPOLOGY:
11617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadCPUTopologyMetadata(data, type, metadata_offset, metadata_size))
11627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_NUMA_TOPOLOGY:
11657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (!ReadNUMATopologyMetadata(data, type, metadata_offset, metadata_size))
11667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
11677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_PMU_MAPPINGS:
11697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // ignore for now
11707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
11717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case HEADER_BRANCH_STACK:
11737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
11747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    default: LOG(INFO) << "Unsupported metadata type: " << type;
11757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
11767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
11777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
11787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Event type events are optional in some newer versions of perf. They
11807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // contain the same information that is already in |attrs_|. Make sure the
11817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // number of event types matches the number of attrs, but only if there are
11827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // event type events present.
11837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_types_.size() > 0) {
11847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event_types_.size() != attrs_.size()) {
11857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Mismatch between number of event type events and attr "
11867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << "events: " << event_types_.size() << " vs "
11877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << attrs_.size();
11887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
11897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
11907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    metadata_mask_ |= (1 << HEADER_EVENT_DESC);
11917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
11927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
11937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
11947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
11957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadBuildIDMetadata(const ConstBufferWithSize& data, u32 /*type*/,
11967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                     size_t offset, size_t size) {
11977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CheckNoBuildIDEventPadding();
11987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while (size > 0) {
11997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Make sure there is enough data for everything but the filename.
12007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (data.size < offset + sizeof(build_id_event) / sizeof(*data.ptr)) {
12017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Not enough bytes to read build id event";
12027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
12047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const build_id_event* temp_ptr =
12067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        reinterpret_cast<const build_id_event*>(data.ptr + offset);
12077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    u16 event_size = temp_ptr->header.size;
12087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_)
12097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_size);
12107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Make sure there is enough data for the rest of the event.
12127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (data.size < offset + event_size / sizeof(*data.ptr)) {
12137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Not enough bytes to read build id event";
12147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
12167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Allocate memory for the event and copy over the bytes.
12187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_event* event = CallocMemoryForBuildID(event_size);
12197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, event_size, "build id event",
12207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &offset, event)) {
12217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
12237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_) {
12247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event->header.type);
12257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event->header.misc);
12267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event->header.size);
12277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event->pid);
12287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
12297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size -= event_size;
12307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Perf tends to use more space than necessary, so fix the size.
12327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event->header.size =
12337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        sizeof(*event) + GetUint64AlignedStringLength(event->filename);
12347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    build_id_events_.push_back(event);
12357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
12367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
12387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
12397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadStringMetadata(const ConstBufferWithSize& data, u32 type,
12417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                    size_t offset, size_t size) {
12427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfStringMetadata str_data;
12437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  str_data.type = type;
12447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t start_offset = offset;
12467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Skip the number of string data if it is present.
12477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (NeedsNumberOfStringData(type))
12487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset += sizeof(num_string_data_type) / sizeof(*data.ptr);
12497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while ((offset - start_offset) < size) {
12517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CStringWithLength single_string;
12527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadStringFromBuffer(data, is_cross_endian_, &offset, &single_string))
12537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    str_data.data.push_back(single_string);
12557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
12567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  string_metadata_.push_back(str_data);
12587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
12597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
12607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadUint32Metadata(const ConstBufferWithSize& data, u32 type,
12627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                    size_t offset, size_t size) {
12637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfUint32Metadata uint32_data;
12647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint32_data.type = type;
12657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t start_offset = offset;
12677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while (size > offset - start_offset) {
12687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t item;
12697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, sizeof(item), "uint32_t data", &offset,
12707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &item))
12717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_)
12747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&item);
12757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_data.data.push_back(item);
12777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
12787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint32_metadata_.push_back(uint32_data);
12807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
12817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
12827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadUint64Metadata(const ConstBufferWithSize& data, u32 type,
12847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                    size_t offset, size_t size) {
12857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfUint64Metadata uint64_data;
12867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_data.type = type;
12877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t start_offset = offset;
12897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  while (size > offset - start_offset) {
12907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t item;
12917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, sizeof(item), "uint64_t data", &offset,
12927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &item))
12937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
12947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_)
12967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&item);
12977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
12987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_data.data.push_back(item);
12997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_metadata_.push_back(uint64_data);
13027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
13037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
13047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadCPUTopologyMetadata(
13067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const ConstBufferWithSize& data, u32 /*type*/, size_t offset, size_t /*size*/) {
13077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  num_siblings_type num_core_siblings;
13087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(num_core_siblings), "num cores",
13097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          &offset, &num_core_siblings)) {
13107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
13117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
13137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&num_core_siblings);
13147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  cpu_topology_.core_siblings.resize(num_core_siblings);
13167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < num_core_siblings; ++i) {
13177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadStringFromBuffer(data, is_cross_endian_, &offset,
13187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              &cpu_topology_.core_siblings[i])) {
13197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
13207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
13217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  num_siblings_type num_thread_siblings;
13247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(num_thread_siblings), "num threads",
13257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          &offset, &num_thread_siblings)) {
13267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
13277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
13297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&num_thread_siblings);
13307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  cpu_topology_.thread_siblings.resize(num_thread_siblings);
13327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < num_thread_siblings; ++i) {
13337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadStringFromBuffer(data, is_cross_endian_, &offset,
13347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              &cpu_topology_.thread_siblings[i])) {
13357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
13367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
13377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
13407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
13417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadNUMATopologyMetadata(
13437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const ConstBufferWithSize& data, u32 /*type*/, size_t offset, size_t /*size*/) {
13447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  numa_topology_num_nodes_type num_nodes;
13457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadDataFromBuffer(data, sizeof(num_nodes), "num nodes",
13467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                          &offset, &num_nodes)) {
13477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
13487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
13507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&num_nodes);
13517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < num_nodes; ++i) {
13537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    PerfNodeTopologyMetadata node;
13547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!ReadDataFromBuffer(data, sizeof(node.id), "node id",
13557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &offset, &node.id) ||
13567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        !ReadDataFromBuffer(data, sizeof(node.total_memory),
13577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            "node total memory", &offset,
13587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &node.total_memory) ||
13597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        !ReadDataFromBuffer(data, sizeof(node.free_memory),
13607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            "node free memory", &offset, &node.free_memory) ||
13617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        !ReadStringFromBuffer(data, is_cross_endian_, &offset,
13627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              &node.cpu_list)) {
13637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
13647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
13657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (is_cross_endian_) {
13667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&node.id);
13677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&node.total_memory);
13687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&node.free_memory);
13697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
13707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    numa_topology_.push_back(node);
13717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
13737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
13747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadTracingMetadata(
13767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const ConstBufferWithSize& data, size_t offset, size_t size) {
13777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t tracing_data_offset = offset;
13787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  tracing_data_.resize(size);
13797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ReadDataFromBuffer(data, tracing_data_.size(), "tracing_data",
13807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                            &tracing_data_offset, tracing_data_.data());
13817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
13827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadTracingMetadataEvent(
13847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const ConstBufferWithSize& data, size_t offset) {
13857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // TRACING_DATA's header.size is a lie. It is the size of only the event
13867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // struct. The size of the data is in the event struct, and followed
13877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // immediately by the tracing header data.
13887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Make a copy of the event (but not the tracing data)
13907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  tracing_data_event tracing_event =
13917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *reinterpret_cast<const tracing_data_event*>(data.ptr + offset);
13927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
13937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_) {
13947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&tracing_event.header.type);
13957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&tracing_event.header.misc);
13967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&tracing_event.header.size);
13977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&tracing_event.size);
13987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
13997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ReadTracingMetadata(data, offset + tracing_event.header.size,
14017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             tracing_event.size);
14027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
14037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadAttrEventBlock(const ConstBufferWithSize& data,
14057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                    size_t offset, size_t size) {
14067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const size_t initial_offset = offset;
14077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfFileAttr attr;
14087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadEventAttr(data, &offset, &attr.attr))
14097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
14107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // attr.attr.size has been upgraded to the current size of perf_event_attr.
14127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const size_t actual_attr_size = offset - initial_offset;
14137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const size_t num_ids =
14157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      (size - actual_attr_size) / sizeof(decltype(attr.ids)::value_type);
14167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadUniqueIDs(data, num_ids, &offset, &attr.ids))
14177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
14187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Event types are found many times in the perf data file.
14207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Only add this event type if it is not already present.
14217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < attrs_.size(); ++i) {
14227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (attrs_[i].ids[0] == attr.ids[0])
14237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return true;
14247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
14257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  attrs_.push_back(attr);
14267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
14277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
14287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// When this method is called, |event| is a reference to the bytes in the data
14307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// vector that contains the entire perf.data file.  As a result, we need to be
14317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// careful to only copy event.header.size bytes.
14327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// In particular, something like
14337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// event_t event_copy = event;
14347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// would be bad, because it would read past the end of the event, and possibly
14357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// pass the end of the data vector as well.
14367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::ReadPerfEventBlock(const event_t& event) {
14377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  u16 size = event.header.size;
14387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_)
14397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&size);
14407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1441e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //
144218b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // Upstream linux perf limits the size of an event record to 2^16 bytes,
144318b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // however simpleperf includes extensions to support larger (2^32) record
144418b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // sizes via a split record scheme (the larger records are split up
144518b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // into chunks and then embedded into a series of SIMPLE_PERF_RECORD_SPLIT
144618b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // records followed by a terminating SIMPLE_PERF_RECORD_SPLIT_END record.
144718b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // At the moment none of the larger records are of interest to perfprofd, so
144818b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  // the main thing we're doing here is ignoring/bypassing them.
1449e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  //
145018b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh  if (event.header.type == SIMPLE_PERF_RECORD_KERNEL_SYMBOL ||
145118b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_DSO ||
145218b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SYMBOL ||
145318b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SPLIT ||
145418b0775d68a04d78a4a4bcd6d23d717245aba184Than McIntosh      event.header.type == SIMPLE_PERF_RECORD_SPLIT_END)
1455e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    size = sizeof(event_t);
1456e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh  else if (size > sizeof(event_t)) {
14577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(INFO) << "Data size: " << size << " sizeof(event_t): "
14587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh              << sizeof(event_t);
14597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
14607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
14617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Copy only the part of the event that is needed.
14637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  malloced_unique_ptr<event_t> event_copy(CallocMemoryForEvent(size));
14647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memcpy(event_copy.get(), &event, size);
14657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_) {
14667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&event_copy->header.type);
14677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&event_copy->header.misc);
14687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ByteSwap(&event_copy->header.size);
14697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
14707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
14717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint32_t type = event_copy->header.type;
14727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (is_cross_endian_) {
14737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    switch (type) {
14747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_SAMPLE:
14757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
14767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_MMAP:
14777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap.pid);
14787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap.tid);
14797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap.start);
14807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap.len);
14817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap.pgoff);
14827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
14837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_MMAP2:
14847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.pid);
14857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.tid);
14867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.start);
14877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.len);
14887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.pgoff);
14897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.maj);
14907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.min);
14917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.ino);
14927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->mmap2.ino_generation);
14937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
14947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_FORK:
14957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_EXIT:
14967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->fork.pid);
14977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->fork.tid);
14987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->fork.ppid);
14997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->fork.ptid);
15007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
15017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_COMM:
15027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->comm.pid);
15037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->comm.tid);
15047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
15057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_LOST:
15067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->lost.id);
15077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->lost.lost);
15087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
15097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    case PERF_RECORD_READ:
15107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.pid);
15117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.tid);
15127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.value);
15137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.time_enabled);
15147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.time_running);
15157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ByteSwap(&event_copy->read.id);
15167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
1517e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh    case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
1518e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh      break;
15197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    default:
15207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(FATAL) << "Unknown event type: " << type;
15217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
15227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
15237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  events_.push_back(std::move(event_copy));
15257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
15277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetNumMetadata() const {
15307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // This is just the number of 1s in the binary representation of the metadata
15317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // mask.  However, make sure to only use supported metadata, and don't include
15327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // branch stack (since it doesn't have an entry in the metadata section).
15337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t new_mask = metadata_mask_;
15347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  new_mask &= kSupportedMetadataMask & ~(1 << HEADER_BRANCH_STACK);
15357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::bitset<sizeof(new_mask) * CHAR_BIT> bits(new_mask);
15367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return bits.count();
15377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetEventDescMetadataSize() const {
15407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = 0;
15417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event_types_.empty()) {
15427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return size;
15437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
15447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (metadata_mask_ & (1 << HEADER_EVENT_DESC)) {
15457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event_types_.size() > 0 && event_types_.size() != attrs_.size()) {
15467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Mismatch between number of event type events and attr "
15477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << "events: " << event_types_.size() << " vs "
15487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << attrs_.size();
15497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return size;
15507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
15517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(event_desc_num_events) + sizeof(event_desc_attr_size);
15527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CStringWithLength dummy;
15537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    for (size_t i = 0; i < attrs_.size(); ++i) {
15547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += sizeof(perf_event_attr) + sizeof(dummy.len);
15557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += sizeof(event_desc_num_unique_ids);
15567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += GetUint64AlignedStringLength(event_types_[i].name) * sizeof(char);
15577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += attrs_[i].ids.size() * sizeof(attrs_[i].ids[0]);
15587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
15597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
15607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
15617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetBuildIDMetadataSize() const {
15647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = 0;
15657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < build_id_events_.size(); ++i)
15667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += build_id_events_[i]->header.size;
15677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
15687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetStringMetadataSize() const {
15717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = 0;
15727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < string_metadata_.size(); ++i) {
15737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const PerfStringMetadata& metadata = string_metadata_[i];
15747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (NeedsNumberOfStringData(metadata.type))
15757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += sizeof(num_string_data_type);
15767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    for (size_t j = 0; j < metadata.data.size(); ++j) {
15787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      const CStringWithLength& str = metadata.data[j];
15797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size += sizeof(str.len) + (str.len * sizeof(char));
15807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
15817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
15827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
15837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetUint32MetadataSize() const {
15867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = 0;
15877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < uint32_metadata_.size(); ++i) {
15887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const PerfUint32Metadata& metadata = uint32_metadata_[i];
15897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += metadata.data.size() * sizeof(metadata.data[0]);
15907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
15917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
15927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
15937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
15947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetUint64MetadataSize() const {
15957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = 0;
15967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < uint64_metadata_.size(); ++i) {
15977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const PerfUint64Metadata& metadata = uint64_metadata_[i];
15987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += metadata.data.size() * sizeof(metadata.data[0]);
15997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
16007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
16017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
16027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetCPUTopologyMetadataSize() const {
16047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Core siblings.
16057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = sizeof(num_siblings_type);
16067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < cpu_topology_.core_siblings.size(); ++i) {
16077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const CStringWithLength& str = cpu_topology_.core_siblings[i];
16087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(str.len) + (str.len * sizeof(char));
16097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
16107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Thread siblings.
16127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size += sizeof(num_siblings_type);
16137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < cpu_topology_.thread_siblings.size(); ++i) {
16147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const CStringWithLength& str = cpu_topology_.thread_siblings[i];
16157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(str.len) + (str.len * sizeof(char));
16167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
16177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
16197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
16207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t PerfReader::GetNUMATopologyMetadataSize() const {
16227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t size = sizeof(numa_topology_num_nodes_type);
16237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < numa_topology_.size(); ++i) {
16247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const PerfNodeTopologyMetadata& node = numa_topology_[i];
16257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(node.id);
16267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(node.total_memory) + sizeof(node.free_memory);
16277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size += sizeof(node.cpu_list.len) + node.cpu_list.len * sizeof(char);
16287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
16297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return size;
16307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
16317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::NeedsNumberOfStringData(u32 type) const {
16337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return type == HEADER_CMDLINE;
16347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
16357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfReader::LocalizeMMapFilenames(
16377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const std::map<string, string>& filename_map) {
16387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Search for mmap/mmap2 events for which the filename needs to be updated.
16397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < events_.size(); ++i) {
16407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string filename;
16417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t size_of_fixed_event_parts;
16427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event_t* event = events_[i].get();
16437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event->header.type == PERF_RECORD_MMAP) {
16447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      filename = string(event->mmap.filename);
16457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size_of_fixed_event_parts =
16467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh          sizeof(event->mmap) - sizeof(event->mmap.filename);
16477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else if (event->header.type == PERF_RECORD_MMAP2) {
16487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      filename = string(event->mmap2.filename);
16497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      size_of_fixed_event_parts =
16507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh          sizeof(event->mmap2) - sizeof(event->mmap2.filename);
16517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else {
16527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
16537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
16547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const auto it = filename_map.find(filename);
16567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (it == filename_map.end())  // not found
16577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
16587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const string& new_filename = it->second;
16607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t old_len = GetUint64AlignedStringLength(filename);
16617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t new_len = GetUint64AlignedStringLength(new_filename);
16627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t old_offset = GetPerfSampleDataOffset(*event);
16637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t sample_size = event->header.size - old_offset;
16647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    int size_change = new_len - old_len;
16667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t new_size = event->header.size + size_change;
16677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    size_t new_offset = old_offset + size_change;
16687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (size_change > 0) {
16707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Allocate memory for a new event.
16717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      event_t* old_event = event;
16727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      malloced_unique_ptr<event_t> new_event(CallocMemoryForEvent(new_size));
16737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Copy over everything except filename and sample info.
16757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      memcpy(new_event.get(), old_event, size_of_fixed_event_parts);
16767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Copy over the sample info to the correct location.
16787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      char* old_addr = reinterpret_cast<char*>(old_event);
16797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      char* new_addr = reinterpret_cast<char*>(new_event.get());
16807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      memcpy(new_addr + new_offset, old_addr + old_offset, sample_size);
16817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      events_[i] = std::move(new_event);
16837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      event = events_[i].get();
16847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else if (size_change < 0) {
16857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Move the perf sample data to its new location.
16867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Since source and dest could overlap, use memmove instead of memcpy.
16877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      char* start_addr = reinterpret_cast<char*>(event);
16887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      memmove(start_addr + new_offset, start_addr + old_offset, sample_size);
16897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
16907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
16917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Copy over the new filename and fix the size of the event.
16927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    char *event_filename = nullptr;
16937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (event->header.type == PERF_RECORD_MMAP) {
16947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      event_filename = event->mmap.filename;
16957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else if (event->header.type == PERF_RECORD_MMAP2) {
16967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      event_filename = event->mmap2.filename;
16977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    } else {
16987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(FATAL) << "Unexpected event type";  // Impossible
16997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
17007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK_GT(snprintf(event_filename, new_filename.size() + 1, "%s",
17017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                      new_filename.c_str()),
17027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh             0);
17037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event->header.size = new_size;
17047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
17057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
17067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
17077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
17087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
17097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace quipper
1710