|  | //@ run-pass | 
|  | //@ ignore-android no libc | 
|  | //@ ignore-emscripten no libc | 
|  | //@ ignore-sgx no libc | 
|  | //@ ignore-backends: gcc | 
|  | //@ only-linux | 
|  | //@ compile-flags:-C panic=abort | 
|  | //@ aux-build:helper.rs | 
|  |  | 
|  | #![feature(rustc_private, lang_items, panic_unwind)] | 
|  | #![feature(alloc_error_handler)] | 
|  | #![no_std] | 
|  | #![no_main] | 
|  |  | 
|  | extern crate alloc; | 
|  | extern crate libc; | 
|  | extern crate unwind; // For _Unwind_Resume | 
|  |  | 
|  | // ARM targets need these symbols | 
|  | #[no_mangle] | 
|  | pub fn __aeabi_unwind_cpp_pr0() {} | 
|  |  | 
|  | #[no_mangle] | 
|  | pub fn __aeabi_unwind_cpp_pr1() {} | 
|  |  | 
|  | use alloc::boxed::Box; | 
|  | use alloc::string::ToString; | 
|  | use core::alloc::{GlobalAlloc, Layout}; | 
|  | use core::ptr::null_mut; | 
|  |  | 
|  | extern crate helper; | 
|  |  | 
|  | struct MyAllocator; | 
|  |  | 
|  | #[alloc_error_handler] | 
|  | fn my_oom(layout: Layout) -> ! { | 
|  | use alloc::fmt::write; | 
|  | unsafe { | 
|  | let size = layout.size(); | 
|  | let mut s = alloc::string::String::new(); | 
|  | write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap(); | 
|  | libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); | 
|  | libc::exit(0) | 
|  | } | 
|  | } | 
|  |  | 
|  | unsafe impl GlobalAlloc for MyAllocator { | 
|  | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | 
|  | if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() } | 
|  | } | 
|  | unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} | 
|  | } | 
|  |  | 
|  | #[global_allocator] | 
|  | static A: MyAllocator = MyAllocator; | 
|  |  | 
|  | #[panic_handler] | 
|  | fn panic(panic_info: &core::panic::PanicInfo) -> ! { | 
|  | unsafe { | 
|  | let s = panic_info.to_string(); | 
|  | const PSTR: &str = "panic occurred: "; | 
|  | const CR: &str = "\n"; | 
|  | libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len()); | 
|  | libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); | 
|  | libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len()); | 
|  | libc::exit(1) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. | 
|  | // However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions | 
|  | // in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't | 
|  | // unwind. So, for this test case we will define the symbol. | 
|  | #[lang = "eh_personality"] | 
|  | extern "C" fn rust_eh_personality( | 
|  | _version: i32, | 
|  | _actions: i32, | 
|  | _exception_class: u64, | 
|  | _exception_object: *mut (), | 
|  | _context: *mut (), | 
|  | ) -> i32 { | 
|  | loop {} | 
|  | } | 
|  |  | 
|  | #[derive(Default, Debug)] | 
|  | struct Page(#[allow(dead_code)] [[u64; 32]; 16]); | 
|  |  | 
|  | #[no_mangle] | 
|  | fn main(_argc: i32, _argv: *const *const u8) -> isize { | 
|  | let zero = Box::<Page>::new(Default::default()); | 
|  | helper::work_with(&zero); | 
|  | 1 | 
|  | } |