blob: 74349b9210e26718d15da0c4f7274f76bf609e9c [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "proto_translation_table.h"
#include <algorithm>
#include "event_info.h"
#include "ftrace_procfs.h"
#include "perfetto/ftrace_reader/format_parser.h"
#include "perfetto/ftrace_reader/ftrace_to_proto.h"
#include "protos/ftrace/ftrace_event_bundle.pbzero.h"
namespace perfetto {
namespace {
const std::vector<Event> BuildEventsVector(const std::vector<Event>& events) {
size_t largest_id = 0;
for (const Event& event : events) {
if (event.ftrace_event_id > largest_id)
largest_id = event.ftrace_event_id;
}
std::vector<Event> events_by_id;
events_by_id.resize(largest_id + 1);
for (const Event& event : events) {
events_by_id[event.ftrace_event_id] = event;
}
events_by_id.shrink_to_fit();
return events_by_id;
}
} // namespace
// static
std::unique_ptr<ProtoTranslationTable> ProtoTranslationTable::Create(
const FtraceProcfs* ftrace_procfs,
std::vector<Event> events) {
std::vector<Field> common_fields;
for (Event& event : events) {
std::string contents =
ftrace_procfs->ReadEventFormat(event.group, event.name);
FtraceEvent ftrace_event;
if (contents == "" || !ParseFtraceEvent(contents, &ftrace_event)) {
PERFETTO_DLOG("Could not read '%s'", event.name);
continue;
}
event.ftrace_event_id = ftrace_event.id;
for (Field& field : event.fields) {
for (FtraceEvent::Field ftrace_field : ftrace_event.fields) {
if (GetNameFromTypeAndName(ftrace_field.type_and_name) !=
field.ftrace_name)
continue;
field.ftrace_offset = ftrace_field.offset;
field.ftrace_size = ftrace_field.size;
field.ftrace_type = kFtraceNumber;
}
}
if (common_fields.empty()) {
for (const FtraceEvent::Field& ftrace_field :
ftrace_event.common_fields) {
common_fields.push_back(Field{ftrace_field.offset, ftrace_field.size});
}
}
}
events.erase(std::remove_if(events.begin(), events.end(),
[](const Event& event) {
return event.proto_field_id == 0 ||
event.ftrace_event_id == 0;
}),
events.end());
auto table = std::unique_ptr<ProtoTranslationTable>(
new ProtoTranslationTable(std::move(events), std::move(common_fields)));
return table;
}
ProtoTranslationTable::ProtoTranslationTable(const std::vector<Event>& events,
std::vector<Field> common_fields)
: events_(BuildEventsVector(events)),
largest_id_(events_.size() - 1),
common_fields_(std::move(common_fields)) {
for (const Event& event : events) {
name_to_event_[event.name] = &events_.at(event.ftrace_event_id);
}
}
ProtoTranslationTable::~ProtoTranslationTable() = default;
} // namespace perfetto