@@ -954,6 +954,29 @@ pub(crate) unsafe fn codegen(
954954 ) )
955955}
956956
957+ fn create_section_with_flags_asm ( section_name : & str , section_flags : & str , data : & [ u8 ] ) -> Vec < u8 > {
958+ let mut asm = format ! ( ".section {},\" {}\" \n " , section_name, section_flags) . into_bytes ( ) ;
959+ asm. extend_from_slice ( b".ascii \" " ) ;
960+ asm. reserve ( data. len ( ) ) ;
961+ for & byte in data {
962+ if byte == b'\\' || byte == b'"' {
963+ asm. push ( b'\\' ) ;
964+ asm. push ( byte) ;
965+ } else if byte < 0x20 || byte >= 0x80 {
966+ // Avoid non UTF-8 inline assembly. Use octal escape sequence, because it is fixed
967+ // width, while hex escapes will consume following characters.
968+ asm. push ( b'\\' ) ;
969+ asm. push ( b'0' + ( ( byte >> 6 ) & 0x7 ) ) ;
970+ asm. push ( b'0' + ( ( byte >> 3 ) & 0x7 ) ) ;
971+ asm. push ( b'0' + ( ( byte >> 0 ) & 0x7 ) ) ;
972+ } else {
973+ asm. push ( byte) ;
974+ }
975+ }
976+ asm. extend_from_slice ( b"\" \n " ) ;
977+ asm
978+ }
979+
957980/// Embed the bitcode of an LLVM module in the LLVM module itself.
958981///
959982/// This is done primarily for iOS where it appears to be standard to compile C
@@ -979,34 +1002,6 @@ unsafe fn embed_bitcode(
9791002 cmdline : & str ,
9801003 bitcode : & [ u8 ] ,
9811004) {
982- let llconst = common:: bytes_in_context ( llcx, bitcode) ;
983- let llglobal = llvm:: LLVMAddGlobal (
984- llmod,
985- common:: val_ty ( llconst) ,
986- "rustc.embedded.module\0 " . as_ptr ( ) . cast ( ) ,
987- ) ;
988- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
989-
990- let is_apple = cgcx. opts . target_triple . triple ( ) . contains ( "-ios" )
991- || cgcx. opts . target_triple . triple ( ) . contains ( "-darwin" )
992- || cgcx. opts . target_triple . triple ( ) . contains ( "-tvos" ) ;
993-
994- let section = if is_apple { "__LLVM,__bitcode\0 " } else { ".llvmbc\0 " } ;
995- llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
996- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
997- llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
998-
999- let llconst = common:: bytes_in_context ( llcx, cmdline. as_bytes ( ) ) ;
1000- let llglobal = llvm:: LLVMAddGlobal (
1001- llmod,
1002- common:: val_ty ( llconst) ,
1003- "rustc.embedded.cmdline\0 " . as_ptr ( ) . cast ( ) ,
1004- ) ;
1005- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1006- let section = if is_apple { "__LLVM,__cmdline\0 " } else { ".llvmcmd\0 " } ;
1007- llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1008- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
1009-
10101005 // We're adding custom sections to the output object file, but we definitely
10111006 // do not want these custom sections to make their way into the final linked
10121007 // executable. The purpose of these custom sections is for tooling
@@ -1028,31 +1023,54 @@ unsafe fn embed_bitcode(
10281023 // * COFF - if we don't do anything the linker will by default copy all
10291024 // these sections to the output artifact, not what we want! To subvert
10301025 // this we want to flag the sections we inserted here as
1031- // `IMAGE_SCN_LNK_REMOVE`. Unfortunately though LLVM has no native way to
1032- // do this. Thankfully though we can do this with some inline assembly,
1033- // which is easy enough to add via module-level global inline asm.
1026+ // `IMAGE_SCN_LNK_REMOVE`.
10341027 //
10351028 // * ELF - this is very similar to COFF above. One difference is that these
10361029 // sections are removed from the output linked artifact when
10371030 // `--gc-sections` is passed, which we pass by default. If that flag isn't
10381031 // passed though then these sections will show up in the final output.
10391032 // Additionally the flag that we need to set here is `SHF_EXCLUDE`.
1033+ //
1034+ // Unfortunately, LLVM provides no way to set custom section flags. For ELF
1035+ // and COFF we emit the sections using module level inline assembly for that
1036+ // reason (see issue #90326 for historical background).
1037+ let is_apple = cgcx. opts . target_triple . triple ( ) . contains ( "-ios" )
1038+ || cgcx. opts . target_triple . triple ( ) . contains ( "-darwin" )
1039+ || cgcx. opts . target_triple . triple ( ) . contains ( "-tvos" ) ;
10401040 if is_apple
10411041 || cgcx. opts . target_triple . triple ( ) . starts_with ( "wasm" )
10421042 || cgcx. opts . target_triple . triple ( ) . starts_with ( "asmjs" )
10431043 {
1044- // nothing to do here
1045- } else if cgcx. is_pe_coff {
1046- let asm = "
1047- .section .llvmbc,\" n\"
1048- .section .llvmcmd,\" n\"
1049- " ;
1050- llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
1044+ // We don't need custom section flags, create LLVM globals.
1045+ let llconst = common:: bytes_in_context ( llcx, bitcode) ;
1046+ let llglobal = llvm:: LLVMAddGlobal (
1047+ llmod,
1048+ common:: val_ty ( llconst) ,
1049+ "rustc.embedded.module\0 " . as_ptr ( ) . cast ( ) ,
1050+ ) ;
1051+ llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1052+
1053+ let section = if is_apple { "__LLVM,__bitcode\0 " } else { ".llvmbc\0 " } ;
1054+ llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1055+ llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
1056+ llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
1057+
1058+ let llconst = common:: bytes_in_context ( llcx, cmdline. as_bytes ( ) ) ;
1059+ let llglobal = llvm:: LLVMAddGlobal (
1060+ llmod,
1061+ common:: val_ty ( llconst) ,
1062+ "rustc.embedded.cmdline\0 " . as_ptr ( ) . cast ( ) ,
1063+ ) ;
1064+ llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1065+ let section = if is_apple { "__LLVM,__cmdline\0 " } else { ".llvmcmd\0 " } ;
1066+ llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) . cast ( ) ) ;
1067+ llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
10511068 } else {
1052- let asm = "
1053- .section .llvmbc,\" e\"
1054- .section .llvmcmd,\" e\"
1055- " ;
1069+ // We need custom section flags, so emit module-level inline assembly.
1070+ let section_flags = if cgcx. is_pe_coff { "n" } else { "e" } ;
1071+ let asm = create_section_with_flags_asm ( ".llvmbc" , section_flags, bitcode) ;
1072+ llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
1073+ let asm = create_section_with_flags_asm ( ".llvmcmd" , section_flags, cmdline. as_bytes ( ) ) ;
10561074 llvm:: LLVMRustAppendModuleInlineAsm ( llmod, asm. as_ptr ( ) . cast ( ) , asm. len ( ) ) ;
10571075 }
10581076}
0 commit comments