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