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