lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Y208lVCN3VweD5iI@Boquns-Mac-mini.local>
Date:   Thu, 10 Nov 2022 10:01:57 -0800
From:   Boqun Feng <boqun.feng@...il.com>
To:     Miguel Ojeda <ojeda@...nel.org>
Cc:     Wedson Almeida Filho <wedsonaf@...il.com>,
        Alex Gaynor <alex.gaynor@...il.com>,
        Gary Guo <gary@...yguo.net>,
        Björn Roy Baron <bjorn3_gh@...tonmail.com>,
        rust-for-linux@...r.kernel.org, linux-kernel@...r.kernel.org,
        patches@...ts.linux.dev, Niklas Mohrin <dev@...lasmohrin.de>
Subject: Re: [PATCH v1 23/28] rust: std_vendor: add `dbg!` macro based on
 `std`'s one

On Thu, Nov 10, 2022 at 05:41:35PM +0100, Miguel Ojeda wrote:
> From: Niklas Mohrin <dev@...lasmohrin.de>
> 
> The Rust standard library has a really handy macro, `dbg!` [1,2].
> It prints the source location (filename and line) along with the raw
> source code that is invoked with and the `Debug` representation
> of the given expression, e.g.:
> 
>     let a = 2;
>     let b = dbg!(a * 2) + 1;
>     //      ^-- prints: [src/main.rs:2] a * 2 = 4
>     assert_eq!(b, 5);
> 
> Port the macro over to the `kernel` crate, using `pr_info!`
> instead of `eprintln!`, inside a new module called `std_vendor`.
> 

I got confused when I saw `dbg!` uses `pr_info` instead of `pr_debug`,
but then I saw the discussion:

	https://github.com/Rust-for-Linux/linux/pull/483#discussion_r689881969

and I'm almost convinced ;-) Better add the gist of discussion into
comment/document/commit log? Users need to know when to use `dbg!` and
when to use `pr_debug!`, right?

Regards,
Boqun

