1 // run-pass
2 // ignore-android no libc
3 // ignore-emscripten no libc
4 // ignore-sgx no libc
5 // ignore-wasm32 no libc
6 // only-linux
7 // compile-flags:-C panic=abort
8 // aux-build:helper.rs
9 
10 #![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
11 #![feature(alloc_error_handler)]
12 #![no_std]
13 
14 extern crate alloc;
15 extern crate libc;
16 
17 // ARM targets need these symbols
18 #[no_mangle]
__aeabi_unwind_cpp_pr0()19 pub fn __aeabi_unwind_cpp_pr0() {}
20 
21 #[no_mangle]
__aeabi_unwind_cpp_pr1()22 pub fn __aeabi_unwind_cpp_pr1() {}
23 
24 use core::ptr::null_mut;
25 use core::alloc::{GlobalAlloc, Layout};
26 use alloc::boxed::Box;
27 
28 extern crate helper;
29 
30 struct MyAllocator;
31 
32 #[alloc_error_handler]
my_oom(layout: Layout) -> !33 fn my_oom(layout: Layout) -> !
34 {
35     use alloc::fmt::write;
36     unsafe {
37         let size = layout.size();
38         let mut s = alloc::string::String::new();
39         write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
40         let s = s.as_str();
41         libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
42         libc::exit(0)
43     }
44 }
45 
46 unsafe impl GlobalAlloc for MyAllocator {
alloc(&self, layout: Layout) -> *mut u847     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
48         if layout.size() < 4096 {
49             libc::malloc(layout.size()) as _
50         } else {
51             null_mut()
52         }
53     }
dealloc(&self, _ptr: *mut u8, _layout: Layout)54     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
55 }
56 
57 #[global_allocator]
58 static A: MyAllocator = MyAllocator;
59 
60 #[panic_handler]
panic(panic_info: &core::panic::PanicInfo) -> !61 fn panic(panic_info: &core::panic::PanicInfo) -> ! {
62     unsafe {
63         if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
64             const PSTR: &str = "panic occurred: ";
65             const CR: &str = "\n";
66             libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
67             libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
68             libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
69         }
70         if let Some(args) = panic_info.message() {
71             let mut s = alloc::string::String::new();
72             alloc::fmt::write(&mut s, *args).unwrap();
73             let s = s.as_str();
74             const PSTR: &str = "panic occurred: ";
75             const CR: &str = "\n";
76             libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
77             libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
78             libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
79         } else {
80             const PSTR: &str = "panic occurred\n";
81             libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
82         }
83         libc::exit(1)
84     }
85 }
86 
87 // Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed.
88 // However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions
89 // in these libaries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
90 // unwind. So, for this test case we will define the symbol.
91 #[lang = "eh_personality"]
rust_eh_personality()92 extern fn rust_eh_personality() {}
93 
94 #[derive(Debug)]
95 struct Page([[u64; 32]; 16]);
96 
97 #[start]
main(_argc: isize, _argv: *const *const u8) -> isize98 pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
99     let zero = Box::<Page>::new_zeroed();
100     let zero = unsafe { zero.assume_init() };
101     helper::work_with(&zero);
102     1
103 }
104