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
2466dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/file.h>
2566dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/logging.h>
269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_attr.h"
28f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui#include "utils.h"
2967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
3042aa127e8ab4c5eb5197cf3cc68470cf3a0fdcbbYabin Cui#define EVENT_TYPE_TABLE_ENTRY(name, type, config) {name, type, config},
3167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
32f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cuistatic const std::vector<EventType> static_event_type_array = {
3367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "event_type_table.h"
3467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui};
3567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
36f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cuistatic const std::vector<EventType> GetTracepointEventTypes() {
37f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::vector<EventType> result;
38f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  const std::string tracepoint_dirname = "/sys/kernel/debug/tracing/events";
39f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::vector<std::string> system_dirs;
40f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  GetEntriesInDir(tracepoint_dirname, nullptr, &system_dirs);
41f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  for (auto& system_name : system_dirs) {
42f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    std::string system_path = tracepoint_dirname + "/" + system_name;
43f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    std::vector<std::string> event_dirs;
44f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    GetEntriesInDir(system_path, nullptr, &event_dirs);
45f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    for (auto& event_name : event_dirs) {
46f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      std::string id_path = system_path + "/" + event_name + "/id";
47f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      std::string id_content;
48f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      if (!android::base::ReadFileToString(id_path, &id_content)) {
49f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        continue;
50f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      }
51f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      char* endptr;
52f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      uint64_t id = strtoull(id_content.c_str(), &endptr, 10);
53f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      if (endptr == id_content.c_str()) {
54f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        LOG(DEBUG) << "unexpected id '" << id_content << "' in " << id_path;
55f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui        continue;
56f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      }
57f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui      result.push_back(EventType(system_name + ":" + event_name, PERF_TYPE_TRACEPOINT, id));
58f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    }
59f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  }
60f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  std::sort(result.begin(), result.end(),
61f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui            [](const EventType& type1, const EventType& type2) { return type1.name < type2.name; });
62f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  return result;
63f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui}
64f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui
65d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cuiconst std::vector<EventType>& GetAllEventTypes() {
66f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  static std::vector<EventType> event_type_array;
67f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  if (event_type_array.empty()) {
68f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    event_type_array.insert(event_type_array.end(), static_event_type_array.begin(),
69f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui                            static_event_type_array.end());
70f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    const std::vector<EventType> tracepoint_array = GetTracepointEventTypes();
71f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui    event_type_array.insert(event_type_array.end(), tracepoint_array.begin(),
72f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui                            tracepoint_array.end());
73f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  }
7467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  return event_type_array;
7567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
7667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
77d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cuiconst EventType* FindEventTypeByConfig(uint32_t type, uint64_t config) {
78d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  for (auto& event_type : GetAllEventTypes()) {
79d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (event_type.type == type && event_type.config == config) {
80d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      return &event_type;
81d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
82d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
83d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  return nullptr;
84d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui}
85d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui
869fd3cc1048a3d0338df4a48760dfd655560992a1Yabin Cuiconst EventType* FindEventTypeByName(const std::string& name) {
879759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  const EventType* result = nullptr;
88f569b478e74560a2d9e29a96824e16b93a55b97fYabin Cui  for (auto& event_type : GetAllEventTypes()) {
8967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    if (event_type.name == name) {
909759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      result = &event_type;
919759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      break;
9267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    }
9367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  }
949759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  if (result == nullptr) {
959759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    LOG(ERROR) << "Unknown event_type '" << name
969759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui               << "', try `simpleperf list` to list all possible event type names";
979759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    return nullptr;
989759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
999759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  return result;
10067d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
10167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
1029fd3cc1048a3d0338df4a48760dfd655560992a1Yabin Cuistd::unique_ptr<EventTypeAndModifier> ParseEventType(const std::string& event_type_str) {
103d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  static std::string modifier_characters = "ukhGHp";
104d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  std::unique_ptr<EventTypeAndModifier> event_type_modifier(new EventTypeAndModifier);
1055872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  event_type_modifier->name = event_type_str;
1065872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  std::string event_type_name = event_type_str;
107d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  std::string modifier;
108d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  size_t comm_pos = event_type_str.rfind(':');
109d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (comm_pos != std::string::npos) {
110d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    bool match_modifier = true;
111d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    for (size_t i = comm_pos + 1; i < event_type_str.size(); ++i) {
112d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      char c = event_type_str[i];
113d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      if (c != ' ' && modifier_characters.find(c) == std::string::npos) {
114d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        match_modifier = false;
115d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
116d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      }
117d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
118d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (match_modifier) {
1195872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type_name = event_type_str.substr(0, comm_pos);
120d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      modifier = event_type_str.substr(comm_pos + 1);
12167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui    }
12267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  }
1235872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui  const EventType* event_type = FindEventTypeByName(event_type_name);
124d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (event_type == nullptr) {
125d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    // Try if the modifier belongs to the event type name, like some tracepoint events.
126d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (!modifier.empty()) {
1275872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type_name = event_type_str;
128d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      modifier.clear();
1295872ac6f1f5b804ffea38ff59025441618802d6bYabin Cui      event_type = FindEventTypeByName(event_type_name);
130d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
131d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    if (event_type == nullptr) {
132d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      return nullptr;
133d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
134d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
135d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  event_type_modifier->event_type = *event_type;
136d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (modifier.find_first_of("ukh") != std::string::npos) {
137d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_user = true;
138d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_kernel = true;
139d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_hv = true;
140d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
141d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  if (modifier.find_first_of("GH") != std::string::npos) {
142d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_guest = true;
143d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    event_type_modifier->exclude_host = true;
144d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
145d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui
146d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  for (auto& c : modifier) {
147d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    switch (c) {
148d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'u':
149d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_user = false;
150d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
151d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'k':
152d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_kernel = false;
153d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
154d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'h':
155d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_hv = false;
156d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
157d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'G':
158d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_guest = false;
159d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
160d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'H':
161d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->exclude_host = false;
162d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
163d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case 'p':
164d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        event_type_modifier->precise_ip++;
165d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
166d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      case ' ':
167d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        break;
168d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui      default:
169d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui        LOG(ERROR) << "Unknown event type modifier '" << c << "'";
170d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui    }
171d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  }
17204d08a35c5e1cabdf6eb7397536a790b0ff44459Yabin Cui  event_type_modifier->modifier = modifier;
173d115b2f738f2cef352877b26c2d93460ac9fea25Yabin Cui  return event_type_modifier;
17467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
175