Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit be04b07

Browse files
committedJan 18, 2025·
Support raw-dylib link kind on ELF
raw-dylib is a link kind that allows rustc to link against a library without having any library files present. This currently only exists on Windows. rustc will take all the symbols from raw-dylib link blocks and put them in an import library, where they can then be resolved by the linker. While import libraries don't exist on ELF, it would still be convenient to have this same functionality. Not having the libraries present at build-time can be convenient for several reasons, especially cross-compilation. With raw-dylib, code linking against a library can be cross-compiled without needing to have these libraries available on the build machine. If the libc crate makes use of this, it would allow cross-compilation without having any libc available on the build machine. This is not yet possible with this implementation, at least against libc's like glibc that use symbol versioning. The raw-dylib kind could be extended with support for symbol versioning in the future. This implementation is very experimental and I have not tested it very well. I have tested it for a toy example and the lz4-sys crate, where it was able to successfully link a binary despite not having a corresponding library at build-time.
1 parent 8e59cf9 commit be04b07

File tree

62 files changed

+609
-127
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+609
-127
lines changed
 

‎compiler/rustc_codegen_ssa/src/back/link.rs

+270-41
Large diffs are not rendered by default.

‎compiler/rustc_codegen_ssa/src/back/metadata.rs

+27-69
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use itertools::Itertools;
99
use object::write::{self, StandardSegment, Symbol, SymbolSection};
1010
use object::{
1111
Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol,
12-
SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe,
13-
xcoff,
12+
SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff,
1413
};
1514
use rustc_abi::Endian;
1615
use rustc_data_structures::memmap::Mmap;
@@ -206,61 +205,12 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
206205
Endian::Little => Endianness::Little,
207206
Endian::Big => Endianness::Big,
208207
};
209-
let (architecture, sub_architecture) = match &sess.target.arch[..] {
210-
"arm" => (Architecture::Arm, None),
211-
"aarch64" => (
212-
if sess.target.pointer_width == 32 {
213-
Architecture::Aarch64_Ilp32
214-
} else {
215-
Architecture::Aarch64
216-
},
217-
None,
218-
),
219-
"x86" => (Architecture::I386, None),
220-
"s390x" => (Architecture::S390x, None),
221-
"mips" | "mips32r6" => (Architecture::Mips, None),
222-
"mips64" | "mips64r6" => (Architecture::Mips64, None),
223-
"x86_64" => (
224-
if sess.target.pointer_width == 32 {
225-
Architecture::X86_64_X32
226-
} else {
227-
Architecture::X86_64
228-
},
229-
None,
230-
),
231-
"powerpc" => (Architecture::PowerPc, None),
232-
"powerpc64" => (Architecture::PowerPc64, None),
233-
"riscv32" => (Architecture::Riscv32, None),
234-
"riscv64" => (Architecture::Riscv64, None),
235-
"sparc" => {
236-
if sess.unstable_target_features.contains(&sym::v8plus) {
237-
// Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode
238-
(Architecture::Sparc32Plus, None)
239-
} else {
240-
// Target uses V7 or V8, aka EM_SPARC
241-
(Architecture::Sparc, None)
242-
}
243-
}
244-
"sparc64" => (Architecture::Sparc64, None),
245-
"avr" => (Architecture::Avr, None),
246-
"msp430" => (Architecture::Msp430, None),
247-
"hexagon" => (Architecture::Hexagon, None),
248-
"bpf" => (Architecture::Bpf, None),
249-
"loongarch64" => (Architecture::LoongArch64, None),
250-
"csky" => (Architecture::Csky, None),
251-
"arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)),
252-
// Unsupported architecture.
253-
_ => return None,
254-
};
255-
let binary_format = if sess.target.is_like_osx {
256-
BinaryFormat::MachO
257-
} else if sess.target.is_like_windows {
258-
BinaryFormat::Coff
259-
} else if sess.target.is_like_aix {
260-
BinaryFormat::Xcoff
261-
} else {
262-
BinaryFormat::Elf
208+
let Some((architecture, sub_architecture)) =
209+
sess.target.object_architecture(&sess.unstable_target_features)
210+
else {
211+
return None;
263212
};
213+
let binary_format = sess.target.binary_format();
264214

265215
let mut file = write::Object::new(binary_format, architecture, endianness);
266216
file.set_sub_architecture(sub_architecture);
@@ -300,7 +250,26 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
300250

301251
file.set_mangling(original_mangling);
302252
}
303-
let e_flags = match architecture {
253+
let e_flags = elf_e_flags(architecture, sess);
254+
// adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
255+
let os_abi = elf_os_abi(sess);
256+
let abi_version = 0;
257+
add_gnu_property_note(&mut file, architecture, binary_format, endianness);
258+
file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
259+
Some(file)
260+
}
261+
262+
pub(super) fn elf_os_abi(sess: &Session) -> u8 {
263+
match sess.target.options.os.as_ref() {
264+
"hermit" => elf::ELFOSABI_STANDALONE,
265+
"freebsd" => elf::ELFOSABI_FREEBSD,
266+
"solaris" => elf::ELFOSABI_SOLARIS,
267+
_ => elf::ELFOSABI_NONE,
268+
}
269+
}
270+
271+
pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
272+
match architecture {
304273
Architecture::Mips => {
305274
let arch = match sess.target.options.cpu.as_ref() {
306275
"mips1" => elf::EF_MIPS_ARCH_1,
@@ -391,18 +360,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
391360
e_flags
392361
}
393362
_ => 0,
394-
};
395-
// adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
396-
let os_abi = match sess.target.options.os.as_ref() {
397-
"hermit" => elf::ELFOSABI_STANDALONE,
398-
"freebsd" => elf::ELFOSABI_FREEBSD,
399-
"solaris" => elf::ELFOSABI_SOLARIS,
400-
_ => elf::ELFOSABI_NONE,
401-
};
402-
let abi_version = 0;
403-
add_gnu_property_note(&mut file, architecture, binary_format, endianness);
404-
file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
405-
Some(file)
363+
}
406364
}
407365

408366
/// Mach-O files contain information about:

0 commit comments

Comments
 (0)
Please sign in to comment.