-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
Description
(At least) on Windows, naked functions are not created in the .text section, but in a .text.First2LettersOfFunctionNameBecause8IsTheSectionNameLengthLimit section, e.g. .text.Ex for a naked function called Example.
Depending on the amount of naked functions, this can bloat the resulting binary file and memory usage.
Maybe the intention was to use the $ sign as a separator instead of a ., which is a magic separation character, as mentioned in #128177, for example .text$FunctionName instead of .text.FunctionName?
Example
-
Create an
example.rs:Rust code
#![no_main] #![no_std] #[cfg(not(test))] #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } // This ends up in the `.text.Wi` section #[unsafe(naked)] #[unsafe(no_mangle)] extern "system" fn WinMainCRTStartup() -> i32 { core::arch::naked_asm!("jmp {}", sym Hello) } // This ends up in the `.text.He` section #[unsafe(naked)] #[unsafe(no_mangle)] extern "system" fn Hello() -> i32 { core::arch::naked_asm!("jmp {}", sym Example) } // This ends up in the `.text.Ex` section #[unsafe(naked)] #[unsafe(no_mangle)] extern "system" fn Example() -> i32 { core::arch::naked_asm!(" xor eax, eax ret ") }
-
Compile via:
rustc example.rs --emit asm,link,llvm-ir -C panic=abort -C "link-args=/Debug:None /EmitToolVersionInfo:No /NoCoffGrpInfo /NoVcFeature /SubSystem:Windows":dumpbin.exe /headers example.exe
SECTION HEADER #1 .text.Wi name 5 virtual size 1000 virtual address (0000000140001000 to 0000000140001004) 200 size of raw data 200 file pointer to raw data (00000200 to 000003FF) 60000020 flags Code Execute Read SECTION HEADER #2 .text.He name 5 virtual size 2000 virtual address (0000000140002000 to 0000000140002004) 200 size of raw data 400 file pointer to raw data (00000400 to 000005FF) 60000020 flags Code Execute Read SECTION HEADER #3 .text.Ex name 3 virtual size 3000 virtual address (0000000140003000 to 0000000140003002) 200 size of raw data 600 file pointer to raw data (00000600 to 000007FF) 60000020 flags Code Execute Read
LLVM module
; ModuleID = 'example.90d8d4ea2542351-cgu.0' source_filename = "example.90d8d4ea2542351-cgu.0" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" module asm ".intel_syntax" module asm ".pushsection .text.WinMainCRTStartup,\22xr\22" module asm ".balign 4" module asm ".globl WinMainCRTStartup" module asm ".def WinMainCRTStartup" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "WinMainCRTStartup:" module asm "jmp Hello" module asm ".popsection" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm ".pushsection .text.Hello,\22xr\22" module asm ".balign 4" module asm ".globl Hello" module asm ".def Hello" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "Hello:" module asm "jmp Example" module asm ".popsection" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm ".pushsection .text.Example,\22xr\22" module asm ".balign 4" module asm ".globl Example" module asm ".def Example" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "Example:" module asm "" module asm " xor eax, eax" module asm " ret" module asm " " module asm ".popsection" module asm "" module asm ".att_syntax" @llvm.compiler.used = appending global [2 x ptr] [ptr @Hello, ptr @Example], section "llvm.metadata" ; __rustc::rust_begin_unwind ; Function Attrs: noreturn nounwind uwtable define hidden void @_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind(ptr align 8 %_1) unnamed_addr #0 { start: br label %bb1 bb1: ; preds = %bb1, %start br label %bb1 } ; Function Attrs: noinline nounwind uwtable declare i32 @WinMainCRTStartup() unnamed_addr #1 ; Function Attrs: noinline nounwind uwtable declare i32 @Hello() unnamed_addr #1 ; Function Attrs: noinline nounwind uwtable declare i32 @Example() unnamed_addr #1 attributes #0 = { noreturn nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" } attributes #1 = { noinline nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 8, !"PIC Level", i32 2} !1 = !{i32 7, !"PIE Level", i32 2} !2 = !{!"rustc version 1.88.0 (6b00bc388 2025-06-23)"}
Assembly module
.def @feat.00; .scl 3; .type 0; .endef .globl @feat.00 .set @feat.00, 0 .file "example.90d8d4ea2542351-cgu.0" .section .text.WinMainCRTStartup,"xr" .p2align 2 .globl WinMainCRTStartup .def WinMainCRTStartup; .scl 2; .type 32; .endef WinMainCRTStartup: jmp Hello .text .section .text.Hello,"xr" .p2align 2 .globl Hello .def Hello; .scl 2; .type 32; .endef Hello: jmp Example .text .section .text.Example,"xr" .p2align 2 .globl Example .def Example; .scl 2; .type 32; .endef Example: xorl %eax, %eax retq .text .def _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind; .scl 2; .type 32; .endef .section .text,"xr",one_only,_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .globl _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .p2align 4 _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind: jmp .LBB0_1 .LBB0_1: jmp .LBB0_1
-
Explicitly set the section name with a
$separator to fix the issue:Rust code
- // This ends up in the `.text.Wi` section + #[unsafe(link_section = ".text$WinMainCRTStartup")] - // This ends up in the `.text.He` section + #[unsafe(link_section = ".text$Hello")] - // This ends up in the `.text.Ex` section + #[unsafe(link_section = ".text$Example")]
-
Compile again:
dumpbin.exe /headers example.exe
SECTION HEADER #1 .text name 11 virtual size 1000 virtual address (0000000140001000 to 0000000140001010) 200 size of raw data 200 file pointer to raw data (00000200 to 000003FF) 60000020 flags Code Execute ReadLLVM module
; ModuleID = 'example.90d8d4ea2542351-cgu.0' source_filename = "example.90d8d4ea2542351-cgu.0" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" module asm ".intel_syntax" module asm ".pushsection .text$WinMainCRTStartup,\22xr\22" module asm ".balign 4" module asm ".globl WinMainCRTStartup" module asm ".def WinMainCRTStartup" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "WinMainCRTStartup:" module asm "jmp Hello" module asm ".popsection" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm ".pushsection .text$Hello,\22xr\22" module asm ".balign 4" module asm ".globl Hello" module asm ".def Hello" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "Hello:" module asm "jmp Example" module asm ".popsection" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm ".pushsection .text$Example,\22xr\22" module asm ".balign 4" module asm ".globl Example" module asm ".def Example" module asm ".scl 2" module asm ".type 32" module asm ".endef" module asm "Example:" module asm "" module asm " xor eax, eax" module asm " ret" module asm " " module asm ".popsection" module asm "" module asm ".att_syntax" @llvm.compiler.used = appending global [2 x ptr] [ptr @Hello, ptr @Example], section "llvm.metadata" ; __rustc::rust_begin_unwind ; Function Attrs: noreturn nounwind uwtable define hidden void @_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind(ptr align 8 %_1) unnamed_addr #0 { start: br label %bb1 bb1: ; preds = %bb1, %start br label %bb1 } ; Function Attrs: noinline nounwind uwtable declare i32 @WinMainCRTStartup() unnamed_addr #1 ; Function Attrs: noinline nounwind uwtable declare i32 @Hello() unnamed_addr #1 ; Function Attrs: noinline nounwind uwtable declare i32 @Example() unnamed_addr #1 attributes #0 = { noreturn nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" } attributes #1 = { noinline nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 8, !"PIC Level", i32 2} !1 = !{i32 7, !"PIE Level", i32 2} !2 = !{!"rustc version 1.88.0 (6b00bc388 2025-06-23)"}
Assembly module
.def @feat.00; .scl 3; .type 0; .endef .globl @feat.00 .set @feat.00, 0 .file "example.90d8d4ea2542351-cgu.0" .section .text$WinMainCRTStartup,"xr" .p2align 2 .globl WinMainCRTStartup .def WinMainCRTStartup; .scl 2; .type 32; .endef WinMainCRTStartup: jmp Hello .text .section .text$Hello,"xr" .p2align 2 .globl Hello .def Hello; .scl 2; .type 32; .endef Hello: jmp Example .text .section .text$Example,"xr" .p2align 2 .globl Example .def Example; .scl 2; .type 32; .endef Example: xorl %eax, %eax retq .text .def _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind; .scl 2; .type 32; .endef .section .text,"xr",one_only,_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .globl _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .p2align 4 _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind: jmp .LBB0_1 .LBB0_1: jmp .LBB0_1
-
In comparison to naked functions, this does not happen with
global_asm. Replace the 3 naked functions and their attributes with the following:Rust code
// These end up in the `.text` section core::arch::global_asm!(" .global WinMainCRTStartup WinMainCRTStartup: jmp Hello "); core::arch::global_asm!(" .global Hello Hello: jmp Example "); core::arch::global_asm!(" .global Example Example: xor eax, eax ret ");
-
Compile again:
dumpbin.exe /headers example.exe
SECTION HEADER #1 .text name 7 virtual size 1000 virtual address (0000000140001000 to 0000000140001006) 200 size of raw data 200 file pointer to raw data (00000200 to 000003FF) 60000020 flags Code Execute ReadLLVM module
; ModuleID = 'example.90d8d4ea2542351-cgu.0' source_filename = "example.90d8d4ea2542351-cgu.0" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" module asm ".intel_syntax" module asm "" module asm " .global WinMainCRTStartup" module asm " WinMainCRTStartup:" module asm " jmp Hello" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm "" module asm " .global Hello" module asm " Hello:" module asm " jmp Example" module asm "" module asm ".att_syntax" module asm ".intel_syntax" module asm "" module asm " .global Example" module asm " Example:" module asm " xor eax, eax" module asm " ret" module asm "" module asm ".att_syntax" ; __rustc::rust_begin_unwind ; Function Attrs: noreturn nounwind uwtable define hidden void @_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind(ptr align 8 %_1) unnamed_addr #0 { start: br label %bb1 bb1: ; preds = %bb1, %start br label %bb1 } attributes #0 = { noreturn nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 8, !"PIC Level", i32 2} !1 = !{i32 7, !"PIE Level", i32 2} !2 = !{!"rustc version 1.88.0 (6b00bc388 2025-06-23)"}
Assembly module
.def @feat.00; .scl 3; .type 0; .endef .globl @feat.00 .set @feat.00, 0 .file "example.90d8d4ea2542351-cgu.0" .globl WinMainCRTStartup WinMainCRTStartup: jmp Hello .globl Hello Hello: jmp Example .globl Example Example: xorl %eax, %eax retq .def _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind; .scl 2; .type 32; .endef .section .text,"xr",one_only,_RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .globl _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind .p2align 4 _RNvCs691rhTbG0Ee_7___rustc17rust_begin_unwind: jmp .LBB0_1 .LBB0_1: jmp .LBB0_1
Expected result
The first example code should only create one section, named .text, instead of .text.Wi, .text.He, and .text.Ex.