event_type.cpp revision 04d08a35c5e1cabdf6eb7397536a790b0ff44459
167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui/*
267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Copyright (C) 2015 The Android Open Source Project
367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * you may not use this file except in compliance with the License.
667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * You may obtain a copy of the License at
767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *      http://www.apache.org/licenses/LICENSE-2.0
967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
1067d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Unless required by applicable law or agreed to in writing, software
1167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * distributed under the License is distributed on an "AS IS" BASIS,
1267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * See the License for the specific language governing permissions and
1467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * limitations under the License.
1567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui */
1667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
1767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_type.h"
1867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
1967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include <unistd.h>
20f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui#include <algorithm>
2167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include <string>
2267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include <vector>
239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
24f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui#include <base/file.h>
259759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <base/logging.h>
269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_attr.h"
2867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_fd.h"
29f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui#include "utils.h"
3067d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
3167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#define EVENT_TYPE_TABLE_ENTRY(name, type, config) \
3267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  { name, type, config }                           \
3367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  ,
3467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
35f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cuistatic const std::vector<EventType> static_event_type_array = {
3667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_type_table.h"
3767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui};
3867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
39f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cuistatic const std::vector<EventType> GetTracepointEventTypes() {
40f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::vector<EventType> result;
41f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  const std::string tracepoint_dirname = "/sys/kernel/debug/tracing/events";
42f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::vector<std::string> system_dirs;
43f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  GetEntriesInDir(tracepoint_dirname, nullptr, &system_dirs);
44f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  for (auto& system_name : system_dirs) {
45f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    std::string system_path = tracepoint_dirname + "/" + system_name;
46f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    std::vector<std::string> event_dirs;
47f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    GetEntriesInDir(system_path, nullptr, &event_dirs);
48f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    for (auto& event_name : event_dirs) {
49f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      std::string id_path = system_path + "/" + event_name + "/id";
50f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      std::string id_content;
51f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      if (!android::base::ReadFileToString(id_path, &id_content)) {
52f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        continue;
53f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      }
54f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      char* endptr;
55f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      uint64_t id = strtoull(id_content.c_str(), &endptr, 10);
56f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      if (endptr == id_content.c_str()) {
57f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        LOG(DEBUG) << "unexpected id '" << id_content << "' in " << id_path;
58f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        continue;
59f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      }
60f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      result.push_back(EventType(system_name + ":" + event_name, PERF_TYPE_TRACEPOINT, id));
61f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    }
62f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  }
63f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::sort(result.begin(), result.end(),
64f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui            [](const EventType& type1, const EventType& type2) { return type1.name < type2.name; });
65f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  return result;
66f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui}
67f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui
68d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cuiconst std::vector<EventType>& GetAllEventTypes() {
69f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  static std::vector<EventType> event_type_array;
70f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  if (event_type_array.empty()) {
71f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    event_type_array.insert(event_type_array.end(), static_event_type_array.begin(),
72f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui                            static_event_type_array.end());
73f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    const std::vector<EventType> tracepoint_array = GetTracepointEventTypes();
74f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    event_type_array.insert(event_type_array.end(), tracepoint_array.begin(),
75f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui                            tracepoint_array.end());
76f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  }
7767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  return event_type_array;
7867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
7967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
80d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cuiconst EventType* FindEventTypeByConfig(uint32_t type, uint64_t config) {
81d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  for (auto& event_type : GetAllEventTypes()) {
82d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (event_type.type == type && event_type.config == config) {
83d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      return &event_type;
84d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
85d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
86d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  return nullptr;
87d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui}
88d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui
899fd3cc1048a3d0338df4a48760dfd655560992a1Yabin Cuiconst EventType* FindEventTypeByName(const std::string& name) {
909759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  const EventType* result = nullptr;
91f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  for (auto& event_type : GetAllEventTypes()) {
9267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    if (event_type.name == name) {
939759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      result = &event_type;
949759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      break;
9567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    }
9667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  }
979759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  if (result == nullptr) {
989759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    LOG(ERROR) << "Unknown event_type '" << name
999759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui               << "', try `simpleperf list` to list all possible event type names";
1009759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    return nullptr;
1019759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
1029759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  return result;
10367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
10467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
1059fd3cc1048a3d0338df4a48760dfd655560992a1Yabin Cuistd::unique_ptr<EventTypeAndModifier> ParseEventType(const std::string& event_type_str) {
106d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  static std::string modifier_characters = "ukhGHp";
107d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  std::unique_ptr<EventTypeAndModifier> event_type_modifier(new EventTypeAndModifier);
1085872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  event_type_modifier->name = event_type_str;
1095872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  std::string event_type_name = event_type_str;
110d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  std::string modifier;
111d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  size_t comm_pos = event_type_str.rfind(':');
112d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (comm_pos != std::string::npos) {
113d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    bool match_modifier = true;
114d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    for (size_t i = comm_pos + 1; i < event_type_str.size(); ++i) {
115d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      char c = event_type_str[i];
116d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      if (c != ' ' && modifier_characters.find(c) == std::string::npos) {
117d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        match_modifier = false;
118d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
119d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      }
120d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
121d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (match_modifier) {
1225872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type_name = event_type_str.substr(0, comm_pos);
123d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      modifier = event_type_str.substr(comm_pos + 1);
12467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    }
12567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  }
1265872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  const EventType* event_type = FindEventTypeByName(event_type_name);
127d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (event_type == nullptr) {
128d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    // Try if the modifier belongs to the event type name, like some tracepoint events.
129d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (!modifier.empty()) {
1305872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type_name = event_type_str;
131d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      modifier.clear();
1325872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type = FindEventTypeByName(event_type_name);
133d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
134d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (event_type == nullptr) {
135d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      return nullptr;
136d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
137d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
138d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  event_type_modifier->event_type = *event_type;
139d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (modifier.find_first_of("ukh") != std::string::npos) {
140d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_user = true;
141d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_kernel = true;
142d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_hv = true;
143d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
144d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (modifier.find_first_of("GH") != std::string::npos) {
145d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_guest = true;
146d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_host = true;
147d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
148d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui
149d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  for (auto& c : modifier) {
150d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    switch (c) {
151d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'u':
152d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_user = false;
153d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
154d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'k':
155d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_kernel = false;
156d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
157d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'h':
158d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_hv = false;
159d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
160d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'G':
161d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_guest = false;
162d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
163d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'H':
164d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_host = false;
165d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
166d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'p':
167d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->precise_ip++;
168d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
169d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case ' ':
170d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
171d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      default:
172d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        LOG(ERROR) << "Unknown event type modifier '" << c << "'";
173d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
174d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
17504d08a35c5e1cabdf6eb7397536a790b0ff44459Yabin Cui  event_type_modifier->modifier = modifier;
176d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  return event_type_modifier;
17767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
178