From a3572979cb88b0ca5760b4a672f652250dadf3bb Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 29 Aug 2020 02:17:35 +0200 Subject: Merge asm implementations --- xtask/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 4575f65..e6248d1 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -68,7 +68,7 @@ fn assemble_really(target: &str, cfgs: &[&str], plugin_lto: bool) { // Pass output and input file. cmd.arg("-o").arg(&obj_file); - cmd.arg("asm.rs"); + cmd.arg("asm/lib.rs"); println!("{:?}", cmd); let status = cmd.status().unwrap(); @@ -198,7 +198,10 @@ pub fn check_blobs() { for ((file, before), (_, after)) in files_before.iter().zip(files_after.iter()) { if before != after { - panic!("{} differs between rebuilds", file); + panic!( + "{} is not up-to-date, please run `cargo xtask assemble`", + file + ); } } -- cgit v1.2.3 From 0f23877e4638183b3c819184e552507c94185383 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 30 Aug 2020 18:35:49 +0200 Subject: Patch out the asm shim panic handler --- bin/thumbv6m-none-eabi.a | Bin 18284 -> 16124 bytes bin/thumbv7em-none-eabi.a | Bin 23360 -> 20436 bytes bin/thumbv7em-none-eabihf.a | Bin 24684 -> 21552 bytes bin/thumbv7m-none-eabi.a | Bin 22020 -> 19276 bytes bin/thumbv8m.base-none-eabi.a | Bin 20936 -> 18352 bytes bin/thumbv8m.main-none-eabi.a | Bin 27220 -> 23652 bytes bin/thumbv8m.main-none-eabihf.a | Bin 28488 -> 24704 bytes xtask/Cargo.toml | 4 ++ xtask/src/lib.rs | 95 +++++++++++++++++++++++++++++++++++++++- 9 files changed, 97 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/bin/thumbv6m-none-eabi.a b/bin/thumbv6m-none-eabi.a index 072dd15..5c8c758 100644 Binary files a/bin/thumbv6m-none-eabi.a and b/bin/thumbv6m-none-eabi.a differ diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a index d7a2c88..ec56934 100644 Binary files a/bin/thumbv7em-none-eabi.a and b/bin/thumbv7em-none-eabi.a differ diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a index 88ac78e..75a7e5d 100644 Binary files a/bin/thumbv7em-none-eabihf.a and b/bin/thumbv7em-none-eabihf.a differ diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a index a97ae6a..ae9db60 100644 Binary files a/bin/thumbv7m-none-eabi.a and b/bin/thumbv7m-none-eabi.a differ diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a index 4c68990..e8bb7a6 100644 Binary files a/bin/thumbv8m.base-none-eabi.a and b/bin/thumbv8m.base-none-eabi.a differ diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a index 2e7280d..af9179a 100644 Binary files a/bin/thumbv8m.main-none-eabi.a and b/bin/thumbv8m.main-none-eabi.a differ diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a index b16ae98..3189a29 100644 Binary files a/bin/thumbv8m.main-none-eabihf.a and b/bin/thumbv8m.main-none-eabihf.a differ diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 06c5143..e23d1a7 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,3 +11,7 @@ harness = false [dependencies] ar = "0.8.0" + +[dependencies.object] +version = "0.21.1" +features = ["write"] diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index e6248d1..3ff66e8 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -4,12 +4,16 @@ //! //! Also see the docs in `asm.rs`. -use process::Stdio; +use object::{ + read::{Object as _, ObjectSection as _}, + write::{Object, Symbol, SymbolSection}, + SymbolFlags, +}; use std::env::current_dir; use std::{ collections::BTreeMap, fs::{self, File}, - process::{self, Command}, + process::{Command, Stdio}, }; fn toolchain() -> String { @@ -25,6 +29,88 @@ 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()); + 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("cortex_m_asm_panic") + || 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 (_sym_idx, 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(); @@ -74,6 +160,11 @@ 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()); -- cgit v1.2.3