1
Fork 0

Test fixing raw-dylib

This commit is contained in:
Daniel Paoliello 2024-09-19 15:00:30 -07:00
parent 13a5097796
commit b2fd8a0192
7 changed files with 95 additions and 55 deletions

View file

@ -26,6 +26,35 @@ use crate::errors::{
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 {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder {
&self,
sess: &Session,
lib_name: &str,
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
items: Vec<ImportLibraryItem>,
output_path: &Path,
) {
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
// functions. Therefore, use binutils to create the import library instead,
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
create_mingw_dll_import_lib(
sess,
lib_name,
import_name_and_ordinal_vector,
output_path,
);
create_mingw_dll_import_lib(sess, lib_name, items, output_path);
} else {
trace!("creating import library");
trace!(" dll_name {:#?}", lib_name);
trace!(" output_path {}", output_path.display());
trace!(
" import names: {}",
import_name_and_ordinal_vector
items
.iter()
.map(|(name, _ordinal)| name.clone())
.map(|ImportLibraryItem { name, .. }| name.clone())
.collect::<Vec<_>>()
.join(", "),
);
@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder {
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
};
let exports = import_name_and_ordinal_vector
.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 exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
let machine = match &*sess.target.arch {
"x86_64" => MachineTypes::AMD64,
"x86" => MachineTypes::I386,
@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder {
fn create_mingw_dll_import_lib(
sess: &Session,
lib_name: &str,
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
items: Vec<ImportLibraryItem>,
output_path: &Path,
) {
let def_file_path = output_path.with_extension("def");
let def_file_content = format!(
"EXPORTS\n{}",
import_name_and_ordinal_vector
items
.into_iter()
.map(|(name, ordinal)| {
.map(|ImportLibraryItem { name, ordinal, .. }| {
match ordinal {
Some(n) => format!("{name} @{n} NONAME"),
None => name,

View file

@ -45,7 +45,7 @@ use rustc_target::spec::{
use tempfile::Builder as TempFileBuilder;
use tracing::{debug, info, warn};
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
use super::command::Command;
use super::linker::{self, Linker};
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 import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
let items: Vec<ImportLibraryItem> = raw_dylib_imports
.iter()
.map(|import: &DllImport| {
if sess.target.arch == "x86" {
(
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
import.ordinal(),
)
ImportLibraryItem {
name: common::i686_decorated_name(
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 {
(import.name.to_string(), import.ordinal())
ImportLibraryItem {
name: import.name.to_string(),
ordinal: import.ordinal(),
symbol_name: None,
is_data: !import.is_fn,
}
}
})
.collect();
@ -515,7 +534,7 @@ fn create_dll_import_libs<'a>(
archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
import_name_and_ordinal_vector,
items,
&output_path,
);

View file

@ -187,12 +187,15 @@ pub fn i686_decorated_name(
dll_import: &DllImport,
mingw: bool,
disable_name_mangling: bool,
force_fully_decorated: bool,
) -> String {
let name = dll_import.name.as_str();
let (add_prefix, add_suffix) = match dll_import.import_name_type {
Some(PeImportNameType::NoPrefix) => (false, true),
Some(PeImportNameType::Undecorated) => (false, false),
let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
// No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
// ignore `force_fully_decorated` and always partially decorate it.
(_, Some(PeImportNameType::NoPrefix)) => (false, true),
(false, Some(PeImportNameType::Undecorated)) => (false, false),
_ => (true, true),
};