From 782b482f425914de17908ec9a18b3becf8280e8d Mon Sep 17 00:00:00 2001 From: tinaun Date: Fri, 24 Apr 2020 01:15:50 -0400 Subject: [PATCH 01/10] ordinals are 16 bits --- src/librustc_middle/middle/codegen_fn_attrs.rs | 2 +- src/librustc_typeck/collect.rs | 8 ++++---- .../ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_middle/middle/codegen_fn_attrs.rs b/src/librustc_middle/middle/codegen_fn_attrs.rs index c480944069efb..794cec35a37c4 100644 --- a/src/librustc_middle/middle/codegen_fn_attrs.rs +++ b/src/librustc_middle/middle/codegen_fn_attrs.rs @@ -21,7 +21,7 @@ pub struct CodegenFnAttrs { /// imported function has in the dynamic library. Note that this must not /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. - pub link_ordinal: Option, + pub link_ordinal: Option, /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 355b4fc413f42..4ccb95d7668d5 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2660,7 +2660,7 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { false } -fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { +fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { use rustc_ast::ast::{Lit, LitIntType, LitKind}; let meta_item_list = attr.meta_item_list(); let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); @@ -2669,13 +2669,13 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { _ => None, }; if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { - if *ordinal <= usize::MAX as u128 { - Some(*ordinal as usize) + if *ordinal <= u16::MAX as u128 { + Some(*ordinal as u16) } else { let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); tcx.sess .struct_span_err(attr.span, &msg) - .note("the value may not exceed `usize::MAX`") + .note("the value may not exceed `u16::MAX`") .emit(); None } diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr index 35f9b53fdf720..85da1d243dffb 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr @@ -13,7 +13,7 @@ error: ordinal value in `link_ordinal` is too large: `18446744073709551616` LL | #[link_ordinal(18446744073709551616)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the value may not exceed `usize::MAX` + = note: the value may not exceed `u16::MAX` error: aborting due to previous error; 1 warning emitted From 1c7848859a56f5aa8cae644bcc2044d055ef1075 Mon Sep 17 00:00:00 2001 From: tinaun Date: Fri, 24 Apr 2020 01:22:02 -0400 Subject: [PATCH 02/10] add backend trait method --- src/librustc_codegen_llvm/lib.rs | 8 ++++++++ src/librustc_codegen_ssa/traits/backend.rs | 20 ++++++++++++++++++++ src/librustc_codegen_ssa/traits/mod.rs | 1 + 3 files changed, 29 insertions(+) diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 55ee660d9f700..a4a3cc8dfa2f8 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -90,6 +90,14 @@ impl ExtraBackendMethods for LlvmCodegenBackend { ) { base::write_compressed_metadata(tcx, metadata, llvm_module) } + fn write_idata_sections<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + raw_dylibs: &[RawDylibImports], + module: &mut ModuleLlvm, + ){ + base::write_idata_sections(tcx, raw_dylibs, module) + } fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 6cbb47efa99f2..92f1ad7facdaa 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -89,6 +89,20 @@ pub trait CodegenBackend { ) -> Result<(), ErrorReported>; } +//TODO: Put this somewhere else? +#[derive(Debug)] +pub enum RawDylibImportName { + Name(Symbol), + Ordinal(u16), +} + +#[derive(Debug)] +pub struct RawDylibImports { + pub name: Symbol, + pub items: Vec +} + + pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; fn write_compressed_metadata<'tcx>( @@ -97,6 +111,12 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se metadata: &EncodedMetadata, llvm_module: &mut Self::Module, ); + fn write_idata_sections<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + raw_dylib_imports: &[RawDylibImports], + mods: &mut Self::Module, + ); fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 6b782731d535c..03c1beb28c157 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -30,6 +30,7 @@ mod write; pub use self::abi::AbiBuilderMethods; pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef}; pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; +pub use self::backend::{RawDylibImports, RawDylibImportName}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; From 81cc064634c799313be1b3b8c24adee5ccb662d5 Mon Sep 17 00:00:00 2001 From: tinaun Date: Fri, 24 Apr 2020 01:22:39 -0400 Subject: [PATCH 03/10] search for raw_dylibs --- src/librustc_codegen_ssa/base.rs | 63 ++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 5b14258bd25be..3febb7b3edb43 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -598,6 +598,69 @@ pub fn codegen_crate( ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module); } + // codegen idata sections for raw-dylib linking + let mut raw_dylib_imports = vec![]; + let native_libs = tcx.native_libraries(LOCAL_CRATE); + + + for lib in native_libs.iter() { + match lib.kind { + cstore::NativeLibraryKind::NativeRawDylib => { + if let (Some(dll_name), Some(def_id)) = (lib.name, lib.foreign_module) { + let foreign_modules = tcx.foreign_modules(LOCAL_CRATE); + for f_mod in foreign_modules { + if f_mod.def_id == def_id { + let items = f_mod.foreign_items.iter().map(|&def_id| { + let fn_attrs = tcx.codegen_fn_attrs(def_id); + if fn_attrs.link_name.is_some() { + RawDylibImportName::Name(fn_attrs.link_name.unwrap()) + } else if fn_attrs.link_ordinal.is_some() { + RawDylibImportName::Ordinal(fn_attrs.link_ordinal.unwrap()) + } else { + let name = tcx.item_name(def_id); + RawDylibImportName::Name(name) + } + }).collect(); + + raw_dylib_imports.push(RawDylibImports { + name: dll_name, + items, + }); + } + } + } else { + bug!( + "not enough information to link raw dylib!", + ); + } + }, + _ => {}, + } + } + + if !raw_dylib_imports.is_empty() { + let idata_cgu_name = + cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("idata")).to_string(); + let mut idata_module = backend.new_metadata(tcx, &idata_cgu_name); + + tcx.sess.time("write_idata_sections", || { + backend.write_idata_sections( + tcx, + &raw_dylib_imports, + &mut idata_module, + ); + }); + + let idata_module = ModuleCodegen { + name: idata_cgu_name, + module_llvm: idata_module, + kind: ModuleKind::Regular, + }; + ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, idata_module); + } + + + // We sort the codegen units by size. This way we can schedule work for LLVM // a bit more efficiently. let codegen_units = { From 89df677178d6c584a9b0874fa250c02bb766e7d2 Mon Sep 17 00:00:00 2001 From: tinaun Date: Fri, 24 Apr 2020 01:23:12 -0400 Subject: [PATCH 04/10] initial codegen --- src/librustc_codegen_llvm/base.rs | 13 +++++++++++++ src/librustc_codegen_ssa/back/link.rs | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 3e17a51528e3e..1a2c4b11733e8 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -36,6 +36,7 @@ use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; +use log::debug; use std::ffi::CString; use std::time::Instant; @@ -75,6 +76,18 @@ pub fn write_compressed_metadata<'tcx>( } } +pub fn write_idata_sections<'tcx>( + _tcx: TyCtxt<'tcx>, + raw_dylibs: &[RawDylibImports], + _llvm_module: &mut ModuleLlvm, +){ + for raw_dylib in raw_dylibs { + debug!("linking raw dylib - {:?}", raw_dylib); + //TODO: emit. + } + +} + pub struct ValueIter<'ll> { cur: Option<&'ll Value>, step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 9a7c4907754b0..2eb62ee4edc96 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1703,8 +1703,7 @@ fn add_local_native_libraries( NativeLibKind::StaticNoBundle => cmd.link_staticlib(name), NativeLibKind::StaticBundle => cmd.link_whole_staticlib(name, &search_path), NativeLibKind::RawDylib => { - // FIXME(#58713): Proper handling for raw dylibs. - bug!("raw_dylib feature not yet implemented"); + // we shouldn't need to do anything here, code has been generated. } } } From ead60692a57b0ef4f60c12d3c085b5dbf13f4437 Mon Sep 17 00:00:00 2001 From: tinaun Date: Fri, 24 Apr 2020 03:29:22 -0400 Subject: [PATCH 05/10] string constants --- src/librustc_codegen_llvm/base.rs | 54 +++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 1a2c4b11733e8..7a5df1400b4b8 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -79,11 +79,61 @@ pub fn write_compressed_metadata<'tcx>( pub fn write_idata_sections<'tcx>( _tcx: TyCtxt<'tcx>, raw_dylibs: &[RawDylibImports], - _llvm_module: &mut ModuleLlvm, + llvm_module: &mut ModuleLlvm, ){ + let (idata_llctx, idata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); + + + let idata_7 = SmallCStr::new(".idata$7"); + let idata_6 = SmallCStr::new(".idata$6"); + for raw_dylib in raw_dylibs { debug!("linking raw dylib - {:?}", raw_dylib); - //TODO: emit. + + let name = CString::new(&*raw_dylib.name.as_str()).unwrap(); + let llname = common::bytes_in_context(idata_llctx, name.as_bytes()); + + let buf = CString::new("dll_name").unwrap(); + unsafe { + let llglobal = llvm::LLVMAddGlobal(idata_llmod, common::val_ty(llname), buf.as_ptr()); + + llvm::LLVMSetInitializer(llglobal, llname); + llvm::LLVMSetGlobalConstant(&llglobal, 1); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::LLVMSetSection(llglobal, idata_7.as_ptr()); + + for item in &raw_dylib.items { + match item { + RawDylibImportName::Name(s) => { + let mut buf = vec![0, 0]; + buf.extend(s.as_str().as_bytes()); + + if buf.len() % 2 == 1 { + buf.push(0); + } + + let llname = common::bytes_in_context(idata_llctx, &buf); + + let global_name = format!("import.{}.fn.{}", raw_dylib.name, s); + let global_name = CString::new(global_name.as_str()).unwrap(); + + let llglobal = llvm::LLVMAddGlobal( + idata_llmod, + common::val_ty(llname), + global_name.as_ptr() + ); + + llvm::LLVMSetInitializer(llglobal, llname); + llvm::LLVMSetGlobalConstant(&llglobal, 1); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::LLVMSetSection(llglobal, idata_6.as_ptr()); + }, + _ => {}, + } + } + } + + } } From ee39aeeeec0974b15d543c46921ddecd869f1869 Mon Sep 17 00:00:00 2001 From: tinaun Date: Sat, 25 Apr 2020 12:53:13 -0400 Subject: [PATCH 06/10] fix tidy + address comments --- src/librustc_codegen_llvm/base.rs | 29 +++++++-------- src/librustc_codegen_llvm/lib.rs | 2 +- src/librustc_codegen_ssa/base.rs | 43 ++++++++-------------- src/librustc_codegen_ssa/traits/backend.rs | 5 +-- src/librustc_codegen_ssa/traits/mod.rs | 2 +- 5 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 7a5df1400b4b8..de32fc8b4c187 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -23,6 +23,7 @@ use crate::llvm; use crate::metadata; use crate::value::Value; +use log::debug; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; @@ -36,7 +37,6 @@ use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; -use log::debug; use std::ffi::CString; use std::time::Instant; @@ -80,23 +80,23 @@ pub fn write_idata_sections<'tcx>( _tcx: TyCtxt<'tcx>, raw_dylibs: &[RawDylibImports], llvm_module: &mut ModuleLlvm, -){ +) { let (idata_llctx, idata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - let idata_7 = SmallCStr::new(".idata$7"); let idata_6 = SmallCStr::new(".idata$6"); for raw_dylib in raw_dylibs { - debug!("linking raw dylib - {:?}", raw_dylib); + debug!("creating raw dylib idata secions - {:?}", raw_dylib); let name = CString::new(&*raw_dylib.name.as_str()).unwrap(); let llname = common::bytes_in_context(idata_llctx, name.as_bytes()); - let buf = CString::new("dll_name").unwrap(); + let buf = format!("import.{}.dll_name", raw_dylib.name); + let buf = CString::new(buf).unwrap(); unsafe { let llglobal = llvm::LLVMAddGlobal(idata_llmod, common::val_ty(llname), buf.as_ptr()); - + llvm::LLVMSetInitializer(llglobal, llname); llvm::LLVMSetGlobalConstant(&llglobal, 1); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); @@ -115,27 +115,24 @@ pub fn write_idata_sections<'tcx>( let llname = common::bytes_in_context(idata_llctx, &buf); let global_name = format!("import.{}.fn.{}", raw_dylib.name, s); - let global_name = CString::new(global_name.as_str()).unwrap(); + let global_name = CString::new(global_name).unwrap(); let llglobal = llvm::LLVMAddGlobal( - idata_llmod, - common::val_ty(llname), - global_name.as_ptr() + idata_llmod, + common::val_ty(llname), + global_name.as_ptr(), ); - + llvm::LLVMSetInitializer(llglobal, llname); llvm::LLVMSetGlobalConstant(&llglobal, 1); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetSection(llglobal, idata_6.as_ptr()); - }, - _ => {}, + } + _ => {} } } } - - } - } pub struct ValueIter<'ll> { diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index a4a3cc8dfa2f8..66cc2cd56ff43 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -95,7 +95,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend { tcx: TyCtxt<'tcx>, raw_dylibs: &[RawDylibImports], module: &mut ModuleLlvm, - ){ + ) { base::write_idata_sections(tcx, raw_dylibs, module) } fn codegen_allocator<'tcx>( diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 3febb7b3edb43..5a5c2705af7ee 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -602,15 +602,16 @@ pub fn codegen_crate( let mut raw_dylib_imports = vec![]; let native_libs = tcx.native_libraries(LOCAL_CRATE); - for lib in native_libs.iter() { - match lib.kind { - cstore::NativeLibraryKind::NativeRawDylib => { - if let (Some(dll_name), Some(def_id)) = (lib.name, lib.foreign_module) { - let foreign_modules = tcx.foreign_modules(LOCAL_CRATE); - for f_mod in foreign_modules { - if f_mod.def_id == def_id { - let items = f_mod.foreign_items.iter().map(|&def_id| { + if lib.kind == cstore::NativeLibraryKind::NativeRawDylib { + if let (Some(dll_name), Some(def_id)) = (lib.name, lib.foreign_module) { + let foreign_modules = tcx.foreign_modules(LOCAL_CRATE); + for f_mod in foreign_modules { + if f_mod.def_id == def_id { + let items = f_mod + .foreign_items + .iter() + .map(|&def_id| { let fn_attrs = tcx.codegen_fn_attrs(def_id); if fn_attrs.link_name.is_some() { RawDylibImportName::Name(fn_attrs.link_name.unwrap()) @@ -620,21 +621,15 @@ pub fn codegen_crate( let name = tcx.item_name(def_id); RawDylibImportName::Name(name) } - }).collect(); + }) + .collect(); - raw_dylib_imports.push(RawDylibImports { - name: dll_name, - items, - }); - } + raw_dylib_imports.push(RawDylibImports { name: dll_name, items }); } - } else { - bug!( - "not enough information to link raw dylib!", - ); } - }, - _ => {}, + } else { + bug!("not enough information to link raw dylib!",); + } } } @@ -644,11 +639,7 @@ pub fn codegen_crate( let mut idata_module = backend.new_metadata(tcx, &idata_cgu_name); tcx.sess.time("write_idata_sections", || { - backend.write_idata_sections( - tcx, - &raw_dylib_imports, - &mut idata_module, - ); + backend.write_idata_sections(tcx, &raw_dylib_imports, &mut idata_module); }); let idata_module = ModuleCodegen { @@ -659,8 +650,6 @@ pub fn codegen_crate( ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, idata_module); } - - // We sort the codegen units by size. This way we can schedule work for LLVM // a bit more efficiently. let codegen_units = { diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 92f1ad7facdaa..893d54abc41dd 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -89,7 +89,7 @@ pub trait CodegenBackend { ) -> Result<(), ErrorReported>; } -//TODO: Put this somewhere else? +//FIXME: Put this somewhere else? #[derive(Debug)] pub enum RawDylibImportName { Name(Symbol), @@ -99,10 +99,9 @@ pub enum RawDylibImportName { #[derive(Debug)] pub struct RawDylibImports { pub name: Symbol, - pub items: Vec + pub items: Vec, } - pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; fn write_compressed_metadata<'tcx>( diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 03c1beb28c157..3e32aeaca7871 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -30,7 +30,7 @@ mod write; pub use self::abi::AbiBuilderMethods; pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef}; pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; -pub use self::backend::{RawDylibImports, RawDylibImportName}; +pub use self::backend::{RawDylibImportName, RawDylibImports}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; From 7bba437bb0317654945fb39bb0d32627bb9731b7 Mon Sep 17 00:00:00 2001 From: tinaun Date: Sun, 26 Apr 2020 02:23:45 -0400 Subject: [PATCH 07/10] inital directory / addr tables layout --- src/librustc_codegen_llvm/base.rs | 173 +++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 37 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index de32fc8b4c187..38de739e254f7 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -76,15 +76,52 @@ pub fn write_compressed_metadata<'tcx>( } } +fn new_global<'ll>( + name: &[&str], + llmod: &'ll llvm::Module, + llvalue: &'ll llvm::Value, + linkage: llvm::Linkage, + section: &str, +) -> &'ll llvm::Value { + let name = CString::new(name.join(".")).unwrap(); + let section = SmallCStr::new(section); + + unsafe { + let llglobal = llvm::LLVMAddGlobal(llmod, common::val_ty(llvalue), name.as_ptr()); + + llvm::LLVMSetInitializer(llglobal, llvalue); + llvm::LLVMRustSetLinkage(llglobal, linkage); + llvm::LLVMSetSection(llglobal, section.as_ptr()); + + llglobal + } +} + pub fn write_idata_sections<'tcx>( _tcx: TyCtxt<'tcx>, raw_dylibs: &[RawDylibImports], llvm_module: &mut ModuleLlvm, ) { let (idata_llctx, idata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); + let llint32 = unsafe { llvm::LLVMInt32TypeInContext(idata_llctx) }; + let llbyte_ptr = unsafe { llvm::LLVMPointerType(llvm::LLVMInt8TypeInContext(idata_llctx), 0) }; + + // import directory table types + let lldir_ty = unsafe { + let llint32 = llvm::LLVMInt32TypeInContext(idata_llctx); + let lldir_ty_name = SmallCStr::new(".win32.image_import_desc"); + let lldir_ty = llvm::LLVMStructCreateNamed(idata_llctx, lldir_ty_name.as_ptr()); + llvm::LLVMStructSetBody( + lldir_ty, + [llbyte_ptr, llint32, llint32, llbyte_ptr, llbyte_ptr].as_ptr(), + 5, + 0, + ); + + lldir_ty + }; - let idata_7 = SmallCStr::new(".idata$7"); - let idata_6 = SmallCStr::new(".idata$6"); + let mut dir_entries = vec![]; for raw_dylib in raw_dylibs { debug!("creating raw dylib idata secions - {:?}", raw_dylib); @@ -92,47 +129,109 @@ pub fn write_idata_sections<'tcx>( let name = CString::new(&*raw_dylib.name.as_str()).unwrap(); let llname = common::bytes_in_context(idata_llctx, name.as_bytes()); - let buf = format!("import.{}.dll_name", raw_dylib.name); - let buf = CString::new(buf).unwrap(); - unsafe { - let llglobal = llvm::LLVMAddGlobal(idata_llmod, common::val_ty(llname), buf.as_ptr()); - - llvm::LLVMSetInitializer(llglobal, llname); - llvm::LLVMSetGlobalConstant(&llglobal, 1); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::LLVMSetSection(llglobal, idata_7.as_ptr()); + let lldll_name = new_global( + &["import", &*raw_dylib.name.as_str(), "dll_name"], + idata_llmod, + llname, + llvm::Linkage::PrivateLinkage, + "idata$7", + ); - for item in &raw_dylib.items { - match item { - RawDylibImportName::Name(s) => { - let mut buf = vec![0, 0]; - buf.extend(s.as_str().as_bytes()); - - if buf.len() % 2 == 1 { - buf.push(0); + unsafe { + llvm::LLVMSetGlobalConstant(&lldll_name, 1); + + let mut lookup_table = raw_dylib + .items + .iter() + .map(|item| { + match item { + RawDylibImportName::Name(s) => { + let mut buf = vec![0, 0]; + buf.extend(s.as_str().as_bytes()); + + if buf.len() % 2 == 1 { + buf.push(0); + } + + let llname = common::bytes_in_context(idata_llctx, &buf); + + let llglobal = new_global( + &["import", &*raw_dylib.name.as_str(), "fn", &*s.as_str()], + idata_llmod, + llname, + llvm::Linkage::PrivateLinkage, + "idata$6", + ); + + llvm::LLVMSetGlobalConstant(&llglobal, 1); + llvm::LLVMConstPointerCast(llglobal, llbyte_ptr) } + RawDylibImportName::Ordinal(o) => { + //FIXME: support 32-bit targets + let o = *o as u64 | 0x8000_0000_0000_0000; + let llint64 = llvm::LLVMInt64TypeInContext(idata_llctx); + let llordinal = llvm::LLVMConstInt(llint64, o, 0); - let llname = common::bytes_in_context(idata_llctx, &buf); - - let global_name = format!("import.{}.fn.{}", raw_dylib.name, s); - let global_name = CString::new(global_name).unwrap(); - - let llglobal = llvm::LLVMAddGlobal( - idata_llmod, - common::val_ty(llname), - global_name.as_ptr(), - ); - - llvm::LLVMSetInitializer(llglobal, llname); - llvm::LLVMSetGlobalConstant(&llglobal, 1); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::LLVMSetSection(llglobal, idata_6.as_ptr()); + llvm::LLVMConstIntToPtr(llordinal, llbyte_ptr) + } } - _ => {} - } - } + }) + .collect::>(); + + lookup_table.push(llvm::LLVMConstNull(llbyte_ptr)); + let lltable = + llvm::LLVMConstArray(llbyte_ptr, lookup_table.as_ptr(), lookup_table.len() as u32); + + //import lookup table + let ll_lookup_table = new_global( + &["import", &*raw_dylib.name.as_str(), "desc"], + idata_llmod, + lltable, + llvm::Linkage::PrivateLinkage, + "idata$4", + ); + + //import address table - filled in at runtime + let ll_addr_table = new_global( + &["import", &*raw_dylib.name.as_str(), "ptr"], + idata_llmod, + lltable, + llvm::Linkage::PrivateLinkage, + "idata$3", + ); + + let llzero = llvm::LLVMConstInt(llint32, 0, 0); + let lldir_entry = llvm::LLVMConstStructInContext( + idata_llctx, + [ + llvm::LLVMConstPointerCast(ll_lookup_table, llbyte_ptr), + llzero, + llzero, + llvm::LLVMConstPointerCast(lldll_name, llbyte_ptr), + llvm::LLVMConstPointerCast(ll_addr_table, llbyte_ptr), + ] + .as_ptr(), + 5, + 0, + ); + + dir_entries.push(lldir_entry); } } + unsafe { + dir_entries.push(llvm::LLVMConstNull(lldir_ty)); + let lldir_table = + llvm::LLVMConstArray(lldir_ty, dir_entries.as_ptr(), dir_entries.len() as u32); + + let lldir_table = new_global( + &[".dllimport"], + idata_llmod, + lldir_table, + llvm::Linkage::AppendingLinkage, + "idata$2", + ); + llvm::LLVMSetGlobalConstant(&lldir_table, 1); + } } pub struct ValueIter<'ll> { From 7a9962fea9b74a97428fcf8c40d23480a81a937e Mon Sep 17 00:00:00 2001 From: tinaun Date: Mon, 11 May 2020 20:46:20 -0400 Subject: [PATCH 08/10] get 32bit rva instead of ptr sized addrs --- src/librustc_codegen_llvm/base.rs | 35 ++++++++++++++++++++++----- src/librustc_codegen_llvm/llvm/ffi.rs | 1 + 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 38de739e254f7..6e331b2e55731 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -97,6 +97,19 @@ fn new_global<'ll>( } } +unsafe fn get_rva<'ll>( + llctx: &'ll llvm::Context, + llptr: &'ll llvm::Value, + llbase: &'ll llvm::Value, +) -> &'ll llvm::Value { + let llrva_ty = llvm::LLVMInt32TypeInContext(llctx); + + let llbase_val = llvm::LLVMConstPtrToInt(llbase, llrva_ty); + let llptr_val = llvm::LLVMConstPtrToInt(llptr, llrva_ty); + + llvm::LLVMConstSub(llptr_val, llbase_val) +} + pub fn write_idata_sections<'tcx>( _tcx: TyCtxt<'tcx>, raw_dylibs: &[RawDylibImports], @@ -108,12 +121,11 @@ pub fn write_idata_sections<'tcx>( // import directory table types let lldir_ty = unsafe { - let llint32 = llvm::LLVMInt32TypeInContext(idata_llctx); let lldir_ty_name = SmallCStr::new(".win32.image_import_desc"); let lldir_ty = llvm::LLVMStructCreateNamed(idata_llctx, lldir_ty_name.as_ptr()); llvm::LLVMStructSetBody( lldir_ty, - [llbyte_ptr, llint32, llint32, llbyte_ptr, llbyte_ptr].as_ptr(), + [llint32, llint32, llint32, llint32, llint32].as_ptr(), 5, 0, ); @@ -121,6 +133,17 @@ pub fn write_idata_sections<'tcx>( lldir_ty }; + // image base constant for computing RVAs + let image_base = unsafe { + let llname = SmallCStr::new("__ImageBase"); + let llty = llvm::LLVMInt8TypeInContext(idata_llctx); + + let llglobal = llvm::LLVMAddGlobal(idata_llmod, llty, llname.as_ptr()); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::ExternalLinkage); + + llglobal + }; + let mut dir_entries = vec![]; for raw_dylib in raw_dylibs { @@ -204,11 +227,11 @@ pub fn write_idata_sections<'tcx>( let lldir_entry = llvm::LLVMConstStructInContext( idata_llctx, [ - llvm::LLVMConstPointerCast(ll_lookup_table, llbyte_ptr), + get_rva(idata_llctx, ll_lookup_table, image_base), llzero, llzero, - llvm::LLVMConstPointerCast(lldll_name, llbyte_ptr), - llvm::LLVMConstPointerCast(ll_addr_table, llbyte_ptr), + get_rva(idata_llctx, lldll_name, image_base), + get_rva(idata_llctx, ll_addr_table, image_base), ] .as_ptr(), 5, @@ -227,7 +250,7 @@ pub fn write_idata_sections<'tcx>( &[".dllimport"], idata_llmod, lldir_table, - llvm::Linkage::AppendingLinkage, + llvm::Linkage::ExternalLinkage, "idata$2", ); llvm::LLVMSetGlobalConstant(&lldir_table, 1); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 3fb7ff3cb8dfd..58c6df1d3e9b9 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -848,6 +848,7 @@ extern "C" { pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions + pub fn LLVMConstSub(LHS: &'a Value, RHS: &'a Value) -> &'a Value; pub fn LLVMConstInBoundsGEP( ConstantVal: &'a Value, ConstantIndices: *const &'a Value, From 1be946ccc3d6d35e7135d42325d40c41c9594fe3 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 12 May 2020 20:16:03 -0400 Subject: [PATCH 09/10] correct section names --- src/librustc_codegen_llvm/base.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 6e331b2e55731..f03eab857fe6b 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -157,7 +157,7 @@ pub fn write_idata_sections<'tcx>( idata_llmod, llname, llvm::Linkage::PrivateLinkage, - "idata$7", + ".idata$7", ); unsafe { @@ -183,7 +183,7 @@ pub fn write_idata_sections<'tcx>( idata_llmod, llname, llvm::Linkage::PrivateLinkage, - "idata$6", + ".idata$6", ); llvm::LLVMSetGlobalConstant(&llglobal, 1); @@ -211,7 +211,7 @@ pub fn write_idata_sections<'tcx>( idata_llmod, lltable, llvm::Linkage::PrivateLinkage, - "idata$4", + ".idata$4", ); //import address table - filled in at runtime @@ -220,7 +220,7 @@ pub fn write_idata_sections<'tcx>( idata_llmod, lltable, llvm::Linkage::PrivateLinkage, - "idata$3", + ".idata$3", ); let llzero = llvm::LLVMConstInt(llint32, 0, 0); @@ -251,7 +251,7 @@ pub fn write_idata_sections<'tcx>( idata_llmod, lldir_table, llvm::Linkage::ExternalLinkage, - "idata$2", + ".idata$2", ); llvm::LLVMSetGlobalConstant(&lldir_table, 1); } From f8426eabbad0fc41f8c90efadf8d982e982374f0 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 26 May 2020 11:46:06 -0400 Subject: [PATCH 10/10] librarykind -> libkind --- src/librustc_codegen_ssa/base.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 5a5c2705af7ee..d0837b3e3e612 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -603,7 +603,7 @@ pub fn codegen_crate( let native_libs = tcx.native_libraries(LOCAL_CRATE); for lib in native_libs.iter() { - if lib.kind == cstore::NativeLibraryKind::NativeRawDylib { + if lib.kind == NativeLibKind::RawDylib { if let (Some(dll_name), Some(def_id)) = (lib.name, lib.foreign_module) { let foreign_modules = tcx.foreign_modules(LOCAL_CRATE); for f_mod in foreign_modules { @@ -948,7 +948,10 @@ pub fn provide_both(providers: &mut Providers<'_>) { .native_libraries(krate) .iter() .filter(|lib| { - if !matches!(lib.kind, NativeLibKind::Dylib | NativeLibKind::Unspecified) { + if !matches!( + lib.kind, + NativeLibKind::Dylib | NativeLibKind::RawDylib | NativeLibKind::Unspecified + ) { return false; } let cfg = match lib.cfg {