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#define LOG_TAG "perf_reader"
67e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
77e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_utils.h"
87e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
97e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <sys/stat.h>
107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cctype>
127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstddef>
137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstdlib>
147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstring>
157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <fstream>  // NOLINT(readability/streams)
167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <iomanip>
177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <sstream>
187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "base/logging.h"
207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "base/macros.h"
217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace {
237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Number of hex digits in a byte.
257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst int kNumHexDigitsInByte = 2;
267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace
287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace quipper {
307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshevent_t* CallocMemoryForEvent(size_t size) {
327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  event_t* event = reinterpret_cast<event_t*>(calloc(1, size));
337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK(event);
347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return event;
357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbuild_id_event* CallocMemoryForBuildID(size_t size) {
387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  build_id_event* event = reinterpret_cast<build_id_event*>(calloc(1, size));
397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK(event);
407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return event;
417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstring HexToString(const u8* array, size_t length) {
447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Convert the bytes to hex digits one at a time.
457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // There will be kNumHexDigitsInByte hex digits, and 1 char for NUL.
467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  char buffer[kNumHexDigitsInByte + 1];
477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  string result = "";
487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < length; ++i) {
497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    snprintf(buffer, sizeof(buffer), "%02x", array[i]);
507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    result += buffer;
517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return result;
537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool StringToHex(const string& str, u8* array, size_t length) {
567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const int kHexRadix = 16;
577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  char* err;
587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Loop through kNumHexDigitsInByte characters at a time (to get one byte)
597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Stop when there are no more characters, or the array has been filled.
607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0;
617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh       (i + 1) * kNumHexDigitsInByte <= str.size() && i < length;
627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh       ++i) {
637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    string one_byte = str.substr(i * kNumHexDigitsInByte, kNumHexDigitsInByte);
647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    array[i] = strtol(one_byte.c_str(), &err, kHexRadix);
657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (*err)
667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshuint64_t AlignSize(uint64_t size, uint32_t align_size) {
727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return ((size + align_size - 1) / align_size) * align_size;
737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// In perf data, strings are packed into the smallest number of 8-byte blocks
767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// possible, including the null terminator.
777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// e.g.
787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "0123"                ->  5 bytes -> packed into  8 bytes
797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "0123456"             ->  8 bytes -> packed into  8 bytes
807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "01234567"            ->  9 bytes -> packed into 16 bytes
817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "0123456789abcd"      -> 15 bytes -> packed into 16 bytes
827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "0123456789abcde"     -> 16 bytes -> packed into 16 bytes
837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//    "0123456789abcdef"    -> 17 bytes -> packed into 24 bytes
847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//
857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Returns the size of the 8-byte-aligned memory for storing |string|.
867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshsize_t GetUint64AlignedStringLength(const string& str) {
877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return AlignSize(str.size() + 1, sizeof(uint64_t));
887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshuint64_t GetSampleFieldsForEventType(uint32_t event_type,
917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                     uint64_t sample_type) {
927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t mask = kuint64max;
937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  switch (event_type) {
947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP:
957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_LOST:
967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_COMM:
977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_EXIT:
987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_THROTTLE:
997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_UNTHROTTLE:
1007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_FORK:
1017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_READ:
1027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP2:
1037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // See perf_event.h "struct" sample_id and sample_id_all.
1047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mask = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID |
1057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh           PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER;
1067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_SAMPLE:
1087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  default:
1107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(FATAL) << "Unknown event type " << event_type;
1117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return sample_type & mask;
1137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshuint64_t GetPerfSampleDataOffset(const event_t& event) {
1167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t offset = kuint64max;
1177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  switch (event.header.type) {
1187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_SAMPLE:
1197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = offsetof(event_t, sample.array);
1207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP:
1227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.mmap) - sizeof(event.mmap.filename) +
1237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh             GetUint64AlignedStringLength(event.mmap.filename);
1247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_FORK:
1267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_EXIT:
1277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.fork);
1287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_COMM:
1307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.comm) - sizeof(event.comm.comm) +
1317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh             GetUint64AlignedStringLength(event.comm.comm);
1327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_LOST:
1347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.lost);
1357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_READ:
1377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.read);
1387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  case PERF_RECORD_MMAP2:
1407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    offset = sizeof(event.mmap2) - sizeof(event.mmap2.filename) +
1417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh             GetUint64AlignedStringLength(event.mmap2.filename);
1427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  default:
1447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(FATAL) << "Unknown/unsupported event type " << event.header.type;
1457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    break;
1467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Make sure the offset was valid
1487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_NE(offset, kuint64max);
1497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_EQ(offset % sizeof(uint64_t), 0U);
1507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return offset;
1517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool ReadFileToData(const string& filename, std::vector<char>* data) {
1547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::ifstream in(filename.c_str(), std::ios::binary);
1557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!in.good()) {
1567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Failed to open file " << filename;
1577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
1587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  in.seekg(0, in.end);
1607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t length = in.tellg();
1617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  in.seekg(0, in.beg);
1627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  data->resize(length);
1637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  in.read(&(*data)[0], length);
1657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!in.good()) {
1677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Error reading from file " << filename;
1687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
1697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
1717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool WriteDataToFile(const std::vector<char>& data, const string& filename) {
1747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::ofstream out(filename.c_str(), std::ios::binary);
1757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  out.seekp(0, std::ios::beg);
1767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  out.write(&data[0], data.size());
1777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return out.good();
1787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace quipper
181