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