1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci//! panic handler for Rust. 17800b99b8Sopenharmony_ci#![feature(rustc_private)] 18800b99b8Sopenharmony_ciextern crate hisysevent; 19800b99b8Sopenharmony_ciextern crate libc; 20800b99b8Sopenharmony_ciextern crate stacktrace_rust; 21800b99b8Sopenharmony_ciuse std::ffi::CString; 22800b99b8Sopenharmony_ciuse std::fs; 23800b99b8Sopenharmony_ciuse std::os::raw::{c_char}; 24800b99b8Sopenharmony_ciuse std::panic; 25800b99b8Sopenharmony_ciuse std::panic::PanicInfo; 26800b99b8Sopenharmony_ciuse std::process; 27800b99b8Sopenharmony_ciuse std::time::{UNIX_EPOCH, SystemTime}; 28800b99b8Sopenharmony_ciuse hilog_rust::{error, hilog, HiLogLabel, LogType}; 29800b99b8Sopenharmony_ciuse hisysevent::{EventType}; 30800b99b8Sopenharmony_ci 31800b99b8Sopenharmony_ciconst LOG_LABEL: HiLogLabel = HiLogLabel { 32800b99b8Sopenharmony_ci log_type: LogType::LogCore, 33800b99b8Sopenharmony_ci domain: 0xD002D11, 34800b99b8Sopenharmony_ci tag: "DfxFaultLogger" 35800b99b8Sopenharmony_ci}; 36800b99b8Sopenharmony_ci 37800b99b8Sopenharmony_ci/// panic handler 38800b99b8Sopenharmony_cifn panic_handler() { 39800b99b8Sopenharmony_ci panic::set_hook(Box::new(move |info| { 40800b99b8Sopenharmony_ci report_info_handler(info) 41800b99b8Sopenharmony_ci })); 42800b99b8Sopenharmony_ci} 43800b99b8Sopenharmony_ci 44800b99b8Sopenharmony_cifn read_process_name(pid: u32) -> String { 45800b99b8Sopenharmony_ci let path = format!("/proc/{}/cmdline", pid); 46800b99b8Sopenharmony_ci let binding = fs::read_to_string(path).unwrap(); 47800b99b8Sopenharmony_ci let mut process_name = binding.as_str(); 48800b99b8Sopenharmony_ci if process_name.find('\0').is_some() { 49800b99b8Sopenharmony_ci (process_name, _) = process_name.split_at(process_name.find('\0').unwrap()); 50800b99b8Sopenharmony_ci } 51800b99b8Sopenharmony_ci if process_name.rfind('/').is_some() { 52800b99b8Sopenharmony_ci (_, process_name) = process_name.split_at(process_name.rfind('/').unwrap() + 1); 53800b99b8Sopenharmony_ci } 54800b99b8Sopenharmony_ci process_name.to_string() 55800b99b8Sopenharmony_ci} 56800b99b8Sopenharmony_ci 57800b99b8Sopenharmony_cifn read_thread_name(pid: u32) -> String { 58800b99b8Sopenharmony_ci let path = format!("/proc/{}/comm", pid); 59800b99b8Sopenharmony_ci fs::read_to_string(path).unwrap() 60800b99b8Sopenharmony_ci} 61800b99b8Sopenharmony_ci 62800b99b8Sopenharmony_ci#[allow(unused_variables)] 63800b99b8Sopenharmony_cifn report_info_handler(info: &PanicInfo) { 64800b99b8Sopenharmony_ci let (file, line) = info.location().map(|loc| (loc.file(), loc.line())).unwrap_or(("<unknown>", 0)); 65800b99b8Sopenharmony_ci let errmsg = match info.payload().downcast_ref::<&'static str>() { 66800b99b8Sopenharmony_ci Some(s) => *s, 67800b99b8Sopenharmony_ci None => match info.payload().downcast_ref::<String>() { 68800b99b8Sopenharmony_ci Some(s) => &**s, 69800b99b8Sopenharmony_ci None => "Box<Any>", 70800b99b8Sopenharmony_ci }, 71800b99b8Sopenharmony_ci }; 72800b99b8Sopenharmony_ci 73800b99b8Sopenharmony_ci let pid = process::id(); 74800b99b8Sopenharmony_ci let process_name = read_process_name(pid); 75800b99b8Sopenharmony_ci let thread_name = read_thread_name(pid); 76800b99b8Sopenharmony_ci let panic_reason = format!("file:{} line:{} message:{}", file, line, errmsg); 77800b99b8Sopenharmony_ci let thread_label = format!("Thread name:{}{}", thread_name, stacktrace_rust::get_trace(true).as_str()); 78800b99b8Sopenharmony_ci let happen_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); 79800b99b8Sopenharmony_ci let ret = hisysevent::write( 80800b99b8Sopenharmony_ci "RELIABILITY", 81800b99b8Sopenharmony_ci "RUST_PANIC", 82800b99b8Sopenharmony_ci EventType::Fault, 83800b99b8Sopenharmony_ci &[hisysevent::build_str_param!("MODULE", process_name.as_str()), 84800b99b8Sopenharmony_ci hisysevent::build_str_param!("REASON", panic_reason.as_str()), 85800b99b8Sopenharmony_ci hisysevent::build_number_param!("PID", pid), 86800b99b8Sopenharmony_ci hisysevent::build_number_param!("TID", unsafe { libc::gettid() }), 87800b99b8Sopenharmony_ci hisysevent::build_number_param!("UID", unsafe { libc::getuid() }), 88800b99b8Sopenharmony_ci hisysevent::build_str_param!("SUMMARY", thread_label.as_str()), 89800b99b8Sopenharmony_ci hisysevent::build_number_param!("HAPPEN_TIME", happen_time) 90800b99b8Sopenharmony_ci ] 91800b99b8Sopenharmony_ci ); 92800b99b8Sopenharmony_ci if ret != 0 { 93800b99b8Sopenharmony_ci error!(LOG_LABEL, "RUST_PANIC hisysevent write failed"); 94800b99b8Sopenharmony_ci } 95800b99b8Sopenharmony_ci} 96800b99b8Sopenharmony_ci 97800b99b8Sopenharmony_ci/// Initializes the panic hook 98800b99b8Sopenharmony_cipub fn init() { 99800b99b8Sopenharmony_ci panic_handler(); 100800b99b8Sopenharmony_ci}