|
| 1 | +use alloc::string::String; |
| 2 | +use core::mem::transmute; |
| 3 | +use core::panic::BoxMeUp; |
| 4 | +use core::ptr::copy_nonoverlapping; |
| 5 | + |
| 6 | +const ANDROID_SET_ABORT_MESSAGE: &[u8] = b"android_set_abort_message\0"; |
| 7 | +type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> (); |
| 8 | + |
| 9 | +// Forward the abort message to libc's android_set_abort_message. We try our best to populate the |
| 10 | +// message but as this function may already be called as part of a failed allocation, it may not be |
| 11 | +// possible to do so. |
| 12 | +// |
| 13 | +// Some methods of core are on purpose avoided (such as try_reserve) as these rely on the correct |
| 14 | +// resolution of rust_eh_personality which is loosely defined in panic_abort. |
| 15 | +// |
| 16 | +// Weakly resolve the symbol for android_set_abort_message. This function is only available |
| 17 | +// for API >= 21. |
| 18 | +pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { |
| 19 | + let func_addr = |
| 20 | + libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char) |
| 21 | + as usize; |
| 22 | + if func_addr == 0 { |
| 23 | + return; |
| 24 | + } |
| 25 | + |
| 26 | + let payload = (*payload).get(); |
| 27 | + let msg = match payload.downcast_ref::<&'static str>() { |
| 28 | + Some(msg) => msg.as_bytes(), |
| 29 | + None => match payload.downcast_ref::<String>() { |
| 30 | + Some(msg) => msg.as_bytes(), |
| 31 | + None => &[], |
| 32 | + }, |
| 33 | + }; |
| 34 | + if msg.is_empty() { |
| 35 | + return; |
| 36 | + } |
| 37 | + |
| 38 | + // Allocate a new buffer to append the null byte. |
| 39 | + let size = msg.len() + 1usize; |
| 40 | + let buf = libc::malloc(size) as *mut libc::c_char; |
| 41 | + if buf.is_null() { |
| 42 | + return; // allocation failure |
| 43 | + } |
| 44 | + copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len()); |
| 45 | + buf.offset(msg.len() as isize).write(0); |
| 46 | + |
| 47 | + let func = transmute::<usize, SetAbortMessageType>(func_addr); |
| 48 | + func(buf); |
| 49 | +} |
0 commit comments