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