about summary refs log tree commit diff
path: root/library/panic_abort
diff options
context:
space:
mode:
authorThiƩbaud Weksteen <tweek@google.com>2021-03-15 11:21:39 +0100
committerThiƩbaud Weksteen <tweek@google.com>2021-04-09 15:33:43 +0200
commit52ee9fbc027f7c371ed2e34ad191633a42c11c95 (patch)
treeaf313f08ef9db0438d1dbc4a0762f47b607acfdd /library/panic_abort
parent354cc751b74e813f180755fa67bebcb669825755 (diff)
downloadrust-52ee9fbc027f7c371ed2e34ad191633a42c11c95.tar.gz
rust-52ee9fbc027f7c371ed2e34ad191633a42c11c95.zip
android: set abort message
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
Diffstat (limited to 'library/panic_abort')
-rw-r--r--library/panic_abort/Cargo.toml1
-rw-r--r--library/panic_abort/src/android.rs49
-rw-r--r--library/panic_abort/src/lib.rs7
3 files changed, 57 insertions, 0 deletions
diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml
index caa89aa30d0..bdab664cd64 100644
--- a/library/panic_abort/Cargo.toml
+++ b/library/panic_abort/Cargo.toml
@@ -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 }
diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs
new file mode 100644
index 00000000000..34d77502eab
--- /dev/null
+++ b/library/panic_abort/src/android.rs
@@ -0,0 +1,49 @@
+use alloc::string::String;
+use core::mem::transmute;
+use core::panic::BoxMeUp;
+use core::ptr::copy_nonoverlapping;
+
+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. We try our best to populate the
+// message but as this function may already be called as part of a failed allocation, it may not be
+// possible to do so.
+//
+// Some methods of core are on purpose avoided (such as try_reserve) as these rely on the correct
+// resolution of rust_eh_personality which is loosely defined in panic_abort.
+//
+// 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;
+    }
+
+    // Allocate a new buffer to append the null byte.
+    let size = msg.len() + 1usize;
+    let buf = libc::malloc(size) as *mut libc::c_char;
+    if buf.is_null() {
+        return; // allocation failure
+    }
+    copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len());
+    buf.offset(msg.len() as isize).write(0);
+
+    let func = transmute::<usize, SetAbortMessageType>(func_addr);
+    func(buf);
+}
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index eb2277d8baa..5dcd1e6af36 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -19,6 +19,9 @@
 #![feature(rustc_attrs)]
 #![feature(asm)]
 
+#[cfg(target_os = "android")]
+mod android;
+
 use core::any::Any;
 use core::panic::BoxMeUp;
 
@@ -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! {