diff options
Diffstat (limited to 'xtask/src/lib.rs')
-rw-r--r-- | xtask/src/lib.rs | 96 |
1 files changed, 4 insertions, 92 deletions
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index b1e982e..a7b85e7 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -4,9 +4,6 @@ //! //! Also see the docs in `asm.rs`. -use object::read::{Object as _, ObjectSection as _}; -use object::write::{Object, Symbol, SymbolSection}; -use object::{ObjectSymbol, SymbolFlags}; use std::collections::BTreeMap; use std::env::current_dir; use std::fs::{self, File}; @@ -25,90 +22,6 @@ fn rustc() -> Command { cmd } -/// Patches an object file so that it doesn't contain a panic handler. -/// -/// The panic handler defined in `asm/lib.rs` should never get linked to the final program. -/// Unfortunately, Rust uses the same symbol for all panic handlers, and doesn't really like it if -/// that ends up with multiple ones. It also demands that we define a panic handler for the inline -/// assembly shim, even though none of that code should ever be able to panic. The result of this is -/// that the supposedly unreachable panic handler does end up getting linked into the final program, -/// unless it is built with optimizations enabled. -/// -/// To fix that, we put the never-to-be-used panic handler into its own section via -/// `#[link_section]`, and then use this function to delete that section. -fn trim_panic_handler(obj_file: &str) { - let objdata = fs::read(&obj_file).unwrap(); - let obj = object::File::parse(&objdata).unwrap(); - - let mut writer = Object::new(obj.format(), obj.architecture(), obj.endianness()); - writer.flags = obj.flags(); // Preserve flags of input file - - for (sec_index, section) in obj.sections().enumerate() { - assert_eq!(section.index().0, sec_index); - - let name = section.name().unwrap(); - if name.starts_with(".ARM") - || name.starts_with(".rel.ARM") - || name.contains("asm_panic_handler") - || name == ".strtab" - || name == ".symtab" - { - // We drop the ARM exception handling tables since they refer back to the panic handler - // symbol. They aren't used either way. We also drop `.strtab` and `.symtab` since they - // otherwise end up having the wrong section type. The object crate should rebuild any - // index tables when writing the file. - continue; - } - - let segment = section - .segment_name() - .unwrap() - .map(|s| s.as_bytes()) - .unwrap_or(&[]); - let sec_id = writer.add_section(segment.to_vec(), name.as_bytes().to_vec(), section.kind()); - - let align = if section.align() == 0 { - // Not sure why but `section.align()` can return 0. - 1 - } else { - section.align() - }; - writer.append_section_data(sec_id, section.data().unwrap(), align); - - // Import all symbols from the section. - for symbol in obj.symbols() { - if symbol.section_index() == Some(section.index()) { - writer.add_symbol(Symbol { - name: symbol.name().unwrap_or("").as_bytes().to_vec(), - value: symbol.address(), - size: symbol.size(), - kind: symbol.kind(), - scope: symbol.scope(), - weak: symbol.is_weak(), - section: match symbol.section() { - object::SymbolSection::Unknown => unimplemented!(), - object::SymbolSection::None => SymbolSection::None, - object::SymbolSection::Undefined => SymbolSection::Undefined, - object::SymbolSection::Absolute => SymbolSection::Absolute, - object::SymbolSection::Common => SymbolSection::Common, - object::SymbolSection::Section(_) => SymbolSection::Section(sec_id), - }, - flags: match symbol.flags() { - SymbolFlags::None => SymbolFlags::None, - SymbolFlags::Elf { st_info, st_other } => { - SymbolFlags::Elf { st_info, st_other } - } - _ => unimplemented!(), - }, - }); - } - } - } - - let obj = writer.write().unwrap(); - fs::write(&obj_file, obj).unwrap(); -} - fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) { let mut cmd = rustc(); @@ -122,6 +35,10 @@ fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) { // We always optimize the assembly shims. There's not really any reason not to. cmd.arg("-O"); + // We use LTO on the archive to ensure the (unused) panic handler is removed, preventing + // a linker error when the archives are linked into final crates with two panic handlers. + cmd.arg("-Clto=yes"); + // rustc will usually add frame pointers by default to aid with debugging, but that is a high // overhead for the tiny assembly routines. cmd.arg("-Cforce-frame-pointers=no"); @@ -158,11 +75,6 @@ fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) { let status = cmd.status().unwrap(); assert!(status.success()); - if !plugin_lto { - // Post-process the object file. - trim_panic_handler(&obj_file); - } - // Archive `target.o` -> `bin/target.a`. let mut builder = ar::Builder::new(File::create(format!("bin/{}.a", file_stub)).unwrap()); |