summaryrefslogtreecommitdiffstats
path: root/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
blob: 28926243390932390a6873f0c85fea9b707e6493 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// run-pass
// ignore-android no libc
// ignore-emscripten no libc
// ignore-sgx no libc
// ignore-wasm32 no libc
// only-linux
// compile-flags:-C panic=abort
// aux-build:helper.rs

#![feature(rustc_private, lang_items)]
#![feature(alloc_error_handler)]
#![no_std]
#![no_main]

extern crate alloc;
extern crate libc;

// 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() {}

#[derive(Default, Debug)]
struct Page(#[allow(unused_tuple_struct_fields)] [[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
}