Skip to content

Each naked function creates separate PE code section #147789

@MauriceKayser

Description

@MauriceKayser

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

  1. 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  ") }
  2. 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
  3. 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")]
  4. 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 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
  5. 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 ");
  6. 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 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 "" 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesA-nakedArea: `#[naked]`, prologue and epilogue-free, functions, https://git.io/vAzzSC-bugCategory: This is a bug.O-windowsOperating system: WindowsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions