summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-11-11 17:05:44 -0500
committerMason Reed <mason@vector35.com>2024-11-11 17:05:44 -0500
commite856d391d377d0a723563925bb0a841ead5ae012 (patch)
tree197df92e0dfc44e1f1e243bf4b35cd08ef8c1cfd /rust
parent911203528b5a5bfc7a98e86ad55b80f7a1385969 (diff)
Add actual logger api to rust
Diffstat (limited to 'rust')
-rw-r--r--rust/Cargo.toml2
-rw-r--r--rust/examples/dwarf/dwarf_export/src/lib.rs4
-rw-r--r--rust/examples/dwarf/dwarf_import/src/lib.rs4
-rw-r--r--rust/examples/idb_import/src/lib.rs3
-rw-r--r--rust/examples/minidump/src/lib.rs3
-rw-r--r--rust/examples/pdb-ng/src/lib.rs5
-rw-r--r--rust/examples/test_demangler/src/lib.rs3
-rw-r--r--rust/examples/workflow/src/lib.rs3
-rw-r--r--rust/src/logger.rs91
9 files changed, 88 insertions, 30 deletions
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 04ccb865..59c71c6b 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -10,7 +10,7 @@ noexports = []
[dependencies]
lazy_static = "1.4.0"
-log = "0.4"
+log = { version = "0.4", features = ["std"] }
libc = "0.2"
rayon = { version = "1.8", optional = true }
binaryninjacore-sys = { path = "binaryninjacore-sys" }
diff --git a/rust/examples/dwarf/dwarf_export/src/lib.rs b/rust/examples/dwarf/dwarf_export/src/lib.rs
index 05592f5f..18cc1e21 100644
--- a/rust/examples/dwarf/dwarf_export/src/lib.rs
+++ b/rust/examples/dwarf/dwarf_export/src/lib.rs
@@ -15,13 +15,13 @@ use binaryninja::{
command::{register, Command},
interaction,
interaction::{FormResponses, FormResponses::Index},
- logger::init,
rc::Ref,
string::BnString,
symbol::SymbolType,
types::{Conf, MemberAccess, StructureType, Type, TypeClass},
};
use log::{error, info, LevelFilter};
+use binaryninja::logger::Logger;
fn export_type(
name: String,
@@ -781,7 +781,7 @@ impl Command for MyCommand {
#[no_mangle]
pub extern "C" fn CorePluginInit() -> bool {
- init(LevelFilter::Debug);
+ Logger::new("DWARF Export").with_level(LevelFilter::Debug).init();
register(
"Export as DWARF",
diff --git a/rust/examples/dwarf/dwarf_import/src/lib.rs b/rust/examples/dwarf/dwarf_import/src/lib.rs
index 20076d0c..b0617ee3 100644
--- a/rust/examples/dwarf/dwarf_import/src/lib.rs
+++ b/rust/examples/dwarf/dwarf_import/src/lib.rs
@@ -42,7 +42,7 @@ use gimli::{constants, CfaRule, DebuggingInformationEntry, Dwarf, DwarfFileType,
use helpers::{get_build_id, load_debug_info_for_build_id};
use log::{debug, error, warn, LevelFilter};
-
+use binaryninja::logger::Logger;
trait ReaderType: Reader<Offset = usize> {}
impl<T: Reader<Offset = usize>> ReaderType for T {}
@@ -658,7 +658,7 @@ impl CustomDebugInfoParser for DWARFParser {
#[no_mangle]
pub extern "C" fn CorePluginInit() -> bool {
- logger::init(LevelFilter::Debug);
+ Logger::new("DWARF").init();
let settings = Settings::new("");
diff --git a/rust/examples/idb_import/src/lib.rs b/rust/examples/idb_import/src/lib.rs
index 0de688be..1faf188c 100644
--- a/rust/examples/idb_import/src/lib.rs
+++ b/rust/examples/idb_import/src/lib.rs
@@ -16,6 +16,7 @@ use idb_rs::til::Type as TILType;
use log::{error, trace, warn, LevelFilter};
use anyhow::Result;
+use binaryninja::logger::Logger;
struct IDBDebugInfoParser;
impl CustomDebugInfoParser for IDBDebugInfoParser {
@@ -337,7 +338,7 @@ fn parse_id0_section_info(
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn CorePluginInit() -> bool {
- logger::init(LevelFilter::Error);
+ Logger::new("IDB Import").with_level(LevelFilter::Error).init();
DebugInfoParser::register("IDB Parser", IDBDebugInfoParser);
DebugInfoParser::register("TIL Parser", TILDebugInfoParser);
true
diff --git a/rust/examples/minidump/src/lib.rs b/rust/examples/minidump/src/lib.rs
index c899591b..62898301 100644
--- a/rust/examples/minidump/src/lib.rs
+++ b/rust/examples/minidump/src/lib.rs
@@ -2,6 +2,7 @@ use binaryninja::binaryview::BinaryView;
use binaryninja::command::{register, Command};
use binaryninja::custombinaryview::register_view_type;
use log::{debug, LevelFilter};
+use binaryninja::logger::Logger;
mod command;
mod view;
@@ -21,7 +22,7 @@ impl Command for PrintMemoryInformationCommand {
#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn CorePluginInit() -> bool {
- binaryninja::logger::init(LevelFilter::Trace);
+ Logger::new("Minidump").with_level(LevelFilter::Trace).init();
debug!("Registering minidump binary view type");
register_view_type("Minidump", "Minidump", view::MinidumpBinaryViewType::new);
diff --git a/rust/examples/pdb-ng/src/lib.rs b/rust/examples/pdb-ng/src/lib.rs
index bc12caae..47eed6ea 100644
--- a/rust/examples/pdb-ng/src/lib.rs
+++ b/rust/examples/pdb-ng/src/lib.rs
@@ -21,7 +21,7 @@ use std::sync::mpsc;
use std::{env, fs};
use anyhow::{anyhow, Result};
-use log::{debug, error, info, LevelFilter};
+use log::{debug, error, info};
use pdb::PDB;
use binaryninja::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt};
@@ -31,6 +31,7 @@ use binaryninja::interaction::{MessageBoxButtonResult, MessageBoxButtonSet};
use binaryninja::settings::Settings;
use binaryninja::string::BnString;
use binaryninja::{add_optional_plugin_dependency, interaction, logger, user_directory};
+use binaryninja::logger::Logger;
use parser::PDBParserInstance;
/// PDB Parser!!
@@ -697,7 +698,7 @@ pub extern "C" fn PDBPluginInit() -> bool {
}
fn init_plugin() -> bool {
- logger::init(LevelFilter::Debug);
+ Logger::new("PDB").init();
DebugInfoParser::register("PDB", PDBParser {});
let settings = Settings::new("");
diff --git a/rust/examples/test_demangler/src/lib.rs b/rust/examples/test_demangler/src/lib.rs
index 6735d5fb..d7dc9eec 100644
--- a/rust/examples/test_demangler/src/lib.rs
+++ b/rust/examples/test_demangler/src/lib.rs
@@ -4,6 +4,7 @@ use binaryninja::binaryview::BinaryView;
use binaryninja::{command, logger};
use binaryninja::command::Command;
use binaryninja::demangle::{Demangler, CustomDemangler};
+use binaryninja::logger::Logger;
use binaryninja::rc::Ref;
use binaryninja::types::{QualifiedName, Type};
@@ -57,7 +58,7 @@ impl Command for DemangleCommand {
#[no_mangle]
pub extern "C" fn CorePluginInit() -> bool {
- logger::init(LevelFilter::Info);
+ Logger::new("Demangle Test").with_level(LevelFilter::Info).init();
Demangler::register("Test", TestDemangler {});
command::register("Demangle Test", "Test", DemangleCommand {});
true
diff --git a/rust/examples/workflow/src/lib.rs b/rust/examples/workflow/src/lib.rs
index 47a8d2c8..6f415941 100644
--- a/rust/examples/workflow/src/lib.rs
+++ b/rust/examples/workflow/src/lib.rs
@@ -3,6 +3,7 @@ use binaryninja::llil::{
};
use binaryninja::workflow::{Activity, AnalysisContext, Workflow};
use log::LevelFilter;
+use binaryninja::logger::Logger;
const RUST_ACTIVITY_NAME: &'static str = "analysis.plugins.rustexample";
const RUST_ACTIVITY_CONFIG: &'static str = r#"{
@@ -55,7 +56,7 @@ fn example_activity(analysis_context: &AnalysisContext) {
#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn CorePluginInit() -> bool {
- binaryninja::logger::init(LevelFilter::Info);
+ Logger::new("Workflow Example").with_level(LevelFilter::Info).init();
log::info!("Initialized the plugin");
diff --git a/rust/src/logger.rs b/rust/src/logger.rs
index 4e9dd1f9..487761e3 100644
--- a/rust/src/logger.rs
+++ b/rust/src/logger.rs
@@ -3,11 +3,11 @@
//! To use logging in your script, do something like:
//!
//! ```no-test
-//! use binaryninja::logger;
+//! use binaryninja::logger::Logger;
//! use log::{info, LevelFilter};
//!
//! fn main() {
-//! logger::init(LevelFilter::Warn).expect("Unable to initialize logger");
+//! Logger::default().init();
//! info!("The logger has been initialized!");
//! // Your code here...
//! }
@@ -16,12 +16,12 @@
//! or
//!
//!```no-test
-//! use binaryninja::logger;
+//! use binaryninja::logger::Logger;
//! use log::{info, LevelFilter};
//!
//! #[no_mangle]
//! pub extern "C" fn CorePluginInit() -> bool {
-//! logger::init(LevelFilter::Warn).expect("Unable to initialize logger");
+//! Logger::new("My Plugin").with_level(LevelFilter::Warn).init();
//! info!("The logger has been initialized!");
//! // Your code here...
//! true
@@ -30,14 +30,73 @@
//!
pub use binaryninjacore_sys::BNLogLevel as Level;
-use binaryninjacore_sys::{BNLogListener, BNUpdateLogListeners};
+use binaryninjacore_sys::{
+ BNFreeLogger, BNLogCreateLogger, BNLogListener, BNLogger, BNLoggerGetName,
+ BNLoggerGetSessionId, BNUpdateLogListeners,
+};
+use crate::string::BnString;
use log;
-use std::ffi::CStr;
+use log::LevelFilter;
+use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};
+use std::ptr::NonNull;
-struct Logger;
-static LOGGER: Logger = Logger;
+const LOGGER_DEFAULT_SESSION_ID: usize = 0;
+
+pub struct Logger {
+ handle: NonNull<BNLogger>,
+ level: LevelFilter,
+}
+
+impl Logger {
+ pub fn new(name: &str) -> Logger {
+ Self::new_with_session(name, LOGGER_DEFAULT_SESSION_ID)
+ }
+
+ pub fn new_with_session(name: &str, session_id: usize) -> Logger {
+ let name_raw = CString::new(name).unwrap();
+ let handle = unsafe { BNLogCreateLogger(name_raw.as_ptr(), session_id) };
+ Logger {
+ handle: NonNull::new(handle).unwrap(),
+ level: LevelFilter::Debug,
+ }
+ }
+
+ pub fn with_level(mut self, level: LevelFilter) -> Logger {
+ self.level = level;
+ self
+ }
+
+ /// Calling this will set the global logger to `self`.
+ ///
+ /// NOTE: There is no guarantee that logs will be sent to BinaryNinja as another log sink
+ /// may have already been initialized beforehand.
+ pub fn init(self) {
+ log::set_max_level(self.level);
+ let _ = log::set_boxed_logger(Box::new(self));
+ }
+
+ pub fn name(&self) -> BnString {
+ unsafe { BnString::from_raw(BNLoggerGetName(self.handle.as_ptr())) }
+ }
+
+ pub fn session_id(&self) -> usize {
+ unsafe { BNLoggerGetSessionId(self.handle.as_ptr()) }
+ }
+}
+
+impl Default for Logger {
+ fn default() -> Self {
+ Logger::new("Default")
+ }
+}
+
+impl Drop for Logger {
+ fn drop(&mut self) {
+ unsafe { BNFreeLogger(self.handle.as_ptr()) };
+ }
+}
impl log::Log for Logger {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
@@ -48,7 +107,6 @@ impl log::Log for Logger {
use self::Level::*;
use binaryninjacore_sys::BNLog;
use log::Level;
- use std::ffi::CString;
let level = match record.level() {
Level::Error => ErrorLog,
@@ -59,11 +117,12 @@ impl log::Log for Logger {
if let Ok(msg) = CString::new(format!("{}", record.args())) {
let percent_s = CString::new("%s").expect("'%s' has no null bytes");
+ let logger_name = self.name();
unsafe {
BNLog(
- 0,
+ self.session_id(),
level,
- std::ptr::null(),
+ logger_name.into_raw(),
0,
percent_s.as_ptr(),
msg.as_ptr(),
@@ -75,14 +134,8 @@ impl log::Log for Logger {
fn flush(&self) {}
}
-/// Uses BinaryNinja's logging functionality as the sink for Rust's `log` crate.
-///
-/// NOTE: There is no guarantee that logs will be sent to BinaryNinja as another log sink
-/// may have already been initialized beforehand.
-pub fn init(filter: log::LevelFilter) {
- log::set_max_level(filter);
- let _ = log::set_logger(&LOGGER);
-}
+unsafe impl Send for Logger {}
+unsafe impl Sync for Logger {}
pub trait LogListener: 'static + Sync {
fn log(&self, session: usize, level: Level, msg: &CStr, logger_name: &CStr, tid: usize);