From a74e0132e80816fac80f4c2e55aa1a4a45bbc68c Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 10 Mar 2026 09:14:30 -0700 Subject: [PATCH] [build] Generate DW_AT_variables for bin_to_assembly data outputs. This lets bloaty attribute the data symbol to its source file, allowing the binary size visualization to nest it appropriately. TEST=runtime/tools/binary_size Change-Id: I683ad6729d2fe2e1730dd3be70c6cce15bdf0003 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/486524 Commit-Queue: Ryan Macnak Reviewed-by: Alexander Aprelev --- runtime/bin/BUILD.gn | 4 +- runtime/tools/bin_to_assembly.py | 71 +++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 6785943045d..c73d77d95b1 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -678,13 +678,13 @@ template("bin_to_assembly") { invoker.symbol, "--target_os", current_os, + "--target_arch", + current_cpu, ] if (defined(invoker.size_symbol)) { args += [ "--size_symbol_name", invoker.size_symbol, - "--target_arch", - current_cpu, ] } if (invoker.executable) { diff --git a/runtime/tools/bin_to_assembly.py b/runtime/tools/bin_to_assembly.py index 888d2d7b329..a3a6be46051 100755 --- a/runtime/tools/bin_to_assembly.py +++ b/runtime/tools/bin_to_assembly.py @@ -109,17 +109,17 @@ def Main(): if options.target_os not in ["mac", "ios", "watchos", "win", "win_gnu"]: output_file.write(".size {0}, .-{0}\n".format(options.symbol_name)) + is64bit = 0 + if options.target_arch: + if options.target_arch in ["arm64", "x64", "riscv64"]: + is64bit = 1 + if options.size_symbol_name: if not options.target_arch: sys.stderr.write("--target_arch not specified\n") parser.print_help() return -1 - is64bit = 0 - if options.target_arch: - if options.target_arch in ["arm64", "x64", "riscv64"]: - is64bit = 1 - if options.target_os in ["win"]: output_file.write("public %s\n" % options.size_symbol_name) output_file.write("%s label byte\n" % options.size_symbol_name) @@ -140,6 +140,67 @@ def Main(): else: output_file.write(".long %d\n" % size) + # For text symbols, with -g the assembler will generate the + # DW_TAG_subprogram/label (gcc/clang) for us. + if not options.executable and options.target_arch != None and options.target_os not in [ + "mac", "ios", "watchos", "win", "win_gnu" + ]: + output_file.write(".section .debug_abbrev,\"\"\n") + + output_file.write(".uleb128 1 // define abbreviation code\n") + output_file.write(".uleb128 0x11 // DW_TAG_compile_unit\n") + output_file.write(".byte 1 // DW_CHILDREN_yes\n") + output_file.write(".uleb128 0x3 // DW_AT_name\n") + output_file.write(".uleb128 0x8 // DW_FORM_string\n") + output_file.write(".uleb128 0x1b // DW_AT_comp_dir\n") + output_file.write(".uleb128 0x8 // DW_FORM_string\n") + output_file.write(".uleb128 0 // End of attributes\n") + output_file.write(".uleb128 0 // End of attributes\n") + + output_file.write(".uleb128 2 // define abbreviation code\n") + output_file.write(".uleb128 0x34 // DW_TAG_variable\n") + output_file.write(".byte 0 // DW_CHILDREN_no\n") + output_file.write(".uleb128 0x3 // DW_AT_name\n") + output_file.write(".uleb128 0x8 // DW_FORM_STRING\n") + output_file.write(".uleb128 0x3f // DW_AT_external\n") + output_file.write(".uleb128 0xc // DW_FORM_flag\n") + output_file.write(".uleb128 0x2 // DW_AT_location\n") + output_file.write(".uleb128 0x18 // DW_FORM_exprloc\n") + output_file.write(".uleb128 0 // End of attributes\n") + output_file.write(".uleb128 0 // End of attributes\n") + + output_file.write(".uleb128 0 // End abbreviations\n") + + output_file.write(".section .debug_info,\"\"\n") + output_file.write(".4byte .Ldebug_info_end - .Ldebug_info_start\n") + output_file.write(".Ldebug_info_start:\n") + output_file.write(".2byte 5 // DWARF version 5\n") + output_file.write(".byte 1 // DW_UT_compile\n") + output_file.write(".byte %s // address size\n" % + (8 if (is64bit == 1) else 4)) + output_file.write(".4byte .debug_abbrev // debug_abbr_offset\n") + + output_file.write(".uleb128 1 // use abbreviation code\n") + output_file.write(".string \"%s\" // DW_AT_name\n" % options.output) + output_file.write(".string \"\" // DW_AT_comp_dir\n") + + output_file.write(".uleb128 2 // use abbreviation code\n") + output_file.write(".string \"%s\" // DW_AT_name\n" % + options.symbol_name) + output_file.write(".byte 1 // DW_AT_external\n") + if (is64bit == 1): + output_file.write(".uleb128 9 // DW_AT_location\n") + output_file.write(".uleb128 0x3 // DW_OP_addr \n") + output_file.write(".8byte %s\n" % options.symbol_name) + else: + output_file.write(".uleb128 5 // DW_AT_location\n") + output_file.write(".uleb128 0x3 // DW_OP_addr \n") + output_file.write(".4byte %s\n" % options.symbol_name) + + output_file.write(".uleb128 0 // end children\n") + output_file.write(".uleb128 0 // end entries\n") + output_file.write(".Ldebug_info_end:\n") + if options.target_os in ["win"]: output_file.write("end\n")