Test fixing raw-dylib
This commit is contained in:
parent
13a5097796
commit
b2fd8a0192
7 changed files with 95 additions and 55 deletions
|
@ -2,6 +2,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use rustc_codegen_ssa::back::archive::{
|
use rustc_codegen_ssa::back::archive::{
|
||||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||||
|
ImportLibraryItem,
|
||||||
};
|
};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||||
&self,
|
&self,
|
||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
_lib_name: &str,
|
_lib_name: &str,
|
||||||
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
_items: Vec<ImportLibraryItem>,
|
||||||
_output_path: &Path,
|
_output_path: &Path,
|
||||||
) {
|
) {
|
||||||
unimplemented!("creating dll imports is not yet supported");
|
unimplemented!("creating dll imports is not yet supported");
|
||||||
|
|
|
@ -49,6 +49,22 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
||||||
let llfn = if tcx.sess.target.arch == "x86"
|
let llfn = if tcx.sess.target.arch == "x86"
|
||||||
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
|
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
|
||||||
{
|
{
|
||||||
|
// When calling functions in generated import libraries, MSVC needs
|
||||||
|
// the fully decorated name (as would have been in the declaring
|
||||||
|
// object file), but MinGW wants the name as exported (as would be
|
||||||
|
// in the def file) which may be missing decorations.
|
||||||
|
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&tcx.sess.target);
|
||||||
|
let llfn = cx.declare_fn(
|
||||||
|
&common::i686_decorated_name(
|
||||||
|
dllimport,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
true,
|
||||||
|
!mingw_gnu_toolchain,
|
||||||
|
),
|
||||||
|
fn_abi,
|
||||||
|
Some(instance),
|
||||||
|
);
|
||||||
|
|
||||||
// Fix for https://github.com/rust-lang/rust/issues/104453
|
// Fix for https://github.com/rust-lang/rust/issues/104453
|
||||||
// On x86 Windows, LLVM uses 'L' as the prefix for any private
|
// On x86 Windows, LLVM uses 'L' as the prefix for any private
|
||||||
// global symbols, so when we create an undecorated function symbol
|
// global symbols, so when we create an undecorated function symbol
|
||||||
|
@ -60,15 +76,6 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
||||||
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
||||||
// existing logic below to set the Storage Class, but it has an
|
// existing logic below to set the Storage Class, but it has an
|
||||||
// exemption for MinGW for backwards compatibility.
|
// exemption for MinGW for backwards compatibility.
|
||||||
let llfn = cx.declare_fn(
|
|
||||||
&common::i686_decorated_name(
|
|
||||||
dllimport,
|
|
||||||
common::is_mingw_gnu_toolchain(&tcx.sess.target),
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
fn_abi,
|
|
||||||
Some(instance),
|
|
||||||
);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,16 +196,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||||
g2
|
g2
|
||||||
}
|
}
|
||||||
} else if cx.tcx.sess.target.arch == "x86"
|
} else if cx.tcx.sess.target.arch == "x86"
|
||||||
|
&& common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
|
||||||
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
||||||
{
|
{
|
||||||
cx.declare_global(
|
cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty)
|
||||||
&common::i686_decorated_name(
|
|
||||||
dllimport,
|
|
||||||
common::is_mingw_gnu_toolchain(&cx.tcx.sess.target),
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
llty,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
// Generate an external declaration.
|
// Generate an external declaration.
|
||||||
// FIXME(nagisa): investigate whether it can be changed into define_global
|
// FIXME(nagisa): investigate whether it can be changed into define_global
|
||||||
|
|
|
@ -26,6 +26,35 @@ use crate::errors::{
|
||||||
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An item to be included in an import library.
|
||||||
|
/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
|
||||||
|
pub struct ImportLibraryItem {
|
||||||
|
/// The name to be exported.
|
||||||
|
pub name: String,
|
||||||
|
/// The ordinal to be exported, if any.
|
||||||
|
pub ordinal: Option<u16>,
|
||||||
|
/// The original, decorated name if `name` is not decorated.
|
||||||
|
pub symbol_name: Option<String>,
|
||||||
|
/// True if this is a data export, false if it is a function export.
|
||||||
|
pub is_data: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ImportLibraryItem> for COFFShortExport {
|
||||||
|
fn from(item: ImportLibraryItem) -> Self {
|
||||||
|
COFFShortExport {
|
||||||
|
name: item.name,
|
||||||
|
ext_name: None,
|
||||||
|
symbol_name: item.symbol_name,
|
||||||
|
alias_target: None,
|
||||||
|
ordinal: item.ordinal.unwrap_or(0),
|
||||||
|
noname: item.ordinal.is_some(),
|
||||||
|
data: item.is_data,
|
||||||
|
private: false,
|
||||||
|
constant: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ArchiveBuilderBuilder {
|
pub trait ArchiveBuilderBuilder {
|
||||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
||||||
|
|
||||||
|
@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder {
|
||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
items: Vec<ImportLibraryItem>,
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
) {
|
) {
|
||||||
if common::is_mingw_gnu_toolchain(&sess.target) {
|
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||||
|
@ -47,21 +76,16 @@ pub trait ArchiveBuilderBuilder {
|
||||||
// that loaded but crashed with an AV upon calling one of the imported
|
// that loaded but crashed with an AV upon calling one of the imported
|
||||||
// functions. Therefore, use binutils to create the import library instead,
|
// functions. Therefore, use binutils to create the import library instead,
|
||||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||||
create_mingw_dll_import_lib(
|
create_mingw_dll_import_lib(sess, lib_name, items, output_path);
|
||||||
sess,
|
|
||||||
lib_name,
|
|
||||||
import_name_and_ordinal_vector,
|
|
||||||
output_path,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
trace!("creating import library");
|
trace!("creating import library");
|
||||||
trace!(" dll_name {:#?}", lib_name);
|
trace!(" dll_name {:#?}", lib_name);
|
||||||
trace!(" output_path {}", output_path.display());
|
trace!(" output_path {}", output_path.display());
|
||||||
trace!(
|
trace!(
|
||||||
" import names: {}",
|
" import names: {}",
|
||||||
import_name_and_ordinal_vector
|
items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, _ordinal)| name.clone())
|
.map(|ImportLibraryItem { name, .. }| name.clone())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
);
|
);
|
||||||
|
@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder {
|
||||||
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
|
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
|
||||||
};
|
};
|
||||||
|
|
||||||
let exports = import_name_and_ordinal_vector
|
let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
|
||||||
.iter()
|
|
||||||
.map(|(name, ordinal)| COFFShortExport {
|
|
||||||
name: name.to_string(),
|
|
||||||
ext_name: None,
|
|
||||||
symbol_name: None,
|
|
||||||
alias_target: None,
|
|
||||||
ordinal: ordinal.unwrap_or(0),
|
|
||||||
noname: ordinal.is_some(),
|
|
||||||
data: false,
|
|
||||||
private: false,
|
|
||||||
constant: false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let machine = match &*sess.target.arch {
|
let machine = match &*sess.target.arch {
|
||||||
"x86_64" => MachineTypes::AMD64,
|
"x86_64" => MachineTypes::AMD64,
|
||||||
"x86" => MachineTypes::I386,
|
"x86" => MachineTypes::I386,
|
||||||
|
@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder {
|
||||||
fn create_mingw_dll_import_lib(
|
fn create_mingw_dll_import_lib(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
items: Vec<ImportLibraryItem>,
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
) {
|
) {
|
||||||
let def_file_path = output_path.with_extension("def");
|
let def_file_path = output_path.with_extension("def");
|
||||||
|
|
||||||
let def_file_content = format!(
|
let def_file_content = format!(
|
||||||
"EXPORTS\n{}",
|
"EXPORTS\n{}",
|
||||||
import_name_and_ordinal_vector
|
items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, ordinal)| {
|
.map(|ImportLibraryItem { name, ordinal, .. }| {
|
||||||
match ordinal {
|
match ordinal {
|
||||||
Some(n) => format!("{name} @{n} NONAME"),
|
Some(n) => format!("{name} @{n} NONAME"),
|
||||||
None => name,
|
None => name,
|
||||||
|
|
|
@ -45,7 +45,7 @@ use rustc_target::spec::{
|
||||||
use tempfile::Builder as TempFileBuilder;
|
use tempfile::Builder as TempFileBuilder;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
|
||||||
use super::command::Command;
|
use super::command::Command;
|
||||||
use super::linker::{self, Linker};
|
use super::linker::{self, Linker};
|
||||||
use super::metadata::{create_wrapper_file, MetadataPosition};
|
use super::metadata::{create_wrapper_file, MetadataPosition};
|
||||||
|
@ -498,16 +498,35 @@ fn create_dll_import_libs<'a>(
|
||||||
|
|
||||||
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
|
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
|
||||||
|
|
||||||
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
|
let items: Vec<ImportLibraryItem> = raw_dylib_imports
|
||||||
.iter()
|
.iter()
|
||||||
.map(|import: &DllImport| {
|
.map(|import: &DllImport| {
|
||||||
if sess.target.arch == "x86" {
|
if sess.target.arch == "x86" {
|
||||||
(
|
ImportLibraryItem {
|
||||||
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
|
name: common::i686_decorated_name(
|
||||||
import.ordinal(),
|
import,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
ordinal: import.ordinal(),
|
||||||
|
symbol_name: import.is_missing_decorations().then(|| {
|
||||||
|
common::i686_decorated_name(
|
||||||
|
import,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
|
}),
|
||||||
|
is_data: !import.is_fn,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(import.name.to_string(), import.ordinal())
|
ImportLibraryItem {
|
||||||
|
name: import.name.to_string(),
|
||||||
|
ordinal: import.ordinal(),
|
||||||
|
symbol_name: None,
|
||||||
|
is_data: !import.is_fn,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -515,7 +534,7 @@ fn create_dll_import_libs<'a>(
|
||||||
archive_builder_builder.create_dll_import_lib(
|
archive_builder_builder.create_dll_import_lib(
|
||||||
sess,
|
sess,
|
||||||
&raw_dylib_name,
|
&raw_dylib_name,
|
||||||
import_name_and_ordinal_vector,
|
items,
|
||||||
&output_path,
|
&output_path,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -187,12 +187,15 @@ pub fn i686_decorated_name(
|
||||||
dll_import: &DllImport,
|
dll_import: &DllImport,
|
||||||
mingw: bool,
|
mingw: bool,
|
||||||
disable_name_mangling: bool,
|
disable_name_mangling: bool,
|
||||||
|
force_fully_decorated: bool,
|
||||||
) -> String {
|
) -> String {
|
||||||
let name = dll_import.name.as_str();
|
let name = dll_import.name.as_str();
|
||||||
|
|
||||||
let (add_prefix, add_suffix) = match dll_import.import_name_type {
|
let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
|
||||||
Some(PeImportNameType::NoPrefix) => (false, true),
|
// No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
|
||||||
Some(PeImportNameType::Undecorated) => (false, false),
|
// ignore `force_fully_decorated` and always partially decorate it.
|
||||||
|
(_, Some(PeImportNameType::NoPrefix)) => (false, true),
|
||||||
|
(false, Some(PeImportNameType::Undecorated)) => (false, false),
|
||||||
_ => (true, true),
|
_ => (true, true),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,11 @@ impl DllImport {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_missing_decorations(&self) -> bool {
|
||||||
|
self.import_name_type == Some(PeImportNameType::Undecorated)
|
||||||
|
|| self.import_name_type == Some(PeImportNameType::NoPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calling convention for a function defined in an external library.
|
/// Calling convention for a function defined in an external library.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue