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