diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 235a8ed4b1..4ca51d8add 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -85,6 +85,7 @@ jobs: if: matrix.coins == 'universal' && matrix.type != 'debuglink' - run: nix-shell --run "poetry run make -C core build_firmware" - run: nix-shell --run "poetry run ./tools/print-rust-stack-sizes.py | sort -k1 -n | tail -n 50" + - run: nix-shell --run "poetry run ./tools/print-rust-type-sizes.sh core/build/firmware/rust-type-sizes.log" | awk '$1 >= 1000' | sort -k1 -n - run: nix-shell --run "poetry run make -C core sizecheck" if: matrix.coins == 'universal' && matrix.type != 'debuglink' - run: nix-shell --run "poetry run ./tools/check-bitcoin-only core/build/firmware/firmware.bin" @@ -99,6 +100,7 @@ jobs: core/build/prodtest/*.bin core/build/firmware/firmware.elf core/build/firmware/firmware-*.bin + core/build/firmware/rust-type-sizes.log retention-days: 7 core_emu: diff --git a/core/Makefile b/core/Makefile index baeb2d1a0f..dd231ec7d4 100644 --- a/core/Makefile +++ b/core/Makefile @@ -45,7 +45,6 @@ TREZOR_EMULATOR_DEBUGGABLE ?= 0 QUIET_MODE ?= 0 TREZOR_DISABLE_ANIMATION ?= $(if $(filter 0,$(PYOPT)),1,0) STORAGE_INSECURE_TESTING_MODE ?= 0 -RUST_PRINT_TYPES_SIZES ?= 0 UI_DEBUG_OVERLAY ?= 0 # If set, VCP writes will be blocking, in order to allow reliable debug data transmission over VCP. @@ -130,7 +129,6 @@ SCONS_VARS = \ PRODUCTION="$(PRODUCTION)" \ PYOPT="$(PYOPT)" \ QUIET_MODE="$(QUIET_MODE)" \ - RUST_PRINT_TYPES_SIZES="$(RUST_PRINT_TYPES_SIZES)" \ SCM_REVISION="$(SCM_REVISION)" \ STORAGE_INSECURE_TESTING_MODE="$(STORAGE_INSECURE_TESTING_MODE)" \ THP="$(THP)" \ diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 54c95fbcf5..b464ee26e0 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -192,12 +192,13 @@ if UI_DEBUG_OVERLAY: features.append('ui_debug_overlay') rust = tools.add_rust_lib( - env, - 'bootloader', - 'release', - features, - ALLPATHS, - str(Dir('.').abspath)) + env=env, + build='bootloader', + profile='release', + features=features, + all_paths=ALLPATHS, + build_dir=str(Dir('.').abspath), +) # diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index 3a727a3925..b8c66efbf2 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -232,12 +232,14 @@ else: profile = 'release' rust = tools.add_rust_lib( - env, - 'bootloader_emu', - profile, - features, - ALLPATHS, - str(Dir('.').abspath)) + env=env, + build='bootloader_emu', + profile=profile, + features=features, + all_paths=ALLPATHS, + build_dir=str(Dir('.').abspath), +) + env.Append(LINKFLAGS='-lm') env.Append(LINKFLAGS='-Wl,' + ('-dead_strip' if env['PLATFORM'] == 'darwin' else '--gc-sections')) diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 19f4ab8f2c..583143cae7 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -778,12 +778,13 @@ if UI_DEBUG_OVERLAY: features.append('ui_debug_overlay') rust = tools.add_rust_lib( - env, - 'firmware', - 'release', - features, - ALLPATHS, - str(Dir('.').abspath)) + env=env, + build='firmware', + profile='release', + features=features, + all_paths=ALLPATHS, + build_dir=str(Dir('.').abspath), +) env.Depends(rust, protobuf_blobs) diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index c5d789088b..a8d20bcc49 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -221,12 +221,13 @@ if UI_DEBUG_OVERLAY: rust = tools.add_rust_lib( - env, - 'prodtest', - 'release', - features, - ALLPATHS, - str(Dir('.').abspath)) + env=env, + build='prodtest', + profile='release', + features=features, + all_paths=ALLPATHS, + build_dir=str(Dir('.').abspath), +) if (vh := ARGUMENTS.get("VENDOR_HEADER", None)): diff --git a/core/SConscript.unix b/core/SConscript.unix index f7fa73d64a..17c5a1effc 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -844,12 +844,13 @@ if EVERYTHING: features.append('universal_fw') rust = tools.add_rust_lib( - env, - 'firmware', - profile, - features, - ALLPATHS, - str(Dir('.').abspath)) + env=env, + build='unix', + profile=profile, + features=features, + all_paths=ALLPATHS, + build_dir=str(Dir('.').abspath), +) env.Depends(rust, protobuf_blobs) diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py index 26b58ff6d3..7d4198c73e 100644 --- a/core/site_scons/tools.py +++ b/core/site_scons/tools.py @@ -128,9 +128,7 @@ def embed_raw_binary(obj_program, env, section, target_, file): ) -def add_rust_lib( - env, build, profile, features, all_paths, build_dir, print_types_sizes=False -): +def add_rust_lib(*, env, build, profile, features, all_paths, build_dir): RUST_LIB = "trezor_lib" RUST_TARGET = env.get("ENV")["RUST_TARGET"] @@ -156,22 +154,26 @@ def add_rust_lib( "-Z build-std=core", "-Z build-std-features=panic_immediate_abort", ] + build_cmd = f"cargo build {profile} " + " ".join(cargo_opts) - if print_types_sizes: + unstable_rustc_flags = [ # see https://nnethercote.github.io/perf-book/type-sizes.html#measuring-type-sizes for more details - env.Append(ENV={"RUSTFLAGS": "-Z print-type-sizes"}) + "print-type-sizes", + # Adds an ELF section with Rust functions' stack sizes. See the following links for more details: + # - https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/emit-stack-sizes.html + # - https://blog.japaric.io/stack-analysis/ + # - https://github.com/japaric/stack-sizes/ + "emit-stack-sizes", + ] - # Adds an ELF section with Rust functions' stack sizes. See the following links for more details: - # - https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/emit-stack-sizes.html - # - https://blog.japaric.io/stack-analysis/ - # - https://github.com/japaric/stack-sizes/ - env.Append(ENV={"RUSTFLAGS": "-Z emit-stack-sizes"}) + env.Append(ENV={"RUSTFLAGS": " ".join(f"-Z {f}" for f in unstable_rustc_flags)}) bindgen_macros = get_bindgen_defines(env.get("CPPDEFINES"), all_paths) return ( - f"export BINDGEN_MACROS={shlex.quote(bindgen_macros)}; export BUILD_DIR='{build_dir}'; cd embed/rust; cargo build {profile} " - + " ".join(cargo_opts) + f"export BINDGEN_MACROS={shlex.quote(bindgen_macros)}; " + f"export BUILD_DIR='{build_dir}'; " + f"cd embed/rust; {build_cmd} > {build_dir}/rust-type-sizes.log" ) rust = env.Command( diff --git a/tools/print-rust-type-sizes.sh b/tools/print-rust-type-sizes.sh new file mode 100755 index 0000000000..da0b093f92 --- /dev/null +++ b/tools/print-rust-type-sizes.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +# Convert `-Z print-type-sizes` output into tab-separated values +sed -nr '/print-type-size/s/.*type: (`.*?`): ([0-9]+) bytes.* ([0-9]+) bytes/\2\t\3\t\1/p' $1