• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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
25
26class Common:
27    auto_generated_gni = "autogenerated.gni"
28
29    this_file = os.path.basename(__file__)
30    logging.basicConfig(
31        format="%(asctime)s %(levelname)s %(message)s", level=logging.INFO
32    )
33    logger = logging.getLogger(this_file)
34
35    cpp_copyright_header = (
36        ""
37        "/* THIS FILE IS GENERATE BY {}, PLEASE DON'T EDIT IT!\n"
38        " * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.\n"
39        ' * Licensed under the Apache License, Version 2.0 (the "License");\n'
40        " * you may not use this file except in compliance with the License.\n"
41        " * You may obtain a copy of the License at\n"
42        " *\n"
43        " *     http://www.apache.org/licenses/LICENSE-2.0\n"
44        " *\n"
45        " * Unless required by applicable law or agreed to in writing, software\n"
46        ' * distributed under the License is distributed on an "AS IS" BASIS,\n'
47        " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
48        " * See the License for the specific language governing permissions and\n"
49        " * limitations under the License.\n"
50        " */\n".format(this_file)
51    )
52
53    gn_copyright_header = (
54        ""
55        "# THIS FILE IS GENERATE BY {}, PLEASE DON'T EDIT IT!\n"
56        "# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.\n"
57        '# Licensed under the Apache License, Version 2.0 (the "License");\n'
58        "# you may not use this file except in compliance with the License.\n"
59        "# You may obtain a copy of the License at\n"
60        "#\n"
61        "#     http://www.apache.org/licenses/LICENSE-2.0\n"
62        "#\n"
63        "# Unless required by applicable law or agreed to in writing, software\n"
64        '# distributed under the License is distributed on an "AS IS" BASIS,\n'
65        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
66        "# See the License for the specific language governing permissions and\n"
67        "# limitations under the License.\n".format(this_file)
68    )
69
70    parse_function_args = "{}, {}, {})".format(
71        "uint8_t data[]",
72        "size_t size",
73        "const EventFormat& format",
74    )
75    parse_register_macro = "REGISTER_FTRACE_EVENT_PARSE_FUNCTION"
76    parse_register_encoder_macro = "REGISTER_FTRACE_EVENT_PARSE_ENCODER_FUNCTION"
77
78    check_function_args = "(const ForStandard::FtraceEvent& event) -> bool"
79    format_function_args = "(const ForStandard::FtraceEvent& event) -> std::string"
80    format_register_macro = "REGISTER_FTRACE_EVENT_FORMATTER"
81
82
83def to_camel_case(name):
84    return "".join([p.capitalize() for p in name.split("_")])
85
86
87def fix_field_name(name):
88    replace_map = {
89        "errno": "error_code",
90        "sa_handler": "sig_handler",
91        "sa_flags": "sig_flags",
92        "new": "seq_new",
93    }
94    if name in replace_map:
95        name = replace_map.get(name)
96    return str.lower(name)
97
98
99def ensure_dir_exists(file_path):
100    file_dir = os.path.dirname(file_path)
101    if not os.path.exists(file_dir):
102        os.mkdir(file_dir)
103
104
105class EventParserCodeGenerator(FtraceEventCodeGenerator):
106    def __init__(self, events_dir, allow_list):
107        super().__init__(events_dir, allow_list)
108
109    def parser_file_path(self, category):
110        file_name = "ftrace_{}_event_parser.cpp".format(category)
111        return os.path.join(self.output_dir, file_name)
112
113    def generate_code(self):
114        generated_cpp_sources = []
115
116        for event in self.target_event_formats:
117            type_name = "{}/{}".format(event.category, event.name)
118            Common.logger.info('ftrace_events: "{}"'.format(type_name))
119
120        # generate sub event parser code
121        for category in self.grouped_event_formats:
122            parser_src_file = self.parser_file_path(category)
123            generated_cpp_sources.append(parser_src_file)
124
125            Common.logger.info("Generate {} ...".format(parser_src_file))
126            ensure_dir_exists(parser_src_file)
127
128            with open(parser_src_file, "w", encoding="utf-8") as f:
129                f.write(Common.cpp_copyright_header)
130                f.write('#include "sub_event_parser.h"\n')
131                f.write("\n")
132                f.write("FTRACE_NS_BEGIN\n")
133                f.write("namespace {\n")
134                f.write("using namespace OHOS::Developtools::Profiler;\n")
135                self.generate_parse_functions(category, f)
136                f.write("} // namespace\n")
137                f.write("FTRACE_NS_END\n")
138                f.write("\n")
139
140        # generate .gni
141        generated_cpp_gni = os.path.join(self.output_dir, Common.auto_generated_gni)
142        Common.logger.info("Generate {} ...".format(generated_cpp_gni))
143        with open(generated_cpp_gni, "w", encoding="utf-8") as f:
144            f.write(Common.gn_copyright_header)
145            f.write("\n")
146            f.write("auto_generated_cpp_sources = [\n")
147            for path in generated_cpp_sources:
148                src = "{}".format(os.path.basename(path))
149                f.write('  "{}",\n'.format(src))
150            f.write("]\n")
151
152    def generate_parse_functions(self, category, f):
153        count = 0
154        for event in self.grouped_event_formats[category]:
155            count += 1
156            if count > 1:
157                f.write("\n")
158            f.write("template <typename T>\n")
159            f.write("void {}_func(T& msg, {}\n".format(event.name, Common.parse_function_args))
160            f.write("{\n    int i = 0;\n")
161            for i in range(len(event.remain_fields)):
162                self.generate_parse_field_lines(event, f, i)
163            f.write("}\n")
164            f.write("{}({},\n".format(Common.parse_register_macro, event.name))
165            f.write("[] (FtraceEvent& ftraceEvent, {} {{\n".format(Common.parse_function_args))
166            f.write(
167                "    auto msg = ftraceEvent.mutable_{}_format();\n".format(
168                    str.lower(event.name)
169                )
170            )
171            f.write("    {}_func(msg, data, size, format);\n".format(event.name))
172            f.write("});\n")
173            f.write("{}({},\n".format(Common.parse_register_encoder_macro, event.name))
174            f.write("[] (ProtoEncoder::FtraceEvent& ftraceEvent, {} {{\n".format(Common.parse_function_args))
175            f.write(
176                "    auto msg = ftraceEvent.mutable_{}_format();\n".format(
177                    str.lower(event.name)
178                )
179            )
180            f.write("    {}_func(msg, data, size, format);\n".format(event.name))
181            f.write("});\n")
182
183    @staticmethod
184    def generate_parse_field_lines(event, f, i):
185        field_info = event.remain_fields[i]
186        field_name = fix_field_name(field_info.name)
187        type_info = field_info.to_proto_type()
188        parse_func = None
189        if type_info.tid == ProtoType.STRING:
190            parse_func = "ParseStrField"
191        elif type_info.tid == ProtoType.ARRAY:
192            parse_func = "ParseVectorIntField"
193        elif type_info.tid == ProtoType.INTEGER:
194            if type_info.size in [4, 8]:
195                c_type = None
196                if type_info.size == 4:
197                    c_type = "int32_t" if type_info.signed else "uint32_t"
198                elif type_info.size == 8:
199                    c_type = "int64_t" if type_info.signed else "uint64_t"
200                parse_func = "ParseIntField<{}>".format(c_type)
201        elif type_info.tid != ProtoType.INVALID:
202            Common.logger.warning(
203                "WARNING: unkown proto type:{} {}".format(event.name, field_name)
204            )
205        if parse_func != None:
206            if type_info.tid == ProtoType.ARRAY:
207                f.write(
208                    "    std::vector<uint64_t> retvalVec = FtraceFieldParser::ParseVectorIntField<uint64_t>"
209                    "(format.fields, i++, data, size);"
210                )
211                f.write("    for (size_t i = 0; i < retvalVec.size(); i++) {")
212                f.write("    msg->add_{}(retvalVec[i]);".format(field_name))
213                f.write("    }")
214            else:
215                f.write("    msg->set_{}(FtraceFieldParser::".format(field_name))
216                f.write("{}(format.fields, i++, data, size));\n".format(parse_func))
217
218
219class EventFormatterCodeGenerator(FtraceEventCodeGenerator):
220    def __init__(self, events_dir, allow_list):
221        super().__init__(events_dir, allow_list)
222
223    def formatter_file_path(self, category):
224        file_name = "ftrace_{}_event_formatter.cpp".format(category)
225        return os.path.join(self.output_dir, file_name)
226
227    def generate_code(self):
228        generated_cpp_sources = []
229
230        # generate sub event parser code
231        for category in self.grouped_event_formats:
232            formatter_src_file = self.formatter_file_path(category)
233            generated_cpp_sources.append(formatter_src_file)
234
235            Common.logger.info("Generate {} ...".format(formatter_src_file))
236            ensure_dir_exists(formatter_src_file)
237
238            with open(formatter_src_file, "w", encoding="utf-8") as f:
239                f.write(Common.cpp_copyright_header)
240                f.write("#include <cinttypes>\n")
241                f.write("\n")
242                f.write('#include "event_formatter.h"\n')
243                if category == "binder":
244                    f.write('#include "binder.h"\n')
245                f.write('#include "logging.h"\n')
246                if category == "f2fs":
247                    f.write('#include "f2fs.h"\n')
248                elif category == "power":
249                    f.write('#include "pm_qos.h"\n')
250                elif category == "writeback":
251                    f.write('#include "pq.h"\n')
252                elif (
253                    (category == "compaction")
254                    | (category == "kmem")
255                    | (category == "vmscan")
256                ):
257                    f.write('#include "type.h"\n')
258                elif category == "timer":
259                    f.write('#include "hrtimer.h"\n')
260                f.write('#include "trace_events.h"\n')
261                f.write("\n")
262                f.write("FTRACE_NS_BEGIN\n")
263                f.write("namespace {\n")
264                f.write("const int BUFFER_SIZE = 512;\n")
265                f.write("\n")
266                self.generate_format_functions(category, f)
267                f.write("} // namespace\n")
268                f.write("FTRACE_NS_END\n")
269                f.write("\n")
270
271        # generate .gni
272        generated_cpp_gni = os.path.join(self.output_dir, Common.auto_generated_gni)
273        Common.logger.info("Generate {} ...".format(generated_cpp_gni))
274        with open(generated_cpp_gni, "w", encoding="utf-8") as f:
275            f.write(Common.gn_copyright_header)
276            f.write("\n")
277            f.write("auto_generated_cpp_sources = [\n")
278            for path in generated_cpp_sources:
279                src = "{}".format(os.path.basename(path))
280                f.write('  "{}",\n'.format(src))
281            f.write("]\n")
282
283    def generate_format_functions(self, category, f):
284        count = 0
285        for event in self.grouped_event_formats.get(category):
286            count += 1
287            if count > 1:
288                f.write("\n")
289            f.write(
290                "{}({},\n".format(Common.format_register_macro, str.lower(event.name))
291            )
292            f.write(
293                "[] {} {{\n".format(
294                    Common.check_function_args,
295                )
296            )
297            f.write("    return event.has_{}_format();".format(str.lower(event.name)))
298            f.write("},")  # end of check function
299            f.write("[] {} {{\n".format(Common.format_function_args))
300            f.write("    auto msg = event.{}_format();\n".format(str.lower(event.name)))
301            f.write("    char buffer[BUFFER_SIZE];\n")
302            event.print_fmt = '"{}: {}'.format(event.name, event.print_fmt[2:])
303            event.print_fmt = str.replace(event.print_fmt, "%zu", '%" PRIu64 "')
304            event.print_fmt = str.replace(event.print_fmt, "%zd", '%" PRIu64 "')
305            event.print_fmt = str.replace(event.print_fmt, "%llu", '%" PRIu64 "')
306            event.print_fmt = str.replace(event.print_fmt, "%lld", '%" PRIu64 "')
307            event.print_fmt = str.replace(event.print_fmt, "%lx", '%" PRIx64 "')
308            event.print_fmt = str.replace(event.print_fmt, "%llx", '%" PRIx64 "')
309            event.print_fmt = str.replace(event.print_fmt, "(unsigned long long)", "")
310
311            if (category == "kmem") | (category == "filemap"):
312                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
313                event.print_fmt = str.replace(
314                    event.print_fmt,
315                    "REC->pfn != -1UL ? (((struct page *)vmemmap_base) + "
316                    "(REC->pfn)): ((void *)0)",
317                    '"0000000000000000"',
318                )
319                event.print_fmt = str.replace(
320                    event.print_fmt,
321                    "(((struct page *)vmemmap_base) + (REC->pfn))",
322                    "\
323                    "
324                    '"0000000000000000"',
325                )
326                event.print_fmt = str.replace(event.print_fmt, " (void *)", " ")
327                event.print_fmt = str.replace(event.print_fmt, ' name=%s"', '"')
328                event.print_fmt = str.replace(
329                    event.print_fmt, "REC->ptr, __get_str(name)", "REC->ptr"
330                )
331                event.print_fmt = str.replace(event.print_fmt, "%lu", '%" PRIu64 "')
332            elif category == "filelock":
333                event.print_fmt = str.replace(event.print_fmt, "=%lu", '=%" PRIu64 "')
334                event.print_fmt = str.replace(
335                    event.print_fmt, "REC->fl_blocker", "msg.fl_next()"
336                )
337                event.print_fmt = str.replace(
338                    event.print_fmt, "REC->fl_owner", "msg.fl_owner()"
339                )
340                event.print_fmt = str.replace(
341                    event.print_fmt, "REC->fl_flags", "msg.fl_flags()"
342                )
343                event.print_fmt = str.replace(
344                    event.print_fmt, "REC->fl_type", "msg.fl_type()"
345                )
346                event.print_fmt = str.replace(
347                    event.print_fmt, "REC->fl_break_time", "msg.fl_break_time()"
348                )
349                event.print_fmt = str.replace(
350                    event.print_fmt, "REC->fl_downgrade_time", "msg.fl_downgrade_time()"
351                )
352                event.print_fmt = str.replace(
353                    event.print_fmt, "REC->rcount", "msg.dcount()"
354                )
355            elif category == "ext4":
356                event.print_fmt = str.replace(event.print_fmt, "%lu", '%" PRIu64 "')
357                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long)", ",")
358            elif category == "vmscan":
359                event.print_fmt = str.replace(event.print_fmt, "%ld", '%" PRIu64 "')
360                event.print_fmt = str.replace(event.print_fmt, "%lu", '%" PRIu64 "')
361            elif category == "writeback":
362                event.print_fmt = str.replace(
363                    event.print_fmt, ", (unsigned long)", ", "
364                )
365                event.print_fmt = str.replace(
366                    event.print_fmt, "cgroup_ino=%lu", 'cgroup_ino=%" PRId32 "'
367                )
368                event.print_fmt = str.replace(event.print_fmt, "%lu", '%" PRIu64 "')
369                event.print_fmt = str.replace(event.print_fmt, "%ld", '%" PRIu64 "')
370            elif category == "sunrpc":
371                event.print_fmt = str.replace(event.print_fmt, "=%lu", '=%" PRIu64 "')
372            elif category == "sched":
373                event.print_fmt = str.replace(event.print_fmt, "%Lu", '%" PRIu64 "')
374            elif category == "ftrace":
375                event.print_fmt = str.replace(event.print_fmt, "(unsigned long)", "")
376
377            page_str = ' "0000000000000000"'
378            if event.name == "binder_command":
379                event.print_fmt = '"binder_command: cmd=0x%x", msg.cmd()'
380            elif event.name == "binder_return":
381                event.print_fmt = '"binder_return: cmd=0x%x", msg.cmd()'
382            elif (event.name == "task_newtask") | (event.name == "task_rename"):
383                event.print_fmt = str.replace(
384                    event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%d"
385                )
386            elif event.name == "branch_format":
387                event.print_fmt = (
388                    '"branch: %u:%s:%s (%u)%s", msg.line(), msg.func().c_str(), msg.file().c_str(), '
389                    'msg.correct(), msg.constant() ? " CONSTANT": ""'
390                )
391            elif (event.name == "mm_lru_activate") | (event.name == "mm_lru_insertion"):
392                event.print_fmt = str.replace(
393                    event.print_fmt, "pfn=%lu", 'pfn=%" PRIu64 "'
394                )
395            elif event.name == "sched_stick_numa":
396                event.print_fmt = (
397                    '"sched_stick_numa: src_pid=%d src_tgid=%d src_ngid=%d src_cpu=%d src_nid=%d '
398                    'dst_pid=%d dst_tgid=%d dst_ngid=%d dst_cpu=%d dst_nid=%d", msg.pid(), msg.tgid(), msg.ngid(), '
399                    "msg.src_cpu(), msg.src_nid(), msg.pid(), msg.tgid(), msg.ngid(), msg.dst_cpu(), msg.dst_nid()"
400                )
401            elif event.name == "workqueue_execute_end":
402                event.print_fmt = '"workqueue_execute_end: work struct %p", msg.work()'
403            elif event.name == "workqueue_queue_work":
404                event.print_fmt = str.replace(
405                    event.print_fmt, "REC->workqueue", "msg.workqueue()"
406                )
407            elif (event.name == "i2c_reply") | (event.name == "i2c_write"):
408                event.print_fmt = str.replace(
409                    event.print_fmt, "l=%u [%*phD]", 'l=%" PRId32 " [%" PRId32 "]'
410                )
411                event.print_fmt = str.replace(
412                    event.print_fmt, "REC->len, REC->len", "REC->len"
413                )
414            elif (
415                (event.name == "mm_compaction_isolate_freepages")
416                | (event.name == "mm_compaction_isolate_migratepages")
417                | (event.name == "mm_compaction_begin")
418                | (event.name == "mm_compaction_end")
419                | (event.name == "mm_compaction_migratepages")
420            ):
421                event.print_fmt = str.replace(event.print_fmt, "%lu", '=0x%" PRIu64 "')
422            elif (
423                (event.name == "mm_compaction_defer_compaction")
424                | (event.name == "mm_compaction_defer_reset")
425                | (event.name == "mm_compaction_deferred")
426                | (event.name == "mm_compaction_end")
427                | (event.name == "mm_compaction_migratepages")
428            ):
429                event.print_fmt = str.replace(
430                    event.print_fmt, "REC->order_failed", "msg.order_failed()"
431                )
432            elif (event.name == "signal_deliver") | (event.name == "signal_generate"):
433                event.print_fmt = str.replace(
434                    event.print_fmt, "REC->errno", "msg.error_code()"
435                )
436                event.print_fmt = str.replace(
437                    event.print_fmt, "REC->sa_handler", "msg.sig_handler()"
438                )
439                event.print_fmt = str.replace(
440                    event.print_fmt, "REC->sa_flags", "msg.sig_flags()"
441                )
442            elif (event.name == "sys_enter") | (event.name == "sys_exit"):
443                event.print_fmt = str.replace(event.print_fmt, "%ld", '%" PRIu64 "')
444            elif event.name == "oom_score_adj_update":
445                event.print_fmt = str.replace(
446                    event.print_fmt, "oom_score_adj=%hd", 'oom_score_adj=%" PRId32 "'
447                )
448            elif event.name == "ext4_da_write_pages":
449                event.print_fmt = str.replace(
450                    event.print_fmt,
451                    'first_page %" PRIu64 " nr_to_write %ld',
452                    "first_page " '%" PRIu64 " nr_to_write %" PRIu64 "',
453                )
454            elif event.name == "ext4_discard_preallocations":
455                event.print_fmt = str.replace(
456                    event.print_fmt,
457                    'ino %" PRIu64 " len: %u needed %u',
458                    "ino " '%" PRIu64 "',
459                )
460                event.print_fmt = str.replace(
461                    event.print_fmt, " REC->ino, REC->len, REC->needed", " REC->ino"
462                )
463            elif (
464                (event.name == "ext4_ext_remove_space_done")
465                | (event.name == "ext4_ext_rm_leaf")
466                | (event.name == "ext4_remove_blocks")
467            ):
468                event.print_fmt = str.replace(
469                    event.print_fmt,
470                    ' [pclu %" PRIu64 " lblk %u state %d]',
471                    '%" ' 'PRIu64 "',
472                )
473                event.print_fmt = str.replace(
474                    event.print_fmt,
475                    "(long long) REC->pc_pclu, "
476                    "(unsigned int) REC->pc_lblk, (int) REC->pc_state",
477                    "msg.partial()",
478                )
479            elif event.name == "ext4_free_blocks":
480                event.print_fmt = str.replace(
481                    event.print_fmt, 'count %" PRIu64 "', 'count %" PRIu64 "'
482                )
483            elif event.name == "ext4_journal_start":
484                event.print_fmt = str.replace(
485                    event.print_fmt, ", revoke_creds %d,", ","
486                )
487                event.print_fmt = str.replace(
488                    event.print_fmt, ", REC->revoke_creds,", ","
489                )
490            elif event.name == "ext4_read_block_bitmap_load":
491                event.print_fmt = str.replace(event.print_fmt, "%u prefetch %d", "%u")
492                event.print_fmt = str.replace(
493                    event.print_fmt, "REC->group, REC->prefetch", "msg.group()"
494                )
495            elif event.name == "ext4_writepages":
496                event.print_fmt = str.replace(
497                    event.print_fmt, "nr_to_write %ld", 'nr_to_write %" PRIu64 "'
498                )
499                event.print_fmt = str.replace(
500                    event.print_fmt, "pages_skipped %ld", 'pages_skipped %" PRIu64 "'
501                )
502            elif event.name == "ext4_writepages_result":
503                event.print_fmt = str.replace(
504                    event.print_fmt, "pages_skipped %ld", 'pages_skipped %" PRIu64 "'
505                )
506            elif event.name == "ext4_load_inode":
507                event.print_fmt = str.replace(
508                    event.print_fmt, "ino %ld", 'ino %" PRIu64 "'
509                )
510            elif event.name == "itimer_state":
511                event.print_fmt = str.replace(
512                    event.print_fmt,
513                    "it_value=%ld.%06ld it_interval=%ld.%06ld",
514                    'it_value=%" PRIu64 "it_interval=%" PRIu64 "',
515                )
516                event.print_fmt = str.replace(
517                    event.print_fmt,
518                    "REC->value_nsec / 1000L, REC->interval_sec, "
519                    "REC->interval_nsec / 1000L",
520                    "msg.interval_sec()",
521                )
522            elif event.name == "timer_expire_entry":
523                event.print_fmt = str.replace(
524                    event.print_fmt, "now=%lu baseclk=%lu", 'now=%" PRIu64 "'
525                )
526                event.print_fmt = str.replace(
527                    event.print_fmt, "REC->now, REC->baseclk", "msg.now()"
528                )
529            elif event.name == "timer_start":
530                event.print_fmt = str.replace(
531                    event.print_fmt,
532                    "expires=%lu [timeout=%ld]",
533                    'expires=%" PRIu64' ' " [timeout=%" PRIu64 "]',
534                )
535                event.print_fmt = str.replace(event.print_fmt, ", (long)", ",")
536            elif (event.name == "mm_shrink_slab_end") | (
537                event.name == "mm_shrink_slab_start"
538            ):
539                event.print_fmt = str.replace(
540                    event.print_fmt, "REC->shrink", "msg.shrink()"
541                )
542            elif event.name == "mm_vmscan_lru_shrink_inactive":
543                event.print_fmt = str.replace(
544                    event.print_fmt,
545                    "nr_activate_anon=%d nr_activate_file=%d",
546                    'nr_activate=%" PRIu64 "',
547                )
548                event.print_fmt = str.replace(
549                    event.print_fmt,
550                    "REC->nr_activate0, REC->nr_activate1",
551                    "\
552                    "
553                    "msg.nr_activate()",
554                )
555            elif event.name == "mm_vmscan_writepage":
556                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
557                print_fmt = (event.print_fmt[:56], event.print_fmt[3728:])
558                event.print_fmt = page_str.join(print_fmt)
559            elif event.name == "mm_vmscan_lru_isolate":
560                event.print_fmt = str.replace(
561                    event.print_fmt, "REC->highest_zoneidx", "msg.classzone_idx()"
562                )
563            elif (event.name == "balance_dirty_pages") | (
564                event.name == "bdi_dirty_ratelimit"
565            ):
566                event.print_fmt = str.replace(
567                    event.print_fmt, "REC->bdi_dirty", "msg.bdi_dirty()"
568                )
569                event.print_fmt = str.replace(
570                    event.print_fmt, "REC->bdi_setpoint", "msg.bdi_setpoint()"
571                )
572                event.print_fmt = str.replace(
573                    event.print_fmt, "REC->dirty_ratelimit", "msg.dirty_ratelimit()"
574                )
575                event.print_fmt = str.replace(
576                    event.print_fmt, "REC->dirtied_pause", "msg.dirtied_pause()"
577                )
578            elif event.name == "sched_migrate_task":
579                event.print_fmt = str.replace(
580                    event.print_fmt, "dest_cpu=%d running=%d", "dest_cpu=%d"
581                )
582                event.print_fmt = str.replace(
583                    event.print_fmt, "REC->dest_cpu, REC->running", "msg.dest_cpu()"
584                )
585            elif event.name == "ext4_find_delalloc_range":
586                event.print_fmt = str.replace(
587                    event.print_fmt, "REC->found_blk", "msg.found_blk()"
588                )
589            elif (event.name == "mm_filemap_add_to_page_cache") | (
590                event.name == "mm_filemap_delete_from_page_cache"
591            ):
592                event.print_fmt = (
593                    '"{}: dev %" PRIu64 ":%" PRIu64 " ino %p page=%s pfn=%" PRIu64 " '
594                    'ofs=%" PRIu64 "", (((msg.s_dev()) >> 20)), (((msg.s_dev()) & ((1U << 20) - 1))), '
595                    'msg.i_ino(), "0000000000000000", msg.pfn(), msg.index() << 12'.format(
596                        event.name
597                    )
598                )
599            elif event.name == "ipi_raise":
600                event.print_fmt = str.replace(
601                    event.print_fmt, "target_mask=%s", 'target_mask=%" PRIu64 "'
602                )
603                event.print_fmt = str.replace(
604                    event.print_fmt, "__get_bitmask(target_cpus)", "msg.target_cpus()"
605                )
606            elif event.name == "mm_page_alloc":
607                print_fmt = (event.print_fmt[:78], event.print_fmt[3783:])
608                event.print_fmt = page_str.join(print_fmt)
609            elif event.name == "mm_page_alloc_extfrag":
610                print_fmt = (event.print_fmt[:181], event.print_fmt[3853:])
611                event.print_fmt = page_str.join(print_fmt)
612            elif event.name == "mm_page_alloc_zone_locked":
613                print_fmt = (event.print_fmt[:94], event.print_fmt[3799:])
614                event.print_fmt = page_str.join(print_fmt)
615            elif event.name == "mm_page_free":
616                print_fmt = (event.print_fmt[:49], event.print_fmt[3721:])
617                event.print_fmt = page_str.join(print_fmt)
618            elif event.name == "mm_page_free_batched":
619                print_fmt = (event.print_fmt[:56], event.print_fmt[3728:])
620                event.print_fmt = page_str.join(print_fmt)
621            elif event.name == "mm_page_pcpu_drain":
622                print_fmt = (event.print_fmt[:70], event.print_fmt[3742:])
623                event.print_fmt = page_str.join(print_fmt)
624            elif event.name == "xprt_transmit":
625                event.print_fmt = (
626                    '"xprt_transmit: xid=0x%08x status=%d", msg.xid(), msg.status()'
627                )
628            elif event.name == "rss_stat":
629                event.print_fmt = str.replace(
630                    event.print_fmt, "size=%ldB", 'size=%" PRIu64 "B'
631                )
632            elif event.name == "file_check_and_advance_wb_err":
633                event.print_fmt = str.replace(
634                    event.print_fmt, "REC->new", "msg.seq_new()"
635                )
636            elif event.name == "f2fs_sync_file_enter":
637                event.print_fmt = str.replace(
638                    event.print_fmt, "i_mode = 0x%hx", "i_mode = 0x%x"
639                )
640            elif (event.name == "wakeup_source_activate") | (
641                event.name == "wakeup_source_deactivate"
642            ):
643                event.print_fmt = str.replace(event.print_fmt, "(unsigned long)", "")
644            elif event.name == "print":
645                f.write("    std::string fieldBuf = msg.buf();\n")
646                f.write(
647                    "    if (fieldBuf.size() > 1 && fieldBuf[fieldBuf.size() - 1] == '\\n') {\n"
648                )
649                f.write("        fieldBuf = fieldBuf.substr(0, fieldBuf.size() - 1);\n")
650                f.write("    }\n")
651                event.print_fmt = '"print: %s", fieldBuf.c_str()'
652
653            event.print_fmt = str.replace(event.print_fmt, "%pS", "%p")
654
655            if event.print_fmt.find("%ps") == -1:
656                self.handle_field_name_functions(event, f, False)
657            else:
658                if (event.print_fmt.find("%ps") != -1) & (
659                    event.print_fmt.find("REC->function") != -1
660                ):
661                    if event.name != "workqueue_execute_end":
662                        self.handle_format_ps_functions(event, f, "function")
663                elif (event.print_fmt.find("%ps") != -1) & (
664                    event.print_fmt.find("REC->ip") != -1
665                ):
666                    self.handle_format_ps_functions(event, f, "ip", True)
667                elif (event.print_fmt.find("%ps") != -1) & (
668                    event.print_fmt.find("REC->action") != -1
669                ):
670                    self.handle_format_ps_functions(event, f, "action")
671                elif (
672                    (category == "cpuhp")
673                    & (event.print_fmt.find("%ps") != -1)
674                    & (event.print_fmt.find("REC->fun") != -1)
675                ):
676                    self.handle_format_ps_functions(event, f, "fun")
677                elif (event.name == "funcgraph_entry") | (
678                    event.name == "funcgraph_exit"
679                ):
680                    self.handle_format_ps_functions(event, f, "func", True)
681                elif (event.name == "kernel_stack") | (event.name == "user_stack"):
682                    f.write("    int len = 0;\n")
683                    f.write('    std::string kernelSymbolsStr = "";\n')
684                    f.write(
685                        "    auto& kernelSymbols = EventFormatter::GetInstance().kernelSymbols_;\n"
686                    )
687                    f.write("    if (kernelSymbols.count(msg.caller()[0]) > 0) {\n")
688                    f.write(
689                        "        kernelSymbolsStr = kernelSymbols[msg.caller()[0]];\n"
690                    )
691                    f.write("    }\n")
692                    f.write('    if (kernelSymbolsStr != "") {\n        ')
693                    print_fmt = event.print_fmt
694                    event.print_fmt = str.replace(event.print_fmt, "%ps", "%s")
695                    offset = 0
696                    if event.name == "kernel_stack":
697                        offset = 2
698                    event.print_fmt = (
699                        "{}kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]]."
700                        "c_str(), kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str(), "
701                        "kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str(),"
702                        " kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str()"
703                        "".format(
704                            event.print_fmt[: 94 + offset],
705                            event.print_fmt[114 + offset],
706                            event.print_fmt[138 + offset],
707                            event.print_fmt[162 + offset],
708                            event.print_fmt[186 + offset],
709                            event.print_fmt[210 + offset],
710                            event.print_fmt[234 + offset],
711                            event.print_fmt[258 + offset],
712                            event.print_fmt[282 + offset],
713                        )
714                    )
715                    f.write(
716                        "    len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(
717                            event.print_fmt
718                        )
719                    )
720                    f.write("    } else {\n")
721                    event.print_fmt = print_fmt
722                    event.print_fmt = str.replace(event.print_fmt, "%ps", "%p")
723                    self.handle_field_name_functions(event, f)
724                    f.write("    }\n")
725
726            f.write("    if (len >= BUFFER_SIZE - 1) {\n")
727            f.write(
728                '      PROFILER_LOG_WARN(LOG_CORE, "maybe, the contents of print event({}) msg had be cut off '
729                'in outfile");\n'.format(event.name)
730            )
731            f.write("    }\n")
732            f.write("    return std::string(buffer);\n")
733            f.write("});\n")  # end of format function
734
735    def handle_field_name_functions(self, event, f, is_define_len=True):
736        for field_info in event.remain_fields:
737            field_name = fix_field_name(field_info.name)
738            event.print_fmt = str.replace(
739                event.print_fmt,
740                "__get_str({})".format(field_name),
741                "msg.{}().c_str()".format(field_name),
742            )
743            event.print_fmt = str.replace(
744                event.print_fmt,
745                "__get_dynamic_array({})".format(field_name),
746                "msg.{}()".format(field_name),
747            )
748            if (
749                field_info.field.startswith("char {}[".format(field_name))
750                | field_info.field.startswith("const char {}[".format(field_name))
751                | field_info.field.startswith("char *")
752                | field_info.field.startswith("const char *")
753            ):
754                event.print_fmt = str.replace(
755                    event.print_fmt,
756                    "REC->{}".format(field_name),
757                    "msg.{}().c_str()".format(field_name),
758                )
759            else:
760                event.print_fmt = str.replace(
761                    event.print_fmt,
762                    "REC->{}".format(field_name),
763                    "msg.{}()".format(field_name),
764                )
765        if event.name == "sched_switch":
766            f.write("    int len = 0;\n")
767            f.write("    if (msg.prev_state() > 0x0400) {\n")
768            f.write(
769                '        len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, "sched_switch: prev_comm=%s '
770                'prev_pid=%d prev_prio=%d prev_state=? ==> next_comm=%s next_pid=%d next_prio=%d", msg.prev_comm()'
771                ".c_str(), msg.prev_pid(), msg.prev_prio(), msg.next_comm().c_str(), msg.next_pid(), "
772                "msg.next_prio());\n"
773            )
774            f.write("    } else {\n")
775            f.write(
776                '        len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, "sched_switch: prev_comm=%s '
777                'prev_pid=%d prev_prio=%d prev_state=%s%s ==> next_comm=%s next_pid=%d next_prio=%d", '
778                "msg.prev_comm().c_str(), msg.prev_pid(), msg.prev_prio(), (msg.prev_state() & ((((0x0000 | 0x0001 "
779                "| 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) << 1) - 1)) ? __print_flags("
780                "msg.prev_state() & ((((0x0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) "
781                '<< 1) - 1), "|", { 0x0001, "S" }, { 0x0002, "D" }, { 0x0004, "T" }, { 0x0008, "t" }, '
782                '{ 0x0010, "X" }, { 0x0020, "Z" }, { 0x0040, "I" }, { 0x0080, "K" }, { 0x0100, "W" }, { '
783                '0x0200, "P" }, { 0x0400, "N" }): "R", msg.prev_state() & (((0x0000 | 0x0001 | 0x0002 | '
784                '0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040) + 1) << 1) ? "+": "", msg.next_comm().c_str(), '
785                "msg.next_pid(), msg.next_prio());\n"
786            )
787            f.write("    }\n")
788        elif is_define_len:
789            f.write(
790                "    len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(
791                    event.print_fmt
792                )
793            )
794        else:
795            f.write(
796                "    int len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(
797                    event.print_fmt
798                )
799            )
800
801    def handle_format_ps_functions(self, event, f, filed_name, is_void=False):
802        f.write("    int len = 0;\n")
803        f.write('    std::string functionStr = "";\n')
804        f.write(
805            "    auto& kernelSymbols = EventFormatter::GetInstance().kernelSymbols_;\n"
806        )
807        f.write("    if (kernelSymbols.count(msg.{}()) > 0) ".format(filed_name))
808        f.write("{\n")
809        f.write("        functionStr = kernelSymbols[msg.{}()];\n".format(filed_name))
810        f.write("    }\n")
811        f.write('    if (functionStr != "") {\n        ')
812        print_fmt = event.print_fmt
813        event.print_fmt = str.replace(event.print_fmt, "%ps", "%s")
814        if is_void:
815            event.print_fmt = str.replace(
816                event.print_fmt,
817                "(void *)REC->{}".format(filed_name),
818                "functionStr.c_str()",
819            )
820        else:
821            event.print_fmt = str.replace(
822                event.print_fmt, "REC->{}".format(filed_name), "functionStr.c_str()"
823            )
824        self.handle_field_name_functions(event, f)
825        f.write("    } else {\n")
826        event.print_fmt = print_fmt
827        event.print_fmt = str.replace(event.print_fmt, "%ps", "%p")
828        self.handle_field_name_functions(event, f)
829        f.write("    }\n")
830
831
832def main():
833    parser = argparse.ArgumentParser(description="FTrace C++ code generator.")
834    parser.add_argument(
835        "-a",
836        dest="allow_list",
837        required=True,
838        type=str,
839        help="event allow list file path",
840    )
841    parser.add_argument(
842        "-e", dest="events_dir", required=True, type=str, help="event formats directory"
843    )
844    parser.add_argument(
845        "-p",
846        dest="parser_out",
847        required=False,
848        type=str,
849        help="parser code output directory",
850    )
851    parser.add_argument(
852        "-f",
853        dest="formatter_out",
854        required=False,
855        type=str,
856        help="formaater code output directory",
857    )
858
859    args = parser.parse_args(sys.argv[1:])
860    allow_list = args.allow_list
861    events_dir = args.events_dir
862    parser_out = args.parser_out
863    formatter_out = args.formatter_out
864
865    # check arguments
866    if not os.path.isfile(allow_list):
867        parser.print_usage()
868        exit(1)
869    if not os.path.isdir(events_dir):
870        parser.print_usage()
871        exit(2)
872
873    if parser_out:
874        if not os.path.isdir(parser_out):
875            parser.print_usage()
876            exit(3)
877        parser_gen = EventParserCodeGenerator(events_dir, allow_list)
878        parser_gen.generate(os.path.join(parser_out))
879        sh_path = "../../../format-code.sh "
880        if os.getcwd().find("device_kernel_version") != -1:
881            sh_path = "../../{}".format(sh_path)
882        parser_sub = subprocess.Popen("{}{}".format(sh_path, parser_out), shell=True)
883        parser_sub.wait()
884        parser_sub = subprocess.Popen(
885            "chmod 775 {}*.cpp".format(parser_out), shell=True
886        )
887        parser_sub.wait()
888
889    if formatter_out:
890        if not os.path.isdir(formatter_out):
891            parser.print_usage()
892            exit(4)
893        fmtter_gen = EventFormatterCodeGenerator(events_dir, allow_list)
894        fmtter_gen.generate(formatter_out)
895        sh_path = "../../../format-code.sh "
896        if os.getcwd().find("device_kernel_version") != -1:
897            sh_path = "../../{}".format(sh_path)
898        formatter_sub = subprocess.Popen(
899            "{}{}".format(sh_path, formatter_out), shell=True
900        )
901        formatter_sub.wait()
902        formatter_sub = subprocess.Popen(
903            "chmod 775 {}*.cpp".format(formatter_out), shell=True
904        )
905        formatter_sub.wait()
906
907
908if __name__ == "__main__":
909    main()
910