• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (C) 2021 Huawei Device Co., Ltd.
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.
15import os
16import subprocess
17import sys
18import argparse
19import logging
20sys.path.append(os.getcwd())
21sys.path.append("../../")
22from ftrace_format_parser import FtraceEventCodeGenerator
23from ftrace_format_parser import ProtoType
24
25AUTO_GENERATED_GNI = 'autogenerated.gni'
26
27THIS_FILE = os.path.basename(__file__)
28logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
29    level=logging.INFO)
30logger = logging.getLogger(THIS_FILE)
31
32CPP_COPYRIGHT_HEADER = '''\
33/* THIS FILE IS GENERATE BY {}, PLEASE DON'T EDIT IT!
34 * Copyright (c) 2021 Huawei Device Co., Ltd.
35 * Licensed under the Apache License, Version 2.0 (the "License");
36 * you may not use this file except in compliance with the License.
37 * You may obtain a copy of the License at
38 *
39 *     http://www.apache.org/licenses/LICENSE-2.0
40 *
41 * Unless required by applicable law or agreed to in writing, software
42 * distributed under the License is distributed on an "AS IS" BASIS,
43 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44 * See the License for the specific language governing permissions and
45 * limitations under the License.
46 */
47'''.format(THIS_FILE)
48
49GN_COPYRIGHT_HEADER = '''\
50# THIS FILE IS GENERATE BY {}, PLEASE DON'T EDIT IT!
51# Copyright (C) 2021 Huawei Device Co., Ltd.
52# Licensed under the Apache License, Version 2.0 (the "License");
53# you may not use this file except in compliance with the License.
54# You may obtain a copy of the License at
55#
56#     http://www.apache.org/licenses/LICENSE-2.0
57#
58# Unless required by applicable law or agreed to in writing, software
59# distributed under the License is distributed on an "AS IS" BASIS,
60# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
61# See the License for the specific language governing permissions and
62# limitations under the License.
63'''.format(THIS_FILE)
64
65PARSE_FUNCTION_ARGS = '({}, {}, {}, {})'.format('FtraceEvent& ftraceEvent',
66    'uint8_t data[]', 'size_t size', 'const EventFormat& format')
67PARSE_REGISTER_MACRO = 'REGISTER_FTRACE_EVENT_PARSE_FUNCTION'
68
69CHECK_FUNCTION_ARGS = '(const FtraceEvent& event) -> bool'
70FORMAT_FUNCTION_ARGS = '(const FtraceEvent& event) -> std::string'
71FORMAT_REGISTER_MACRO = 'REGISTER_FTRACE_EVENT_FORMATTER'
72
73
74def to_camel_case(name):
75    return ''.join([p.capitalize() for p in name.split('_')])
76
77
78def fix_field_name(name):
79    replace_map = {
80        'errno': 'error_code',
81        'sa_handler': 'sig_handler',
82        'sa_flags': 'sig_flags'
83    }
84    if name in replace_map:
85        name = replace_map[name]
86    return str.lower(name)
87
88
89def ensure_dir_exists(file_path):
90    file_dir = os.path.dirname(file_path)
91    if not os.path.exists(file_dir):
92        os.mkdir(file_dir)
93
94
95class EventParserCodeGenerator(FtraceEventCodeGenerator):
96    def __init__(self, events_dir, allow_list):
97        super().__init__(events_dir, allow_list)
98
99    def parser_file_path(self, category):
100        file_name = 'ftrace_{}_event_parser.cpp'.format(category)
101        return os.path.join(self.output_dir, file_name)
102
103    def generate_code(self):
104        generated_cpp_sources = []
105
106        for event in self.target_event_formats:
107            type_name = '{}/{}'.format(event.category, event.name)
108            logger.info('ftrace_events: "{}"'.format(type_name))
109
110        # generate sub event parser code
111        for category in self.grouped_event_formats:
112            parser_src_file = self.parser_file_path(category)
113            generated_cpp_sources.append(parser_src_file)
114
115            logger.info('Generate {} ...'.format(parser_src_file))
116            ensure_dir_exists(parser_src_file)
117
118            with open(parser_src_file, 'w', encoding='utf-8') as f:
119                f.write(CPP_COPYRIGHT_HEADER)
120                f.write('#include "sub_event_parser.h"\n')
121                f.write('\n')
122                f.write("FTRACE_NS_BEGIN\n")
123                f.write("namespace {\n")
124                self.generate_parse_functions(category, f)
125                f.write("} // namespace\n")
126                f.write("FTRACE_NS_END\n")
127                f.write('\n')
128
129        # generate .gni
130        generated_cpp_gni = os.path.join(self.output_dir, AUTO_GENERATED_GNI)
131        logger.info('Generate {} ...'.format(generated_cpp_gni))
132        with open(generated_cpp_gni, 'w', encoding='utf-8') as f:
133            f.write(GN_COPYRIGHT_HEADER)
134            f.write('\n')
135            f.write('auto_generated_cpp_sources = [\n')
136            for path in generated_cpp_sources:
137                src = '{}'.format(os.path.basename(path))
138                f.write('  "{}",\n'.format(src))
139            f.write(']\n')
140
141    def generate_parse_functions(self, category, f):
142        count = 0
143        for event in self.grouped_event_formats[category]:
144            count += 1
145            if count > 1:
146                f.write('\n')
147            f.write('{}({},\n'.format(PARSE_REGISTER_MACRO, event.name))
148            f.write('[] {} {{\n'.format(PARSE_FUNCTION_ARGS))
149            f.write('    int i = 0;\n')
150            f.write('    auto msg = ftraceEvent.mutable_{}_format();\n'.format(
151                str.lower(event.name)))
152            for i in range(len(event.remain_fields)):
153                self.generate_parse_field_lines(event, f, i)
154            f.write("});\n")
155
156    @staticmethod
157    def generate_parse_field_lines(event, f, i):
158        field_info = event.remain_fields[i]
159        field_name = fix_field_name(field_info.name)
160        type_info = field_info.to_proto_type()
161        parse_func = None
162        if type_info.tid == ProtoType.STRING:
163            parse_func = 'ParseStrField'
164        elif type_info.tid == ProtoType.INTEGER:
165            if type_info.size in [4, 8]:
166                c_type = None
167                if type_info.size == 4:
168                    c_type = 'int32_t' if type_info.signed else 'uint32_t'
169                elif type_info.size == 8:
170                    c_type = 'int64_t' if type_info.signed else 'uint64_t'
171                parse_func = 'ParseIntField<{}>'.format(c_type)
172        else:
173            logger.warning('WARNING: unkown proto type:{} {}'.format(
174                event.name, field_name))
175        if parse_func is not None:
176            f.write('    msg->set_{}(FtraceFieldParser::'.format(field_name))
177            f.write('{}(format.fields, i++, data, size));\n'.format(parse_func))
178
179
180class EventFormatterCodeGenerator(FtraceEventCodeGenerator):
181    def __init__(self, events_dir, allow_list):
182        super().__init__(events_dir, allow_list)
183
184    def formatter_file_path(self, category):
185        file_name = 'ftrace_{}_event_formatter.cpp'.format(category)
186        return os.path.join(self.output_dir, file_name)
187
188    def generate_code(self):
189        generated_cpp_sources = []
190
191        # generate sub event parser code
192        for category in self.grouped_event_formats:
193            formatter_src_file = self.formatter_file_path(category)
194            generated_cpp_sources.append(formatter_src_file)
195
196            logger.info('Generate {} ...'.format(formatter_src_file))
197            ensure_dir_exists(formatter_src_file)
198
199            with open(formatter_src_file, 'w', encoding='utf-8') as f:
200                f.write(CPP_COPYRIGHT_HEADER)
201                f.write('#include <cinttypes>\n')
202                f.write('\n')
203                f.write('#include "event_formatter.h"\n')
204                if (category == "binder") :
205                    f.write('#include "binder.h"\n')
206                if (category == "power") :
207                    f.write('#include "pm_qos.h"\n')
208                if (category == "writeback") :
209                    f.write('#include "pq.h"\n')
210                elif (category == "compaction")  | (category == "kmem") | (category == "vmscan") :
211                    f.write('#include "type.h"\n')
212                elif (category == "timer") :
213                    f.write('#include "hrtimer.h"\n')
214                f.write('#include "trace_events.h"\n')
215                f.write('\n')
216                f.write("FTRACE_NS_BEGIN\n")
217                f.write("namespace {\n")
218                f.write('const int BUFFER_SIZE = 200;\n')
219                f.write('\n')
220                self.generate_format_functions(category, f)
221                f.write("} // namespace\n")
222                f.write("FTRACE_NS_END\n")
223                f.write('\n')
224
225        # generate .gni
226        generated_cpp_gni = os.path.join(self.output_dir, AUTO_GENERATED_GNI)
227        logger.info('Generate {} ...'.format(generated_cpp_gni))
228        with open(generated_cpp_gni, 'w', encoding='utf-8') as f:
229            f.write(GN_COPYRIGHT_HEADER)
230            f.write('\n')
231            f.write('auto_generated_cpp_sources = [\n')
232            for path in generated_cpp_sources:
233                src = '{}'.format(os.path.basename(path))
234                f.write('  "{}",\n'.format(src))
235            f.write(']\n')
236
237    def generate_format_functions(self, category, f):
238        count = 0
239        for event in self.grouped_event_formats[category]:
240            count += 1
241            if count > 1:
242                f.write('\n')
243            f.write('{}({},\n'.format(FORMAT_REGISTER_MACRO, event.name))
244            f.write('[] {} {{\n'.format(CHECK_FUNCTION_ARGS, ))
245            f.write('    return event.has_{}_format();'.format(
246                str.lower(event.name)))
247            f.write('},')  # end of check function
248            f.write('[] {} {{\n'.format(FORMAT_FUNCTION_ARGS))
249            f.write('    auto msg = event.{}_format();\n'.format(
250                str.lower(event.name)))
251            f.write("    char buffer[BUFFER_SIZE];\n")
252            event.print_fmt = "\"{}: {}".format(event.name, event.print_fmt[2:])
253            event.print_fmt = str.replace(event.print_fmt, "=%zu", "=%llu")
254            event.print_fmt = str.replace(event.print_fmt, "pfn=%llu", "pfn=%\" PRId64 \"")
255            if (category == "binder") :
256                event.print_fmt = str.replace(event.print_fmt, "%zd", "%\" PRId64 \"")
257                event.print_fmt = str.replace(event.print_fmt, "%llu", "%\" PRId64 \"")
258            elif (category == "net") :
259                event.print_fmt = str.replace(event.print_fmt, "skbaddr=%p", "skbaddr=%\" PRId64 \"")
260            elif (category == "kmem") | (category == "filemap") :
261                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
262                event.print_fmt = str.replace(event.print_fmt, "%p", "%\" PRId64 \"")
263                event.print_fmt = str.replace(event.print_fmt, "REC->pfn != -1UL ? (((struct page *)vmemmap_base) + (REC->pfn)) : ((void *)0)", "\"0000000000000000\"")
264                event.print_fmt = str.replace(event.print_fmt, "(((struct page *)vmemmap_base) + (REC->pfn))", "\"0000000000000000\"")
265                event.print_fmt = str.replace(event.print_fmt, " (void *)", " ")
266                event.print_fmt = str.replace(event.print_fmt, " name=%s\"", "\"")
267                event.print_fmt = str.replace(event.print_fmt, "REC->ptr, __get_str(name)", "REC->ptr")
268                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRId64 \"")
269                event.print_fmt = str.replace(event.print_fmt, "%llu", "%\" PRId64 \"")
270                event.print_fmt = str.replace(event.print_fmt, "%lx", "%\" PRId64 \"")
271            elif (category == "filelock") :
272                event.print_fmt = str.replace(event.print_fmt, "fl=%p", "fl=%\" PRId64 \"")
273                event.print_fmt = str.replace(event.print_fmt, "ino=0x%lx", "ino=0x%\" PRId64 \"")
274                event.print_fmt = str.replace(event.print_fmt, "fl_blocker=%p", "fl_blocker=%\" PRId64 \"")
275                event.print_fmt = str.replace(event.print_fmt, "fl_owner=%p", "fl_owner=%\" PRId32 \"")
276                event.print_fmt = str.replace(event.print_fmt, "=%lu", "=%\" PRId64 \"")
277                event.print_fmt = str.replace(event.print_fmt, "REC->fl_blocker", "msg.fl_next()")
278                event.print_fmt = str.replace(event.print_fmt, "REC->fl_owner", "msg.fl_owner()")
279                event.print_fmt = str.replace(event.print_fmt, "REC->fl_flags", "msg.fl_flags()")
280                event.print_fmt = str.replace(event.print_fmt, "REC->fl_type", "msg.fl_type()")
281                event.print_fmt = str.replace(event.print_fmt, "REC->fl_break_time", "msg.fl_break_time()")
282                event.print_fmt = str.replace(event.print_fmt, "REC->fl_downgrade_time", "msg.fl_downgrade_time()")
283                event.print_fmt = str.replace(event.print_fmt, "REC->rcount", "msg.dcount()")
284            elif (category == "ext4") :
285                event.print_fmt = str.replace(event.print_fmt, "%llu", "%\" PRId64 \"")
286                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRId64 \"")
287                event.print_fmt = str.replace(event.print_fmt, "%lld", "%\" PRId64 \"")
288                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long long)", ",")
289                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long)", ",")
290            elif (category == "timer") :
291                event.print_fmt = str.replace(event.print_fmt, "=%ps", "=%\" PRId64 \"")
292                event.print_fmt = str.replace(event.print_fmt, "=%p", "=%\" PRId64 \"")
293            elif (category == "vmscan") :
294                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRId64 \"")
295                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRId64 \"")
296            elif (category == "writeback") :
297                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long)", ", ")
298                event.print_fmt = str.replace(event.print_fmt, "cgroup_ino=%lu", "cgroup_ino=%\" PRId32 \"")
299                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRId64 \"")
300                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRId64 \"")
301                event.print_fmt = str.replace(event.print_fmt, "%lx", "%\" PRId64 \"")
302            elif (category == "sunrpc") :
303                event.print_fmt = str.replace(event.print_fmt, "socket:[%llu]", "socket:[%\" PRId64 \"]")
304                event.print_fmt = str.replace(event.print_fmt, "action=%ps", "action=%\" PRId64 \"")
305                event.print_fmt = str.replace(event.print_fmt, "=%lu", "=%\" PRId64 \"")
306            elif (category == "v4l2") :
307                event.print_fmt = str.replace(event.print_fmt, "timestamp = %llu", "timestamp = %\" PRId64 \"")
308            elif (category == "sched") :
309                event.print_fmt = str.replace(event.print_fmt, "%Lu", "%\" PRId64 \"")
310                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long long)", ", ")
311
312            if (event.name == "binder_command") :
313                event.print_fmt = "\"binder_command: cmd=0x%x\", msg.cmd()"
314            elif (event.name == "binder_ioctl") :
315                event.print_fmt = str.replace(event.print_fmt, "arg=0x%lx", "arg=0x%\" PRId64 \"")
316            elif (event.name == "binder_return") :
317                event.print_fmt = "\"binder_return: cmd=0x%x\", msg.cmd()"
318            elif (event.name == "mmiotrace_map") | (event.name == "mmiotrace_rw") :
319                event.print_fmt = str.replace(event.print_fmt, "%lx %lx %d", "%\" PRId64 \" %\" PRId64 \" %d")
320            elif (event.name == "funcgraph_exit") :
321                event.print_fmt = str.replace(event.print_fmt, "(start: %llx  end: %llx)", "(start: %\" PRId64 \"  end: %\" PRId64 \")")
322            elif (event.name == "task_newtask") :
323                event.print_fmt = str.replace(event.print_fmt, "clone_flags=%lx oom_score_adj=%hd", "clone_flags=%\" PRId64 \" oom_score_adj=%d")
324            elif (event.name == "task_rename") :
325                event.print_fmt = str.replace(event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%d")
326            elif (event.name == "branch_format"):
327                event.print_fmt = "\"branch: %u:%s:%s (%u)%s\", msg.line(), msg.func().c_str(), msg.file().c_str(), msg.correct(), msg.constant() ? \" CONSTANT\" : \"\""
328            elif (event.name == "kernel_stack"):
329                event.print_fmt = "\"kernel_stack: \""
330            elif (event.name == "user_stack"):
331                event.print_fmt = "\"user_stack: \""
332            elif (event.name == "mm_lru_activate") | (event.name == "mm_lru_insertion") :
333                event.print_fmt = str.replace(event.print_fmt, "page=%p pfn=%lu", "page=%\" PRId64 \" pfn=%\" PRId64 \"")
334            elif (event.name == "task_rename") :
335                event.print_fmt = str.replace(event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%d")
336            elif (event.name == "sched_stick_numa"):
337                event.print_fmt = "\"sched_stick_numa: src_pid=%d src_tgid=%d src_ngid=%d src_cpu=%d src_nid=%d dst_pid=%d dst_tgid=%d dst_ngid=%d dst_cpu=%d dst_nid=%d\", msg.pid(), msg.tgid(), msg.ngid(), msg.src_cpu(), msg.src_nid(), msg.pid(), msg.tgid(), msg.ngid(), msg.dst_cpu(), msg.dst_nid()"
338            elif (event.name == "print"):
339                event.print_fmt = "\"print: %s\", msg.buf().c_str()"
340            elif (event.name == "workqueue_activate_work"):
341                event.print_fmt = str.replace(event.print_fmt, "struct %p", "struct %\" PRId64 \"")
342            elif (event.name == "workqueue_execute_start"):
343                event.print_fmt = str.replace(event.print_fmt, "struct %p", "struct %\" PRId64 \"")
344                event.print_fmt = str.replace(event.print_fmt, "function %ps", "function %\" PRId64 \"")
345            elif (event.name == "workqueue_execute_end"):
346                event.print_fmt = "\"workqueue_execute_end: work struct %\" PRId64 \"\", msg.work()"
347            elif (event.name == "workqueue_queue_work"):
348                event.print_fmt = str.replace(event.print_fmt, "struct=%p ", "struct=%\" PRId64 \" ")
349                event.print_fmt = str.replace(event.print_fmt, "function=%ps ", "function=%\" PRId64 \" ")
350                event.print_fmt = str.replace(event.print_fmt, "workqueue=%p ", "workqueue=%\" PRId64 \" ")
351                event.print_fmt = str.replace(event.print_fmt, "REC->workqueue", "msg.workqueue()")
352            elif (event.name == "i2c_reply") | (event.name == "i2c_write") :
353                event.print_fmt = str.replace(event.print_fmt, "l=%u [%*phD]", "l=%\" PRId32 \" [%\" PRId32 \"]")
354                event.print_fmt = str.replace(event.print_fmt, "REC->len, REC->len", "REC->len")
355            elif (event.name == "block_dirty_buffer") | (event.name == "block_touch_buffer") :
356                event.print_fmt = str.replace(event.print_fmt, "size=%llu", "size=%\" PRId64 \"")
357            elif (event.name == "mm_compaction_isolate_freepages") | (event.name == "mm_compaction_isolate_migratepages") \
358                    | (event.name == "mm_compaction_begin") | (event.name == "mm_compaction_end") \
359                    | (event.name == "mm_compaction_migratepages") :
360                event.print_fmt = str.replace(event.print_fmt, "0x%lx", "=0x%\" PRId64 \"")
361                event.print_fmt = str.replace(event.print_fmt, "%lu", "=0x%\" PRId64 \"")
362            elif (event.name == "mm_compaction_defer_compaction") | (event.name == "mm_compaction_defer_reset") \
363                    | (event.name == "mm_compaction_deferred") | (event.name == "mm_compaction_end") \
364                    | (event.name == "mm_compaction_migratepages") :
365                event.print_fmt = str.replace(event.print_fmt, "REC->order_failed", "msg.order_failed()")
366            elif (event.name == "cpuhp_enter") | (event.name == "cpuhp_multi_enter") :
367                event.print_fmt = str.replace(event.print_fmt, "(%ps)", "(%\" PRId64 \")")
368            elif (event.name == "signal_deliver") | (event.name == "signal_generate") :
369                event.print_fmt = str.replace(event.print_fmt, "=%lx", "=%\" PRId64 \"")
370                event.print_fmt = str.replace(event.print_fmt, "REC->errno", "msg.error_code()")
371                event.print_fmt = str.replace(event.print_fmt, "REC->sa_handler", "msg.sig_handler()")
372                event.print_fmt = str.replace(event.print_fmt, "REC->sa_flags", "msg.sig_flags()")
373            elif (event.name == "sys_enter"):
374                event.print_fmt = "\"sys_enter: NR %\" PRId64 \" (%d, %d, %d, %d %d, %d)\", msg.id(), int(msg.args()[0]-'0'), int(msg.args()[1]-'0'), int(msg.args()[2]-'0'), int(msg.args()[3]-'0'), int(msg.args()[4]-'0'), int(msg.args()[5]-'0')"
375            elif (event.name == "sys_exit"):
376                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRId64 \"")
377            elif (event.name == "oom_score_adj_update"):
378                event.print_fmt = str.replace(event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%\" PRId32 \"")
379            elif (event.name == "ext4_da_write_pages"):
380                event.print_fmt = str.replace(event.print_fmt, "first_page %\" PRId64 \" nr_to_write %ld", "first_page %\" PRId64 \" nr_to_write %\" PRId64 \"")
381            elif (event.name == "ext4_discard_preallocations"):
382                event.print_fmt = str.replace(event.print_fmt, "ino %\" PRId64 \" len: %u needed %u", "ino %\" PRId64 \"")
383                event.print_fmt = str.replace(event.print_fmt, " REC->ino, REC->len, REC->needed", " REC->ino")
384            elif (event.name == "ext4_ext_remove_space_done") | (event.name == "ext4_ext_rm_leaf") | (event.name == "ext4_remove_blocks") :
385                event.print_fmt = str.replace(event.print_fmt, " [pclu %\" PRId64 \" lblk %u state %d]", "%\" PRId64 \"")
386                event.print_fmt = str.replace(event.print_fmt, "(long long) REC->pc_pclu, (unsigned int) REC->pc_lblk, (int) REC->pc_state", "msg.partial()")
387            elif (event.name == "ext4_free_blocks"):
388                event.print_fmt = str.replace(event.print_fmt, "count %\" PRId64 \"", "count %\" PRId64 \"")
389            elif (event.name == "ext4_journal_start"):
390                event.print_fmt = str.replace(event.print_fmt, ", revoke_creds %d,", ",")
391                event.print_fmt = str.replace(event.print_fmt, ", REC->revoke_creds,", ",")
392            elif (event.name == "ext4_read_block_bitmap_load"):
393                event.print_fmt = str.replace(event.print_fmt, "%u prefetch %d", "%u")
394                event.print_fmt = str.replace(event.print_fmt, "REC->group, REC->prefetch", "msg.group()")
395            elif (event.name == "ext4_writepages"):
396                event.print_fmt = str.replace(event.print_fmt, "nr_to_write %ld", "nr_to_write %\" PRId64 \"")
397                event.print_fmt = str.replace(event.print_fmt, "pages_skipped %ld", "pages_skipped %\" PRId64 \"")
398            elif (event.name == "ext4_writepages_result"):
399                event.print_fmt = str.replace(event.print_fmt, "pages_skipped %ld", "pages_skipped %\" PRId64 \"")
400            elif (event.name == "ext4_load_inode"):
401                event.print_fmt = str.replace(event.print_fmt, "ino %ld", "ino %\" PRId64 \"")
402            elif (event.name == "itimer_state") :
403                event.print_fmt = str.replace(event.print_fmt, "it_value=%ld.%06ld it_interval=%ld.%06ld", "it_value=%\" PRId64 \"it_interval=%\" PRId64 \"")
404                event.print_fmt = str.replace(event.print_fmt, "REC->value_nsec / 1000L, REC->interval_sec, REC->interval_nsec / 1000L", "msg.interval_sec()")
405                event.print_fmt = str.replace(event.print_fmt, "expires=%llu", "expires=%\" PRId64 \"")
406            elif (event.name == "timer_expire_entry") :
407                event.print_fmt = str.replace(event.print_fmt, "now=%lu baseclk=%lu", "now=%\" PRId64 \"")
408                event.print_fmt = str.replace(event.print_fmt, "REC->now, REC->baseclk", "msg.now()")
409            elif (event.name == "timer_start") :
410                event.print_fmt = str.replace(event.print_fmt, "expires=%lu [timeout=%ld]", "expires=%\" PRId64 \" [timeout=%\" PRId64 \"]")
411                event.print_fmt = str.replace(event.print_fmt, ", (long)", ",")
412            elif (event.name == "itimer_expire") :
413                event.print_fmt = str.replace(event.print_fmt, "now=%llu", "now=%\" PRId64 \"")
414            elif (event.name == "mm_shrink_slab_end") | (event.name == "mm_shrink_slab_start") :
415                event.print_fmt = str.replace(event.print_fmt, "%lld", "%\" PRId64 \"")
416                event.print_fmt = str.replace(event.print_fmt, " %pS %p", "%\" PRId64 \"S %\" PRId64 \"")
417                event.print_fmt = str.replace(event.print_fmt, "REC->shrink", "msg.shrink()")
418            elif (event.name == "mm_vmscan_lru_shrink_inactive") :
419                event.print_fmt = str.replace(event.print_fmt, "nr_activate_anon=%d nr_activate_file=%d", "nr_activate=%\" PRId64 \"")
420                event.print_fmt = str.replace(event.print_fmt, "REC->nr_activate0, REC->nr_activate1", "msg.nr_activate()")
421            elif (event.name == "mm_vmscan_writepage") :
422                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
423                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:56], event.print_fmt[3728:])
424            elif (event.name == "mm_vmscan_lru_isolate") :
425                event.print_fmt = str.replace(event.print_fmt, "REC->highest_zoneidx", "msg.classzone_idx()")
426            elif (event.name == "balance_dirty_pages") | (event.name == "bdi_dirty_ratelimit") :
427                event.print_fmt = str.replace(event.print_fmt, "REC->bdi_dirty", "msg.bdi_dirty()")
428                event.print_fmt = str.replace(event.print_fmt, "REC->bdi_setpoint", "msg.bdi_setpoint()")
429                event.print_fmt = str.replace(event.print_fmt, "REC->dirty_ratelimit", "msg.dirty_ratelimit()")
430                event.print_fmt = str.replace(event.print_fmt, "REC->dirtied_pause", "msg.dirtied_pause()")
431            elif (event.name == "sched_migrate_task") :
432                event.print_fmt = str.replace(event.print_fmt, "dest_cpu=%d running=%d", "dest_cpu=%d")
433                event.print_fmt = str.replace(event.print_fmt, "REC->dest_cpu, REC->running", "msg.dest_cpu()")
434            elif (event.name == "ext4_find_delalloc_range") :
435                event.print_fmt = str.replace(event.print_fmt, "REC->found_blk", "msg.found_blk()")
436            elif (event.name == "mm_filemap_add_to_page_cache") | (event.name == "mm_filemap_delete_from_page_cache"):
437                event.print_fmt = "\"{}: dev %\" PRId64 \":%\" PRId64 \" ino %\" PRId64 \" page=%s pfn=%\" PRId64 \" ofs=%\" PRId64 \"\", \
438                (((msg.s_dev()) >> 20)), (((msg.s_dev()) & ((1U << 20) - 1))), msg.i_ino(), \"0000000000000000\", msg.pfn(), msg.index() << 12".format(event.name)
439            elif (event.name == "ipi_raise") :
440                event.print_fmt = str.replace(event.print_fmt, "target_mask=%s", "target_mask=%\" PRId64 \"")
441                event.print_fmt = str.replace(event.print_fmt, "__get_bitmask(target_cpus)", "msg.target_cpus()")
442            elif (event.name == "mm_page_alloc") :
443                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:78], event.print_fmt[3783:])
444            elif (event.name == "mm_page_alloc_extfrag") :
445                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:181], event.print_fmt[3853:])
446            elif (event.name == "mm_page_alloc_zone_locked") :
447                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:94], event.print_fmt[3799:])
448            elif (event.name == "mm_page_free") :
449                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:49], event.print_fmt[3721:])
450            elif (event.name == "mm_page_free_batched") :
451                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:56], event.print_fmt[3728:])
452            elif (event.name == "mm_page_pcpu_drain") :
453                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:70], event.print_fmt[3742:])
454            elif (event.name == "xprt_transmit"):
455                event.print_fmt = "\"xprt_transmit: xid=0x%08x status=%d\", msg.xid(), msg.status()"
456
457            for field_info in event.remain_fields:
458                field_name = fix_field_name(field_info.name)
459                event.print_fmt = str.replace(event.print_fmt, "__get_str({})".format(field_name),
460                                                    "msg.{}().c_str()".format(field_name))
461                event.print_fmt = str.replace(event.print_fmt, "__get_dynamic_array({})".format(field_name),
462                                                    "msg.{}()".format(field_name))
463                if field_info.field.startswith('char {}['.format(field_name)) \
464                    | field_info.field.startswith('const char {}['.format(field_name)) \
465                    | field_info.field.startswith('char *') | field_info.field.startswith('const char *'):
466                    event.print_fmt = str.replace(event.print_fmt, "REC->{}".format(field_name),
467                                                    "msg.{}().c_str()".format(field_name))
468                else:
469                    event.print_fmt = str.replace(event.print_fmt, "REC->{}".format(field_name),
470                                                    "msg.{}()".format(field_name))
471            if (event.name == "sched_switch"):
472                f.write("    if (msg.prev_state() > 0x0400) {\n")
473                f.write('        sprintf(buffer, "sched_switch: prev_comm=%s prev_pid=%d prev_prio=%d prev_state=? ==> next_comm=%s next_pid=%d next_prio=%d", msg.prev_comm().c_str(), msg.prev_pid(), msg.prev_prio(), msg.next_comm().c_str(), msg.next_pid(), msg.next_prio());\n')
474                f.write("    } else {\n")
475                f.write('        sprintf(buffer, "sched_switch: prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s%s ==> next_comm=%s next_pid=%d next_prio=%d", msg.prev_comm().c_str(), msg.prev_pid(), msg.prev_prio(), (msg.prev_state() & ((((0x0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) << 1) - 1)) ? __print_flags(msg.prev_state() & ((((0x0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) << 1) - 1), "|", { 0x0001, "S" }, { 0x0002, "D" }, { 0x0004, "T" }, { 0x0008, "t" }, { 0x0010, "X" }, { 0x0020, "Z" }, { 0x0040, "I" }, { 0x0080, "K" }, { 0x0100, "W" }, { 0x0200, "P" }, { 0x0400, "N" }) : "R", msg.prev_state() & (((0x0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) << 1) ? "+" : "", msg.next_comm().c_str(), msg.next_pid(), msg.next_prio());\n')
476                f.write("    }\n")
477            else :
478                f.write('    sprintf(buffer,{});\n'.format(event.print_fmt))
479            f.write("    return std::string(buffer);\n")
480            f.write("});\n")  # end of format function
481
482
483def main():
484    parser = argparse.ArgumentParser(
485        description='FTrace C++ code generator.')
486    parser.add_argument('-a', dest='allow_list', required=True, type=str,
487                        help='event allow list file path')
488    parser.add_argument('-e', dest='events_dir', required=True, type=str,
489                        help='event formats directory')
490    parser.add_argument('-p', dest='parser_out', required=False, type=str,
491                        help='parser code output directory')
492    parser.add_argument('-f', dest='formatter_out', required=False, type=str,
493                        help='formaater code output directory')
494
495    args = parser.parse_args(sys.argv[1:])
496    allow_list = args.allow_list
497    events_dir = args.events_dir
498    parser_out = args.parser_out
499    formatter_out = args.formatter_out
500
501    # check arguments
502    if not os.path.isfile(allow_list):
503        parser.print_usage()
504        exit(1)
505    if not os.path.isdir(events_dir):
506        parser.print_usage()
507        exit(2)
508
509    if parser_out:
510        if not os.path.isdir(parser_out):
511            parser.print_usage()
512            exit(3)
513        parser_gen = EventParserCodeGenerator(events_dir, allow_list)
514        parser_gen.generate(os.path.join(parser_out))
515
516    if formatter_out:
517        if not os.path.isdir(formatter_out):
518            parser.print_usage()
519            exit(4)
520        fmtter_gen = EventFormatterCodeGenerator(events_dir, allow_list)
521        fmtter_gen.generate(formatter_out)
522    subprocess.run("./../../../format-code.sh ./trace_converter/event_formatters", shell=True)
523    subprocess.run("chmod 775 ./trace_converter/event_formatters/*.cpp", shell=True)
524
525
526if __name__ == '__main__':
527    main()
528