Skip to content

Commit

Permalink
android: set abort message
Browse files Browse the repository at this point in the history
Android has the ability to supply an abort message [1]. This message is
automatically included in the debug trace, which helps debugging [2].
Modify panic_abort to populate this message before calling abort().

[1] https://android.googlesource.com/platform/bionic/+/master/libc/include/android/set_abort_message.h
[2] https://source.android.com/devices/tech/debug/native-crash
  • Loading branch information
tweksteen committed Mar 23, 2021
1 parent 2287a88 commit f41d0a4
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2471,6 +2471,7 @@ dependencies = [
name = "panic_abort"
version = "0.0.0"
dependencies = [
"alloc",
"cfg-if 0.1.10",
"compiler_builtins",
"core",
Expand Down
1 change: 1 addition & 0 deletions library/panic_abort/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ bench = false
doc = false

[dependencies]
alloc = { path = "../alloc" }
cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
core = { path = "../core" }
libc = { version = "0.2", default-features = false }
Expand Down
44 changes: 44 additions & 0 deletions library/panic_abort/src/android.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use alloc::string::String;
use alloc::vec::Vec;
use core::mem::transmute;
use core::panic::BoxMeUp;

const ANDROID_SET_ABORT_MESSAGE: &[u8] = b"android_set_abort_message\0";
type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> ();

// Forward the abort message to libc's android_set_abort_message. The fallible allocator is used
// to avoid panicking, as this function may already be called as part of a failed allocation.
//
// Weakly resolve the symbol for android_set_abort_message. This function is only available
// for API >= 21.
pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
let func_addr =
libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char)
as usize;
if func_addr == 0 {
return;
}

let payload = (*payload).get();
let msg = match payload.downcast_ref::<&'static str>() {
Some(msg) => msg.as_bytes(),
None => match payload.downcast_ref::<String>() {
Some(msg) => msg.as_bytes(),
None => &[],
},
};
if msg.is_empty() {
return;
}

let size = msg.len() + 1;
let mut v = Vec::new();
if v.try_reserve(size).is_err() {
return;
}

v.extend(msg);
v.push(0);
let func = transmute::<usize, SetAbortMessageType>(func_addr);
func(v.as_ptr() as *const libc::c_char);
}
7 changes: 7 additions & 0 deletions library/panic_abort/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![feature(asm)]
#![cfg_attr(target_os = "android", feature(try_reserve))]
#[cfg(target_os = "android")]
mod android;

use core::any::Any;
use core::panic::BoxMeUp;
Expand All @@ -31,6 +34,10 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
// "Leak" the payload and shim to the relevant abort on the platform in question.
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 {
// Android has the ability to attach a message as part of the abort.
#[cfg(target_os = "android")]
android::android_set_abort_message(_payload);

abort();

cfg_if::cfg_if! {
Expand Down

0 comments on commit f41d0a4

Please sign in to comment.