blob: 954ddc312bd47a6d49e715ff276f5b02642b1545 [file] [log] [blame]
Hector Dearmanbe61adf2017-10-18 15:58:46 +01001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Hector Dearman2193ff42017-11-08 14:15:19 +000017#include "ftrace_reader/format_parser.h"
Hector Dearmanbe61adf2017-10-18 15:58:46 +010018
19#include <string.h>
20
21#include <iosfwd>
22#include <iostream>
23#include <memory>
24#include <vector>
25
Hector Dearman2193ff42017-11-08 14:15:19 +000026#include "ftrace_reader/ftrace_to_proto.h"
Oystein Eftevaagdd727e42017-12-05 08:49:55 -080027#include "perfetto_base/utils.h"
Hector Dearmanbe61adf2017-10-18 15:58:46 +010028
29namespace perfetto {
30namespace {
31
32#define MAX_FIELD_LENGTH 127
33#define STRINGIFY(x) STRINGIFY2(x)
34#define STRINGIFY2(x) #x
35
36const char* kCommonFieldPrefix = "common_";
37
Hector Dearmanb9b41a52017-11-27 11:52:37 +000038bool IsCommonFieldName(std::string name) {
39 return name.compare(0, strlen(kCommonFieldPrefix), kCommonFieldPrefix) == 0;
40}
41
Hector Dearmanbe61adf2017-10-18 15:58:46 +010042} // namespace
43
44bool ParseFtraceEvent(const std::string& input, FtraceEvent* output) {
Hector Dearman798bcdf2017-10-31 16:36:46 +000045 std::unique_ptr<char[], base::FreeDeleter> input_copy(strdup(input.c_str()));
Hector Dearmanbe61adf2017-10-18 15:58:46 +010046 char* s = input_copy.get();
47
48 char buffer[MAX_FIELD_LENGTH + 1];
49
50 bool has_id = false;
51 bool has_name = false;
52
53 int id = 0;
54 std::string name;
Hector Dearmanb9b41a52017-11-27 11:52:37 +000055 std::vector<FtraceEvent::Field> common_fields;
Hector Dearmanbe61adf2017-10-18 15:58:46 +010056 std::vector<FtraceEvent::Field> fields;
57
58 for (char* line = strtok(s, "\n"); line; line = strtok(nullptr, "\n")) {
59 if (!has_id && sscanf(line, "ID: %d", &id) == 1) {
60 has_id = true;
61 continue;
62 }
63
64 if (!has_name &&
65 sscanf(line, "name: %" STRINGIFY(MAX_FIELD_LENGTH) "s", buffer) == 1) {
66 name = std::string(buffer);
67 has_name = true;
68 continue;
69 }
70
71 if (strcmp("format:", line) == 0) {
72 continue;
73 }
74
Hector Dearman7d8bbfa2017-11-09 11:36:04 +000075 size_t offset = 0;
76 size_t size = 0;
Hector Dearmanbe61adf2017-10-18 15:58:46 +010077 int is_signed = 0;
Hector Dearman7d8bbfa2017-11-09 11:36:04 +000078 if (sscanf(line,
79 "\tfield:%" STRINGIFY(MAX_FIELD_LENGTH) "[^;];\toffset: "
80 "%zu;\tsize: "
81 "%zu;\tsigned: %d;",
82 buffer, &offset, &size, &is_signed) == 4) {
Hector Dearmanbe61adf2017-10-18 15:58:46 +010083 std::string type_and_name(buffer);
84
Hector Dearmanbe61adf2017-10-18 15:58:46 +010085 FtraceEvent::Field field{type_and_name, offset, size, is_signed == 1};
Hector Dearmanb9b41a52017-11-27 11:52:37 +000086
87 if (IsCommonFieldName(GetNameFromTypeAndName(type_and_name))) {
88 common_fields.push_back(field);
89 } else {
90 fields.push_back(field);
91 }
92
Hector Dearmanbe61adf2017-10-18 15:58:46 +010093 continue;
94 }
95
96 if (strncmp(line, "print fmt:", 10) == 0) {
97 break;
98 }
99
100 if (output)
101 fprintf(stderr, "Cannot parse line: \"%s\"\n", line);
102 return false;
103 }
104
105 if (!has_id || !has_name || fields.size() == 0) {
106 if (output)
107 fprintf(stderr, "Could not parse format file: %s.\n",
108 !has_id ? "no ID found"
109 : !has_name ? "no name found" : "no fields found");
110 return false;
111 }
112
113 if (!output)
114 return true;
115
116 output->id = id;
117 output->name = name;
118 output->fields = std::move(fields);
Hector Dearmanb9b41a52017-11-27 11:52:37 +0000119 output->common_fields = std::move(common_fields);
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100120
121 return true;
122}
123
124::std::ostream& operator<<(::std::ostream& os,
125 const FtraceEvent::Field& field) {
126 PrintTo(field, &os);
127 return os;
128}
129
130// Allow gtest to pretty print FtraceEvent::Field.
131void PrintTo(const FtraceEvent::Field& field, ::std::ostream* os) {
132 *os << "FtraceEvent::Field(" << field.type_and_name << ", " << field.offset
133 << ", " << field.size << ", " << field.is_signed << ")";
134}
135
136} // namespace perfetto