@@ -950,6 +950,29 @@ pub(crate) unsafe fn codegen(
950950 ) )
951951}
952952
953+ fn create_section_with_flags_asm ( section_name : & str , section_flags : & str , data : & [ u8 ] ) -> Vec < u8 > {
954+ let mut asm = format ! ( ".section {},\" {}\" \n " , section_name, section_flags) . into_bytes ( ) ;
955+ asm. extend_from_slice ( b".ascii \" " ) ;
956+ asm. reserve ( data. len ( ) ) ;
957+ for & byte in data {
958+ if byte == b'\\' || byte == b'"' {
959+ asm. push ( b'\\' ) ;
960+ asm. push ( byte) ;
961+ } else if byte < 0x20 || byte >= 0x80 {
962+ // Avoid non UTF-8 inline assembly. Use octal escape sequence, because it is fixed
963+ // width, while hex escapes will consume following characters.
964+ asm. push ( b'\\' ) ;
965+ asm. push ( b'0' + ( ( byte >> 6 ) & 0x7 ) ) ;
966+ asm. push ( b'0' + ( ( byte >> 3 ) & 0x7 ) ) ;
967+ asm. push ( b'0' + ( ( byte >> 0 ) & 0x7 ) ) ;
968+ } else {
969+ asm. push ( byte) ;
970+ }
971+ }
972+ asm. extend_from_slice ( b"\" \n " ) ;
973+ asm
974+ }
975+
953976/// Embed the bitcode of an LLVM module in the LLVM module itself.
954977///
955978/// This is done primarily for iOS where it appears to be standard to compile C
@@ -975,34 +998,6 @@ unsafe fn embed_bitcode(
975998 cmdline : & str ,
976999 bitcode : & [ u8 ] ,
9771000) {
978- let llconst = common:: bytes_in_context ( llcx, bitcode) ;
979- let llglobal = llvm:: LLVMAddGlobal (
980- llmod,
981- common:: val_ty ( llconst) ,
982- "rustc.embedded.module\0 " . as_ptr ( ) . cast ( ) ,
983- ) ;
984- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
985-
986- let is_apple = cgcx. opts . target_triple . triple ( ) . contains ( "-ios" )
987- || cgcx. opts . target_triple . triple ( ) . contains ( "-darwin" )
988- || cgcx. opts . target_triple . triple ( ) . contains ( "-tvos" ) ;
989-
990- let section = if is_apple { "__LLVM,__bitcode\0 " } else { ".llvmbc\0 " } ;
991- llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
992- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
993- llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
994-
995- let llconst = common:: bytes_in_context ( llcx, cmdline. as_bytes ( ) ) ;
996- let llglobal = llvm:: LLVMAddGlobal (
997- llmod,
998- common:: val_ty ( llconst) ,
999- "rustc.embedded.cmdline\0 " . as_ptr ( ) . cast ( ) ,
1000- ) ;
1001- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1002- let section = if is_apple { "__LLVM,__cmdline\0 " } else { ".llvmcmd\0 " } ;
1003- llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1004- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
1005-
10061001 // We're adding custom sections to the output object file, but we definitely
10071002 // do not want these custom sections to make their way into the final linked
10081003 // executable. The purpose of these custom sections is for tooling
@@ -1024,31 +1019,54 @@ unsafe fn embed_bitcode(
10241019 // * COFF - if we don't do anything the linker will by default copy all
10251020 // these sections to the output artifact, not what we want! To subvert
10261021 // this we want to flag the sections we inserted here as
1027- // `IMAGE_SCN_LNK_REMOVE`. Unfortunately though LLVM has no native way to
1028- // do this. Thankfully though we can do this with some inline assembly,
1029- // which is easy enough to add via module-level global inline asm.
1022+ // `IMAGE_SCN_LNK_REMOVE`.
10301023 //
10311024 // * ELF - this is very similar to COFF above. One difference is that these
10321025 // sections are removed from the output linked artifact when
10331026 // `--gc-sections` is passed, which we pass by default. If that flag isn't
10341027 // passed though then these sections will show up in the final output.
10351028 // Additionally the flag that we need to set here is `SHF_EXCLUDE`.
1029+ //
1030+ // Unfortunately, LLVM provides no way to set custom section flags. For ELF
1031+ // and COFF we emit the sections using module level inline assembly for that
1032+ // reason (see issue #90326 for historical background).
1033+ let is_apple = cgcx. opts . target_triple . triple ( ) . contains ( "-ios" )
1034+ || cgcx. opts . target_triple . triple ( ) . contains ( "-darwin" )
1035+ || cgcx. opts . target_triple . triple ( ) . contains ( "-tvos" ) ;
10361036 if is_apple
10371037 || cgcx. opts . target_triple . triple ( ) . starts_with ( "wasm" )
10381038 || cgcx. opts . target_triple . triple ( ) . starts_with ( "asmjs" )
10391039 {
1040- // nothing to do here
1041- } else if cgcx. is_pe_coff {
1042- let asm = "
1043- .section .llvmbc,\" n\"
1044- .section .llvmcmd,\" n\"
1045- " ;
1046- llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
1040+ // We don't need custom section flags, create LLVM globals.
1041+ let llconst = common:: bytes_in_context ( llcx, bitcode) ;
1042+ let llglobal = llvm:: LLVMAddGlobal (
1043+ llmod,
1044+ common:: val_ty ( llconst) ,
1045+ "rustc.embedded.module\0 " . as_ptr ( ) . cast ( ) ,
1046+ ) ;
1047+ llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1048+
1049+ let section = if is_apple { "__LLVM,__bitcode\0 " } else { ".llvmbc\0 " } ;
1050+ llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1051+ llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
1052+ llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
1053+
1054+ let llconst = common:: bytes_in_context ( llcx, cmdline. as_bytes ( ) ) ;
1055+ let llglobal = llvm:: LLVMAddGlobal (
1056+ llmod,
1057+ common:: val_ty ( llconst) ,
1058+ "rustc.embedded.cmdline\0 " . as_ptr ( ) . cast ( ) ,
1059+ ) ;
1060+ llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1061+ let section = if is_apple { "__LLVM,__cmdline\0 " } else { ".llvmcmd\0 " } ;
1062+ llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1063+ llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
10471064 } else {
1048- let asm = "
1049- .section .llvmbc,\" e\"
1050- .section .llvmcmd,\" e\"
1051- " ;
1065+ // We need custom section flags, so emit module-level inline assembly.
1066+ let section_flags = if cgcx. is_pe_coff { "n" } else { "e" } ;
1067+ let asm = create_section_with_flags_asm ( ".llvmbc" , section_flags, bitcode) ;
1068+ llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
1069+ let asm = create_section_with_flags_asm ( ".llvmcmd" , section_flags, cmdline. as_bytes ( ) ) ;
10521070 llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
10531071 }
10541072}
0 commit comments