> Since the source code for the macro is taken from the standard
> library source (with only minor adjustments), the new file is
> licensed under `Apache 2.0 OR MIT`, just like the original [3,4].
> 
> Link: https://doc.rust-lang.org/std/macro.dbg.html [1]
> Link: https://github.com/rust-lang/rust/blob/master/library/std/src/macros.rs#L212 [2]
> Link: https://github.com/rust-lang/rust/blob/master/library/std/Cargo.toml [3]
> Link: https://github.com/rust-lang/rust/blob/master/COPYRIGHT [4]
> Signed-off-by: Niklas Mohrin <dev@...lasmohrin.de>
> [Reworded, adapted for upstream and applied latest changes]
> Signed-off-by: Miguel Ojeda <ojeda@...nel.org>
> ---
>  rust/kernel/lib.rs        |   2 +
>  rust/kernel/prelude.rs    |   2 +-
>  rust/kernel/std_vendor.rs | 160 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 163 insertions(+), 1 deletion(-)
>  create mode 100644 rust/kernel/std_vendor.rs
> 
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index ffc6626a6d29..d6371c9c8453 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -26,6 +26,8 @@ mod allocator;
>  pub mod error;
>  pub mod prelude;
>  pub mod print;
> +#[doc(hidden)]
> +pub mod std_vendor;
>  pub mod str;
>  
>  #[doc(hidden)]
> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
> index 89c2c9f4e7a7..345fc9075d1f 100644
> --- a/rust/kernel/prelude.rs
> +++ b/rust/kernel/prelude.rs
> @@ -17,7 +17,7 @@ pub use alloc::{boxed::Box, vec::Vec};
>  
>  pub use macros::{module, vtable};
>  
> -pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
> +pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
>  
>  pub use super::error::{code::*, Error, Result};
>  
> diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs
> new file mode 100644
> index 000000000000..da57b4e521f4
> --- /dev/null
> +++ b/rust/kernel/std_vendor.rs
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: Apache-2.0 OR MIT
> +
> +//! The contents of this file come from the Rust standard library, hosted in
> +//! the <https://github.com/rust-lang/rust> repository, licensed under
> +//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,
> +//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.
> +
> +/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`].
> +///
> +/// Prints and returns the value of a given expression for quick and dirty
> +/// debugging.
> +///
> +/// An example:
> +///
> +/// ```rust
> +/// let a = 2;
> +/// # #[allow(clippy::dbg_macro)]
> +/// let b = dbg!(a * 2) + 1;
> +/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
> +/// assert_eq!(b, 5);
> +/// ```
> +///
> +/// The macro works by using the `Debug` implementation of the type of
> +/// the given expression to print the value with [`printk`] along with the
> +/// source location of the macro invocation as well as the source code
> +/// of the expression.
> +///
> +/// Invoking the macro on an expression moves and takes ownership of it
> +/// before returning the evaluated expression unchanged. If the type
> +/// of the expression does not implement `Copy` and you don't want
> +/// to give up ownership, you can instead borrow with `dbg!(&expr)`
> +/// for some expression `expr`.
> +///
> +/// The `dbg!` macro works exactly the same in release builds.
> +/// This is useful when debugging issues that only occur in release
> +/// builds or when debugging in release mode is significantly faster.
> +///
> +/// Note that the macro is intended as a debugging tool and therefore you
> +/// should avoid having uses of it in version control for long periods
> +/// (other than in tests and similar).
> +///
> +/// # Stability
> +///
> +/// The exact output printed by this macro should not be relied upon
> +/// and is subject to future changes.
> +///
> +/// # Further examples
> +///
> +/// With a method call:
> +///
> +/// ```rust
> +/// # #[allow(clippy::dbg_macro)]
> +/// fn foo(n: usize) {
> +///     if dbg!(n.checked_sub(4)).is_some() {
> +///         // ...
> +///     }
> +/// }
> +///
> +/// foo(3)
> +/// ```
> +///
> +/// This prints to the kernel log:
> +///
> +/// ```text,ignore
> +/// [src/main.rs:4] n.checked_sub(4) = None
> +/// ```
> +///
> +/// Naive factorial implementation:
> +///
> +/// ```rust
> +/// # #[allow(clippy::dbg_macro)]
> +/// # {
> +/// fn factorial(n: u32) -> u32 {
> +///     if dbg!(n <= 1) {
> +///         dbg!(1)
> +///     } else {
> +///         dbg!(n * factorial(n - 1))
> +///     }
> +/// }
> +///
> +/// dbg!(factorial(4));
> +/// # }
> +/// ```
> +///
> +/// This prints to the kernel log:
> +///
> +/// ```text,ignore
> +/// [src/main.rs:3] n <= 1 = false
> +/// [src/main.rs:3] n <= 1 = false
> +/// [src/main.rs:3] n <= 1 = false
> +/// [src/main.rs:3] n <= 1 = true
> +/// [src/main.rs:4] 1 = 1
> +/// [src/main.rs:5] n * factorial(n - 1) = 2
> +/// [src/main.rs:5] n * factorial(n - 1) = 6
> +/// [src/main.rs:5] n * factorial(n - 1) = 24
> +/// [src/main.rs:11] factorial(4) = 24
> +/// ```
> +///
> +/// The `dbg!(..)` macro moves the input:
> +///
> +/// ```ignore
> +/// /// A wrapper around `usize` which importantly is not Copyable.
> +/// #[derive(Debug)]
> +/// struct NoCopy(usize);
> +///
> +/// let a = NoCopy(42);
> +/// let _ = dbg!(a); // <-- `a` is moved here.
> +/// let _ = dbg!(a); // <-- `a` is moved again; error!
> +/// ```
> +///
> +/// You can also use `dbg!()` without a value to just print the
> +/// file and line whenever it's reached.
> +///
> +/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
> +/// a tuple (and return it, too):
> +///
> +/// ```
> +/// # #[allow(clippy::dbg_macro)]
> +/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
> +/// ```
> +///
> +/// However, a single argument with a trailing comma will still not be treated
> +/// as a tuple, following the convention of ignoring trailing commas in macro
> +/// invocations. You can use a 1-tuple directly if you need one:
> +///
> +/// ```
> +/// # #[allow(clippy::dbg_macro)]
> +/// # {
> +/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
> +/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
> +/// # }
> +/// ```
> +///
> +/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html
> +/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html
> +/// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html
> +#[macro_export]
> +macro_rules! dbg {
> +    // NOTE: We cannot use `concat!` to make a static string as a format argument
> +    // of `pr_info!` because `file!` could contain a `{` or
> +    // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!`
> +    // will be malformed.
> +    () => {
> +        $crate::pr_info!("[{}:{}]\n", ::core::file!(), ::core::line!())
> +    };
> +    ($val:expr $(,)?) => {
> +        // Use of `match` here is intentional because it affects the lifetimes
> +        // of temporaries - https://stackoverflow.com/a/48732525/1063961
> +        match $val {
> +            tmp => {
> +                $crate::pr_info!("[{}:{}] {} = {:#?}\n",
> +                    ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp);
> +                tmp
> +            }
> +        }
> +    };
> +    ($($val:expr),+ $(,)?) => {
> +        ($($crate::dbg!($val)),+,)
> +    };
> +}
> -- 
> 2.38.1
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