• 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 ForStandard::FtraceEvent& event) -> bool'
70FORMAT_FUNCTION_ARGS = '(const ForStandard::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        'new': 'seq_new'
84    }
85    if name in replace_map:
86        name = replace_map[name]
87    return str.lower(name)
88
89
90def ensure_dir_exists(file_path):
91    file_dir = os.path.dirname(file_path)
92    if not os.path.exists(file_dir):
93        os.mkdir(file_dir)
94
95
96class Common:
97    this_file = os.path.basename(__file__)
98    logging.basicConfig(
99        format="%(asctime)s %(levelname)s %(message)s", level=logging.INFO
100    )
101    logger = logging.getLogger(this_file)
102    cpp_copyright_header = CPP_COPYRIGHT_HEADER
103    parse_register_macro = PARSE_REGISTER_MACRO
104    auto_generated_gni = AUTO_GENERATED_GNI
105    parse_function_args = PARSE_FUNCTION_ARGS
106    gn_copyright_header = GN_COPYRIGHT_HEADER
107
108
109class EventParserCodeGenerator(FtraceEventCodeGenerator):
110    def __init__(self, events_dir, allow_list):
111        super().__init__(events_dir, allow_list)
112
113    def parser_file_path(self, category):
114        file_name = 'ftrace_{}_event_parser.cpp'.format(category)
115        return os.path.join(self.output_dir, file_name)
116
117    def generate_code(self):
118        generated_cpp_sources = []
119
120        for event in self.target_event_formats:
121            type_name = '{}/{}'.format(event.category, event.name)
122            logger.info('ftrace_events: "{}"'.format(type_name))
123
124        # generate sub event parser code
125        for category in self.grouped_event_formats:
126            parser_src_file = self.parser_file_path(category)
127            generated_cpp_sources.append(parser_src_file)
128
129            logger.info('Generate {} ...'.format(parser_src_file))
130            ensure_dir_exists(parser_src_file)
131
132            with open(parser_src_file, 'w', encoding='utf-8') as f:
133                f.write(CPP_COPYRIGHT_HEADER)
134                f.write('#include "sub_event_parser.h"\n')
135                f.write('\n')
136                f.write("FTRACE_NS_BEGIN\n")
137                f.write("namespace {\n")
138                self.generate_parse_functions(category, f)
139                f.write("} // namespace\n")
140                f.write("FTRACE_NS_END\n")
141                f.write('\n')
142
143        # generate .gni
144        generated_cpp_gni = os.path.join(self.output_dir, AUTO_GENERATED_GNI)
145        logger.info('Generate {} ...'.format(generated_cpp_gni))
146        with open(generated_cpp_gni, 'w', encoding='utf-8') as f:
147            f.write(GN_COPYRIGHT_HEADER)
148            f.write('\n')
149            f.write('auto_generated_cpp_sources = [\n')
150            for path in generated_cpp_sources:
151                src = '{}'.format(os.path.basename(path))
152                f.write('  "{}",\n'.format(src))
153            f.write(']\n')
154
155    def generate_parse_functions(self, category, f):
156        count = 0
157        for event in self.grouped_event_formats[category]:
158            count += 1
159            if count > 1:
160                f.write('\n')
161            f.write('{}({},\n'.format(PARSE_REGISTER_MACRO, event.name))
162            f.write('[] {} {{\n'.format(PARSE_FUNCTION_ARGS))
163            f.write('    int i = 0;\n')
164            f.write('    auto msg = ftraceEvent.mutable_{}_format();\n'.format(
165                str.lower(event.name)))
166            for i in range(len(event.remain_fields)):
167                self.generate_parse_field_lines(event, f, i)
168            f.write("});\n")
169
170    @staticmethod
171    def generate_parse_field_lines(event, f, i):
172        field_info = event.remain_fields[i]
173        field_name = fix_field_name(field_info.name)
174        type_info = field_info.to_proto_type()
175        parse_func = None
176        if type_info.tid == ProtoType.STRING:
177            parse_func = 'ParseStrField'
178        elif type_info.tid == ProtoType.ARRAY:
179            parse_func = 'ParseVectorIntField'
180        elif type_info.tid == ProtoType.INTEGER:
181            assert type_info.size in [4, 8]
182            c_type = None
183            if type_info.size == 4:
184                c_type = 'int32_t' if type_info.signed else 'uint32_t'
185            elif type_info.size == 8:
186                c_type = 'int64_t' if type_info.signed else 'uint64_t'
187            parse_func = 'ParseIntField<{}>'.format(c_type)
188        else:
189            logger.warning('WARNING: unkown proto type:{} {}'.format(
190                event.name, field_name))
191        assert parse_func
192        if (type_info.tid == ProtoType.ARRAY):
193            f.write('    std::vector<uint64_t> retvalVec = FtraceFieldParser::ParseVectorIntField<uint64_t>(format.fields, i++, data, size);')
194            f.write('    for (size_t i = 0; i < retvalVec.size(); i++) {')
195            f.write('    msg->add_{}(retvalVec[i]);'.format(field_name))
196            f.write('    }')
197        else:
198            f.write('    msg->set_{}(FtraceFieldParser::'.format(field_name))
199            f.write('{}(format.fields, i++, data, size));\n'.format(parse_func))
200
201
202class EventFormatterCodeGenerator(FtraceEventCodeGenerator):
203    def __init__(self, events_dir, allow_list):
204        super().__init__(events_dir, allow_list)
205
206    def formatter_file_path(self, category):
207        file_name = 'ftrace_{}_event_formatter.cpp'.format(category)
208        return os.path.join(self.output_dir, file_name)
209
210    def generate_code(self):
211        generated_cpp_sources = []
212
213        # generate sub event parser code
214        for category in self.grouped_event_formats:
215            formatter_src_file = self.formatter_file_path(category)
216            generated_cpp_sources.append(formatter_src_file)
217
218            logger.info('Generate {} ...'.format(formatter_src_file))
219            ensure_dir_exists(formatter_src_file)
220
221            with open(formatter_src_file, 'w', encoding='utf-8') as f:
222                f.write(CPP_COPYRIGHT_HEADER)
223                f.write('#include <cinttypes>\n')
224                f.write('\n')
225                f.write('#include "event_formatter.h"\n')
226                if (category == "binder") :
227                    f.write('#include "binder.h"\n')
228                f.write('#include "logging.h"\n')
229                if (category == "f2fs") :
230                    f.write('#include "f2fs.h"\n')
231                elif (category == "power") :
232                    f.write('#include "pm_qos.h"\n')
233                elif (category == "writeback") :
234                    f.write('#include "pq.h"\n')
235                elif (category == "compaction")  | (category == "kmem") | (category == "vmscan") :
236                    f.write('#include "type.h"\n')
237                elif (category == "timer") :
238                    f.write('#include "hrtimer.h"\n')
239                f.write('#include "trace_events.h"\n')
240                f.write('\n')
241                f.write("FTRACE_NS_BEGIN\n")
242                f.write("namespace {\n")
243                f.write('const int BUFFER_SIZE = 512;\n')
244                f.write('\n')
245                self.generate_format_functions(category, f)
246                f.write("} // namespace\n")
247                f.write("FTRACE_NS_END\n")
248                f.write('\n')
249
250        # generate .gni
251        generated_cpp_gni = os.path.join(self.output_dir, AUTO_GENERATED_GNI)
252        logger.info('Generate {} ...'.format(generated_cpp_gni))
253        with open(generated_cpp_gni, 'w', encoding='utf-8') as f:
254            f.write(GN_COPYRIGHT_HEADER)
255            f.write('\n')
256            f.write('auto_generated_cpp_sources = [\n')
257            for path in generated_cpp_sources:
258                src = '{}'.format(os.path.basename(path))
259                f.write('  "{}",\n'.format(src))
260            f.write(']\n')
261
262    def generate_format_functions(self, category, f):
263        count = 0
264        for event in self.grouped_event_formats[category]:
265            count += 1
266            if count > 1:
267                f.write('\n')
268            f.write('{}({},\n'.format(FORMAT_REGISTER_MACRO, str.lower(event.name)))
269            f.write('[] {} {{\n'.format(CHECK_FUNCTION_ARGS, ))
270            f.write('    return event.has_{}_format();'.format(
271                str.lower(event.name)))
272            f.write('},')  # end of check function
273            f.write('[] {} {{\n'.format(FORMAT_FUNCTION_ARGS))
274            f.write('    auto msg = event.{}_format();\n'.format(
275                str.lower(event.name)))
276            f.write("    char buffer[BUFFER_SIZE];\n")
277            event.print_fmt = "\"{}: {}".format(event.name, event.print_fmt[2:])
278            event.print_fmt = str.replace(event.print_fmt, "%zu", "%\" PRIu64 \"")
279            event.print_fmt = str.replace(event.print_fmt, "%zd", "%\" PRIu64 \"")
280            event.print_fmt = str.replace(event.print_fmt, "%llu", "%\" PRIu64 \"")
281            event.print_fmt = str.replace(event.print_fmt, "%lld", "%\" PRIu64 \"")
282            event.print_fmt = str.replace(event.print_fmt, "%lx", "%\" PRIx64 \"")
283            event.print_fmt = str.replace(event.print_fmt, "%llx", "%\" PRIx64 \"")
284            event.print_fmt = str.replace(event.print_fmt, "(unsigned long long)", "")
285
286            if (category == "kmem") | (category == "filemap") :
287                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
288                event.print_fmt = str.replace(event.print_fmt, "REC->pfn != -1UL ? (((struct page *)vmemmap_base) + (REC->pfn)) : ((void *)0)", "\"0000000000000000\"")
289                event.print_fmt = str.replace(event.print_fmt, "(((struct page *)vmemmap_base) + (REC->pfn))", "\"0000000000000000\"")
290                event.print_fmt = str.replace(event.print_fmt, " (void *)", " ")
291                event.print_fmt = str.replace(event.print_fmt, " name=%s\"", "\"")
292                event.print_fmt = str.replace(event.print_fmt, "REC->ptr, __get_str(name)", "REC->ptr")
293                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRIu64 \"")
294            elif (category == "filelock") :
295                event.print_fmt = str.replace(event.print_fmt, "=%lu", "=%\" PRIu64 \"")
296                event.print_fmt = str.replace(event.print_fmt, "REC->fl_blocker", "msg.fl_next()")
297                event.print_fmt = str.replace(event.print_fmt, "REC->fl_owner", "msg.fl_owner()")
298                event.print_fmt = str.replace(event.print_fmt, "REC->fl_flags", "msg.fl_flags()")
299                event.print_fmt = str.replace(event.print_fmt, "REC->fl_type", "msg.fl_type()")
300                event.print_fmt = str.replace(event.print_fmt, "REC->fl_break_time", "msg.fl_break_time()")
301                event.print_fmt = str.replace(event.print_fmt, "REC->fl_downgrade_time", "msg.fl_downgrade_time()")
302                event.print_fmt = str.replace(event.print_fmt, "REC->rcount", "msg.dcount()")
303            elif (category == "ext4") :
304                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRIu64 \"")
305                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long)", ",")
306            elif (category == "vmscan") :
307                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRIu64 \"")
308                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRIu64 \"")
309            elif (category == "writeback") :
310                event.print_fmt = str.replace(event.print_fmt, ", (unsigned long)", ", ")
311                event.print_fmt = str.replace(event.print_fmt, "cgroup_ino=%lu", "cgroup_ino=%\" PRId32 \"")
312                event.print_fmt = str.replace(event.print_fmt, "%lu", "%\" PRIu64 \"")
313                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRIu64 \"")
314            elif (category == "sunrpc") :
315                event.print_fmt = str.replace(event.print_fmt, "=%lu", "=%\" PRIu64 \"")
316            elif (category == "sched") :
317                event.print_fmt = str.replace(event.print_fmt, "%Lu", "%\" PRIu64 \"")
318            elif (category == "ftrace") :
319                event.print_fmt = str.replace(event.print_fmt, "(unsigned long)", "")
320
321            if (event.name == "binder_command") :
322                event.print_fmt = "\"binder_command: cmd=0x%x\", msg.cmd()"
323            elif (event.name == "binder_return") :
324                event.print_fmt = "\"binder_return: cmd=0x%x\", msg.cmd()"
325            elif (event.name == "task_newtask") | (event.name == "task_rename") :
326                event.print_fmt = str.replace(event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%d")
327            elif (event.name == "branch_format"):
328                event.print_fmt = "\"branch: %u:%s:%s (%u)%s\", msg.line(), msg.func().c_str(), msg.file().c_str(), msg.correct(), msg.constant() ? \" CONSTANT\" : \"\""
329            elif (event.name == "mm_lru_activate") | (event.name == "mm_lru_insertion") :
330                event.print_fmt = str.replace(event.print_fmt, "pfn=%lu", "pfn=%\" PRIu64 \"")
331            elif (event.name == "sched_stick_numa"):
332                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()"
333            elif (event.name == "workqueue_execute_end"):
334                event.print_fmt = "\"workqueue_execute_end: work struct %p\", msg.work()"
335            elif (event.name == "workqueue_queue_work"):
336                event.print_fmt = str.replace(event.print_fmt, "REC->workqueue", "msg.workqueue()")
337            elif (event.name == "i2c_reply") | (event.name == "i2c_write") :
338                event.print_fmt = str.replace(event.print_fmt, "l=%u [%*phD]", "l=%\" PRId32 \" [%\" PRId32 \"]")
339                event.print_fmt = str.replace(event.print_fmt, "REC->len, REC->len", "REC->len")
340            elif (event.name == "mm_compaction_isolate_freepages") | (event.name == "mm_compaction_isolate_migratepages") \
341                    | (event.name == "mm_compaction_begin") | (event.name == "mm_compaction_end") \
342                    | (event.name == "mm_compaction_migratepages") :
343                event.print_fmt = str.replace(event.print_fmt, "%lu", "=0x%\" PRIu64 \"")
344            elif (event.name == "mm_compaction_defer_compaction") | (event.name == "mm_compaction_defer_reset") \
345                    | (event.name == "mm_compaction_deferred") | (event.name == "mm_compaction_end") \
346                    | (event.name == "mm_compaction_migratepages") :
347                event.print_fmt = str.replace(event.print_fmt, "REC->order_failed", "msg.order_failed()")
348            elif (event.name == "signal_deliver") | (event.name == "signal_generate") :
349                event.print_fmt = str.replace(event.print_fmt, "REC->errno", "msg.error_code()")
350                event.print_fmt = str.replace(event.print_fmt, "REC->sa_handler", "msg.sig_handler()")
351                event.print_fmt = str.replace(event.print_fmt, "REC->sa_flags", "msg.sig_flags()")
352            elif (event.name == "sys_enter") | (event.name == "sys_exit"):
353                event.print_fmt = str.replace(event.print_fmt, "%ld", "%\" PRIu64 \"")
354            elif (event.name == "oom_score_adj_update"):
355                event.print_fmt = str.replace(event.print_fmt, "oom_score_adj=%hd", "oom_score_adj=%\" PRId32 \"")
356            elif (event.name == "ext4_da_write_pages"):
357                event.print_fmt = str.replace(event.print_fmt, "first_page %\" PRIu64 \" nr_to_write %ld", "first_page %\" PRIu64 \" nr_to_write %\" PRIu64 \"")
358            elif (event.name == "ext4_discard_preallocations"):
359                event.print_fmt = str.replace(event.print_fmt, "ino %\" PRIu64 \" len: %u needed %u", "ino %\" PRIu64 \"")
360                event.print_fmt = str.replace(event.print_fmt, " REC->ino, REC->len, REC->needed", " REC->ino")
361            elif (event.name == "ext4_ext_remove_space_done") | (event.name == "ext4_ext_rm_leaf") | (event.name == "ext4_remove_blocks") :
362                event.print_fmt = str.replace(event.print_fmt, " [pclu %\" PRIu64 \" lblk %u state %d]", "%\" PRIu64 \"")
363                event.print_fmt = str.replace(event.print_fmt, "(long long) REC->pc_pclu, (unsigned int) REC->pc_lblk, (int) REC->pc_state", "msg.partial()")
364            elif (event.name == "ext4_free_blocks"):
365                event.print_fmt = str.replace(event.print_fmt, "count %\" PRIu64 \"", "count %\" PRIu64 \"")
366            elif (event.name == "ext4_journal_start"):
367                event.print_fmt = str.replace(event.print_fmt, ", revoke_creds %d,", ",")
368                event.print_fmt = str.replace(event.print_fmt, ", REC->revoke_creds,", ",")
369            elif (event.name == "ext4_read_block_bitmap_load"):
370                event.print_fmt = str.replace(event.print_fmt, "%u prefetch %d", "%u")
371                event.print_fmt = str.replace(event.print_fmt, "REC->group, REC->prefetch", "msg.group()")
372            elif (event.name == "ext4_writepages"):
373                event.print_fmt = str.replace(event.print_fmt, "nr_to_write %ld", "nr_to_write %\" PRIu64 \"")
374                event.print_fmt = str.replace(event.print_fmt, "pages_skipped %ld", "pages_skipped %\" PRIu64 \"")
375            elif (event.name == "ext4_writepages_result"):
376                event.print_fmt = str.replace(event.print_fmt, "pages_skipped %ld", "pages_skipped %\" PRIu64 \"")
377            elif (event.name == "ext4_load_inode"):
378                event.print_fmt = str.replace(event.print_fmt, "ino %ld", "ino %\" PRIu64 \"")
379            elif (event.name == "itimer_state") :
380                event.print_fmt = str.replace(event.print_fmt, "it_value=%ld.%06ld it_interval=%ld.%06ld", "it_value=%\" PRIu64 \"it_interval=%\" PRIu64 \"")
381                event.print_fmt = str.replace(event.print_fmt, "REC->value_nsec / 1000L, REC->interval_sec, REC->interval_nsec / 1000L", "msg.interval_sec()")
382            elif (event.name == "timer_expire_entry") :
383                event.print_fmt = str.replace(event.print_fmt, "now=%lu baseclk=%lu", "now=%\" PRIu64 \"")
384                event.print_fmt = str.replace(event.print_fmt, "REC->now, REC->baseclk", "msg.now()")
385            elif (event.name == "timer_start") :
386                event.print_fmt = str.replace(event.print_fmt, "expires=%lu [timeout=%ld]", "expires=%\" PRIu64 \" [timeout=%\" PRIu64 \"]")
387                event.print_fmt = str.replace(event.print_fmt, ", (long)", ",")
388            elif (event.name == "mm_shrink_slab_end") | (event.name == "mm_shrink_slab_start") :
389                event.print_fmt = str.replace(event.print_fmt, "REC->shrink", "msg.shrink()")
390            elif (event.name == "mm_vmscan_lru_shrink_inactive") :
391                event.print_fmt = str.replace(event.print_fmt, "nr_activate_anon=%d nr_activate_file=%d", "nr_activate=%\" PRIu64 \"")
392                event.print_fmt = str.replace(event.print_fmt, "REC->nr_activate0, REC->nr_activate1", "msg.nr_activate()")
393            elif (event.name == "mm_vmscan_writepage") :
394                event.print_fmt = str.replace(event.print_fmt, "page=%p", "page=%s")
395                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:56], event.print_fmt[3728:])
396            elif (event.name == "mm_vmscan_lru_isolate") :
397                event.print_fmt = str.replace(event.print_fmt, "REC->highest_zoneidx", "msg.classzone_idx()")
398            elif (event.name == "balance_dirty_pages") | (event.name == "bdi_dirty_ratelimit") :
399                event.print_fmt = str.replace(event.print_fmt, "REC->bdi_dirty", "msg.bdi_dirty()")
400                event.print_fmt = str.replace(event.print_fmt, "REC->bdi_setpoint", "msg.bdi_setpoint()")
401                event.print_fmt = str.replace(event.print_fmt, "REC->dirty_ratelimit", "msg.dirty_ratelimit()")
402                event.print_fmt = str.replace(event.print_fmt, "REC->dirtied_pause", "msg.dirtied_pause()")
403            elif (event.name == "sched_migrate_task") :
404                event.print_fmt = str.replace(event.print_fmt, "dest_cpu=%d running=%d", "dest_cpu=%d")
405                event.print_fmt = str.replace(event.print_fmt, "REC->dest_cpu, REC->running", "msg.dest_cpu()")
406            elif (event.name == "ext4_find_delalloc_range") :
407                event.print_fmt = str.replace(event.print_fmt, "REC->found_blk", "msg.found_blk()")
408            elif (event.name == "mm_filemap_add_to_page_cache") | (event.name == "mm_filemap_delete_from_page_cache"):
409                event.print_fmt = "\"{}: dev %\" PRIu64 \":%\" PRIu64 \" ino %p page=%s pfn=%\" PRIu64 \" ofs=%\" PRIu64 \"\", (((msg.s_dev()) >> 20)), (((msg.s_dev()) & ((1U << 20) - 1))), msg.i_ino(), \"0000000000000000\", msg.pfn(), msg.index() << 12".format(event.name)
410            elif (event.name == "ipi_raise") :
411                event.print_fmt = str.replace(event.print_fmt, "target_mask=%s", "target_mask=%\" PRIu64 \"")
412                event.print_fmt = str.replace(event.print_fmt, "__get_bitmask(target_cpus)", "msg.target_cpus()")
413            elif (event.name == "mm_page_alloc") :
414                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:78], event.print_fmt[3783:])
415            elif (event.name == "mm_page_alloc_extfrag") :
416                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:181], event.print_fmt[3853:])
417            elif (event.name == "mm_page_alloc_zone_locked") :
418                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:181], event.print_fmt[3853:])
419            elif (event.name == "mm_page_free") :
420                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:49], event.print_fmt[3721:])
421            elif (event.name == "mm_page_free_batched") :
422                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:56], event.print_fmt[3728:])
423            elif (event.name == "mm_page_pcpu_drain") :
424                event.print_fmt = "{} \"0000000000000000\"{}".format(event.print_fmt[:70], event.print_fmt[3742:])
425            elif (event.name == "xprt_transmit"):
426                event.print_fmt = "\"xprt_transmit: xid=0x%08x status=%d\", msg.xid(), msg.status()"
427            elif (event.name == "rss_stat") :
428                event.print_fmt = str.replace(event.print_fmt, "size=%ldB", "size=%\" PRIu64 \"B")
429            elif (event.name == "file_check_and_advance_wb_err") :
430                event.print_fmt = str.replace(event.print_fmt, "REC->new", "msg.seq_new()")
431            elif (event.name == "f2fs_sync_file_enter") :
432                event.print_fmt = str.replace(event.print_fmt, "i_mode = 0x%hx", "i_mode = 0x%x")
433            elif (event.name == "wakeup_source_activate") | (event.name == "wakeup_source_deactivate") :
434                event.print_fmt = str.replace(event.print_fmt, "(unsigned long)", "")
435            elif (event.name == "print") :
436                f.write("    std::string fieldBuf = msg.buf();\n")
437                f.write("    if (fieldBuf.size() > 1 && fieldBuf[fieldBuf.size() - 1] == '\\n') {\n")
438                f.write("        fieldBuf = fieldBuf.substr(0, fieldBuf.size() - 1);\n")
439                f.write("    }\n")
440                event.print_fmt = "\"print: %s\", fieldBuf.c_str()"
441
442            event.print_fmt = str.replace(event.print_fmt, "%pS", "%p")
443
444            if (event.print_fmt.find("%ps") == -1) :
445                self.handle_field_name_functions(event, f, False)
446            else :
447                if ((event.print_fmt.find("%ps") != -1) & (event.print_fmt.find("REC->function") != -1)) :
448                    if (event.name != "workqueue_execute_end") :
449                        self.handle_format_ps_functions(event, f, "function")
450                elif ((event.print_fmt.find("%ps") != -1) & (event.print_fmt.find("REC->ip") != -1)) :
451                    self.handle_format_ps_functions(event, f, "ip", True)
452                elif ((event.print_fmt.find("%ps") != -1) & (event.print_fmt.find("REC->action") != -1)) :
453                    self.handle_format_ps_functions(event, f, "action")
454                elif ((category == "cpuhp") & (event.print_fmt.find("%ps") != -1) & (event.print_fmt.find("REC->fun") != -1)) :
455                    self.handle_format_ps_functions(event, f, "fun")
456                elif ((event.name == "funcgraph_entry") | (event.name == "funcgraph_exit")) :
457                    self.handle_format_ps_functions(event, f, "func", True)
458                elif (event.name == "kernel_stack") | (event.name == "user_stack") :
459                    f.write("    int len = 0;\n")
460                    f.write("    std::string kernelSymbolsStr = \"\";\n")
461                    f.write("    auto kernelSymbols = EventFormatter::GetInstance().kernelSymbols_;\n")
462                    f.write("    if (kernelSymbols.count(msg.caller()[0]) > 0) {\n")
463                    f.write("        kernelSymbolsStr = kernelSymbols[msg.caller()[0]];\n")
464                    f.write("    }\n")
465                    f.write("    if (kernelSymbolsStr != \"\") {\n        ")
466                    print_fmt = event.print_fmt
467                    event.print_fmt = str.replace(event.print_fmt, "%ps", "%s")
468                    offset = 0
469                    if (event.name == "kernel_stack") :
470                        offset = 2
471                    event.print_fmt = "{}kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str()," \
472                        " kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str()," \
473                        " kernelSymbols[msg.caller()[{}]].c_str(), kernelSymbols[msg.caller()[{}]].c_str()".format(event.print_fmt[:94+offset], event.print_fmt[114+offset],
474                        event.print_fmt[138+offset], event.print_fmt[162+offset], event.print_fmt[186+offset], event.print_fmt[210+offset], event.print_fmt[234+offset],
475                        event.print_fmt[258+offset], event.print_fmt[282+offset])
476                    f.write("    len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(event.print_fmt))
477                    f.write("    } else {\n")
478                    event.print_fmt = print_fmt
479                    event.print_fmt = str.replace(event.print_fmt, "%ps", "%p")
480                    self.handle_field_name_functions(event, f)
481                    f.write("    }\n")
482
483            f.write('    if (len >= BUFFER_SIZE - 1) {\n')
484            f.write('      HILOG_WARN(LOG_CORE, "maybe, the contents of print event({}) msg had be cut off in outfile");\n'.format(event.name))
485            f.write('    }\n')
486            f.write("    return std::string(buffer);\n")
487            f.write("});\n")  # end of format function
488
489    def handle_field_name_functions(self, event, f, is_define_len=True):
490        for field_info in event.remain_fields:
491            field_name = fix_field_name(field_info.name)
492            event.print_fmt = str.replace(event.print_fmt, "__get_str({})".format(field_name),
493                                                "msg.{}().c_str()".format(field_name))
494            event.print_fmt = str.replace(event.print_fmt, "__get_dynamic_array({})".format(field_name),
495                                                "msg.{}()".format(field_name))
496            if field_info.field.startswith('char {}['.format(field_name)) \
497                | field_info.field.startswith('const char {}['.format(field_name)) \
498                | field_info.field.startswith('char *') | field_info.field.startswith('const char *'):
499                event.print_fmt = str.replace(event.print_fmt, "REC->{}".format(field_name), "msg.{}().c_str()".format(field_name))
500            else:
501                event.print_fmt = str.replace(event.print_fmt, "REC->{}".format(field_name), "msg.{}()".format(field_name))
502        if (event.name == "sched_switch"):
503            f.write("    int len = 0;\n")
504            f.write("    if (msg.prev_state() > 0x0400) {\n")
505            f.write('        len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, "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')
506            f.write("    } else {\n")
507            f.write('        len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, "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')
508            f.write("    }\n")
509        elif (is_define_len) :
510            f.write("    len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(event.print_fmt))
511        else :
512            f.write("    int len = snprintf_s(buffer, BUFFER_SIZE, BUFFER_SIZE - 1, {});\n".format(event.print_fmt))
513
514    def handle_format_ps_functions(self, event, f, filed_name, is_void=False):
515        f.write("    int len = 0;\n")
516        f.write("    std::string functionStr = \"\";\n")
517        f.write("    auto kernelSymbols = EventFormatter::GetInstance().kernelSymbols_;\n")
518        f.write("    if (kernelSymbols.count(msg.{}()) > 0) ".format(filed_name))
519        f.write("{\n")
520        f.write("        functionStr = kernelSymbols[msg.{}()];\n".format(filed_name))
521        f.write("    }\n")
522        f.write("    if (functionStr != \"\") {\n        ")
523        print_fmt = event.print_fmt
524        event.print_fmt = str.replace(event.print_fmt, "%ps", "%s")
525        if (is_void) :
526            event.print_fmt = str.replace(event.print_fmt, "(void *)REC->{}".format(filed_name), "functionStr.c_str()")
527        else :
528            event.print_fmt = str.replace(event.print_fmt, "REC->{}".format(filed_name), "functionStr.c_str()")
529        self.handle_field_name_functions(event, f)
530        f.write("    } else {\n")
531        event.print_fmt = print_fmt
532        event.print_fmt = str.replace(event.print_fmt, "%ps", "%p")
533        self.handle_field_name_functions(event, f)
534        f.write("    }\n")
535
536def main():
537    parser = argparse.ArgumentParser(
538        description='FTrace C++ code generator.')
539    parser.add_argument('-a', dest='allow_list', required=True, type=str,
540                        help='event allow list file path')
541    parser.add_argument('-e', dest='events_dir', required=True, type=str,
542                        help='event formats directory')
543    parser.add_argument('-p', dest='parser_out', required=False, type=str,
544                        help='parser code output directory')
545    parser.add_argument('-f', dest='formatter_out', required=False, type=str,
546                        help='formaater code output directory')
547
548    args = parser.parse_args(sys.argv[1:])
549    allow_list = args.allow_list
550    events_dir = args.events_dir
551    parser_out = args.parser_out
552    formatter_out = args.formatter_out
553
554    # check arguments
555    if not os.path.isfile(allow_list):
556        parser.print_usage()
557        exit(1)
558    if not os.path.isdir(events_dir):
559        parser.print_usage()
560        exit(2)
561
562    if parser_out:
563        if not os.path.isdir(parser_out):
564            parser.print_usage()
565            exit(3)
566        parser_gen = EventParserCodeGenerator(events_dir, allow_list)
567        parser_gen.generate(os.path.join(parser_out))
568        sh_path = "../../../format-code.sh "
569        if (os.getcwd().find("device_kernel_version") != -1):
570            sh_path = "../../{}".format(sh_path)
571        subprocess.run("{}{}".format(sh_path, parser_out), shell=True)
572        subprocess.run("chmod 775 {}*.cpp".format(parser_out), shell=True)
573
574    if formatter_out:
575        if not os.path.isdir(formatter_out):
576            parser.print_usage()
577            exit(4)
578        fmtter_gen = EventFormatterCodeGenerator(events_dir, allow_list)
579        fmtter_gen.generate(formatter_out)
580        sh_path = "../../../format-code.sh "
581        if (os.getcwd().find("device_kernel_version") != -1):
582            sh_path = "../../{}".format(sh_path)
583        subprocess.run("{}{}".format(sh_path, formatter_out), shell=True)
584        subprocess.run("chmod 775 {}*.cpp".format(formatter_out), shell=True)
585
586
587if __name__ == '__main__':
588    main()
589