bpfloader-rs: implement rust native logging am: cbb87b6c97 am: 22020c5f2f
Original change: https://android-review.googlesource.com/c/platform/system/bpf/+/3294153
Change-Id: Ifbea6a19d7e0b40254dc7fa85434abda2f7c4d35
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/loader/Android.bp b/loader/Android.bp
index 1e68f92..c9ea5d0 100644
--- a/loader/Android.bp
+++ b/loader/Android.bp
@@ -113,6 +113,8 @@
],
rustlibs: [
"libbpf_android_bindgen",
+ "libandroid_logger",
+ "liblog_rust",
],
required: [
"timeInState.o",
diff --git a/loader/bpfloader.rs b/loader/bpfloader.rs
index ede1a29..a117f14 100644
--- a/loader/bpfloader.rs
+++ b/loader/bpfloader.rs
@@ -15,19 +15,131 @@
*/
//! BPF loader for system and vendor applications
+use android_logger::AndroidLogger;
+use log::{error, info, Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
+use std::{
+ cmp::max,
+ env,
+ fs::File,
+ io::{LineWriter, Write},
+ os::fd::FromRawFd,
+ panic,
+ sync::{Arc, Mutex},
+};
+
+enum KernelLevel {
+ // Commented out unused due to rust complaining...
+ // EMERG = 0,
+ // ALERT = 1,
+ // CRIT = 2,
+ ERR = 3,
+ WARNING = 4,
+ // NOTICE = 5,
+ INFO = 6,
+ DEBUG = 7,
+}
+
+fn level_to_kern_level(level: &Level) -> u8 {
+ let result = match level {
+ Level::Error => KernelLevel::ERR,
+ Level::Warn => KernelLevel::WARNING,
+ Level::Info => KernelLevel::INFO,
+ Level::Debug => KernelLevel::DEBUG,
+ Level::Trace => KernelLevel::DEBUG,
+ };
+ result as u8
+}
+
+/// A logger implementation to enable bpfloader to write to kmsg on error as
+/// bpfloader runs at early init prior to the availability of standard Android
+/// logging. If a crash were to occur, we can disrupt boot, and therefore we
+/// need the ability to access the logs on the serial port.
+pub struct BpfKmsgLogger {
+ log_level: LevelFilter,
+ tag: String,
+ kmsg_writer: Arc<Mutex<Box<dyn Write + Send>>>,
+ a_logger: AndroidLogger,
+}
+
+impl Log for BpfKmsgLogger {
+ fn enabled(&self, metadata: &Metadata) -> bool {
+ metadata.level() <= self.log_level || self.a_logger.enabled(metadata)
+ }
+
+ fn log(&self, record: &Record) {
+ if !self.enabled(record.metadata()) {
+ return;
+ }
+
+ if record.metadata().level() <= self.log_level {
+ let mut writer = self.kmsg_writer.lock().unwrap();
+ write!(
+ writer,
+ "<{}>{}: {}",
+ level_to_kern_level(&record.level()),
+ self.tag,
+ record.args()
+ )
+ .unwrap();
+ let _ = writer.flush();
+ }
+ self.a_logger.log(record);
+ }
+
+ fn flush(&self) {}
+}
+
+impl BpfKmsgLogger {
+ /// Initialize the logger
+ pub fn init(kmsg_file: File) -> Result<(), SetLoggerError> {
+ let alog_level = LevelFilter::Info;
+ let kmsg_level = LevelFilter::Error;
+
+ let log_config = android_logger::Config::default()
+ .with_tag("BpfLoader-rs")
+ .with_max_level(alog_level)
+ .with_log_buffer(android_logger::LogId::Main)
+ .format(|buf, record| writeln!(buf, "{}", record.args()));
+
+ let writer = Box::new(LineWriter::new(kmsg_file)) as Box<dyn Write + Send>;
+ log::set_max_level(max(alog_level, kmsg_level));
+ log::set_boxed_logger(Box::new(BpfKmsgLogger {
+ log_level: kmsg_level,
+ tag: "BpfLoader-rs".to_string(),
+ kmsg_writer: Arc::new(Mutex::new(writer)),
+ a_logger: AndroidLogger::new(log_config),
+ }))
+ }
+}
#[cfg(enable_libbpf)]
fn load_libbpf_progs() {
// Libbpf loader functionality here.
+ info!("Loading libbpf programs");
}
#[cfg(not(enable_libbpf))]
fn load_libbpf_progs() {
// Empty stub for feature flag disabled case
+ info!("Loading of libbpf programs DISABLED");
}
fn main() {
+ let kmsg_fd = env::var("ANDROID_FILE__dev_kmsg").unwrap().parse::<i32>().unwrap();
+ // SAFETY: The init script opens this file for us
+ let kmsg_file = unsafe { File::from_raw_fd(kmsg_fd) };
+
+ if let Err(logger) = BpfKmsgLogger::init(kmsg_file) {
+ error!("BpfLoader-rs: log::setlogger failed: {}", logger);
+ }
+
+ // Redirect panic messages to both logcat and serial port
+ panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
load_libbpf_progs();
+ info!("Done, loading legacy BPF progs");
// SAFETY: Linking in the existing legacy bpfloader functionality.
// Any of the four following bindgen functions can abort() or exit()