summaryrefslogtreecommitdiffstats
path: root/rust/quote/format.rs
diff options
context:
space:
mode:
authorUlises Mendez Martinez <umendez@google.com>2026-09-04 15:07:09 +0000
committerJosh Poimboeuf <jpoimboe@kernel.org>2026-09-13 18:15:43 -0700
commit7e61560628d17ea6b1d8ee370f6d42694cff8758 (patch)
treee6080164b2f4c4c419894bdb3ce4d956ca9a98c5 /rust/quote/format.rs
downloadlinux-stable-7e61560628d17ea6b1d8ee370f6d42694cff8758.tar.gz
linux-stable-7e61560628d17ea6b1d8ee370f6d42694cff8758.zip
objtool: Validate disassembler headers in libopcodes probegrafted
commit 3f2de814c059 ("objtool: Fix libopcodes linking with static libraries") tested for libopcodes availability by linking a test snippet with a forward declaration of disassemble_init_for_target(). However, testing symbol linkage with an extern declaration only verifies the presence of the library (.so/.a) and bypasses checking for development headers (binutils-dev). On systems where libopcodes is present without development headers installed, the probe succeeds, enabling BUILD_DISAS. Subsequent compilation of objtool then fails: fatal error: 'bfd.h' file not found 113 | #include <bfd.h> Additionally, the probe invokes $(HOSTCC) without $(HOSTCFLAGS), ignoring any sysroot or include flags specified for the host compiler. Fix this by including <bfd.h> and <dis-asm.h> directly in the test snippet, passing $(HOSTCFLAGS) so host compiler options are respected, and defining PACKAGE="objtool" to satisfy the configuration check in <bfd.h>. Fixes: 3f2de814c059 ("objtool: Fix libopcodes linking with static libraries") Fixes: 436326bc525d ("objtool: fix build failure due to missing libopcodes check") Reported-by: Alice Ryhl <aliceryhl@google.com> Assisted-by: Antigravity:Gemini-Next Signed-off-by: Ulises Mendez Martinez <umendez@google.com> Link: https://patch.msgid.link/20260904150710.2997558-1-umendez@google.com Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Diffstat (limited to 'rust/quote/format.rs')
-rw-r--r--rust/quote/format.rs170
1 files changed, 170 insertions, 0 deletions
diff --git a/rust/quote/format.rs b/rust/quote/format.rs
new file mode 100644
index 000000000..6e3d55b6e
--- /dev/null
+++ b/rust/quote/format.rs
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+/// Formatting macro for constructing `Ident`s.
+///
+/// <br>
+///
+/// # Syntax
+///
+/// Syntax is copied from the [`format!`] macro, supporting both positional and
+/// named arguments.
+///
+/// Only a limited set of formatting traits are supported. The current mapping
+/// of format types to traits is:
+///
+/// * `{}` ⇒ [`IdentFragment`]
+/// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)
+/// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)
+/// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)
+/// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)
+///
+/// See [`std::fmt`] for more information.
+///
+/// <br>
+///
+/// # IdentFragment
+///
+/// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by
+/// default. This trait is like `Display`, with a few differences:
+///
+/// * `IdentFragment` is only implemented for a limited set of types, such as
+/// unsigned integers and strings.
+/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
+///
+/// [`IdentFragment`]: crate::IdentFragment
+/// [`Ident`]: proc_macro2::Ident
+///
+/// <br>
+///
+/// # Hygiene
+///
+/// The [`Span`] of the first `Ident` argument is used as the span of the final
+/// identifier, falling back to [`Span::call_site`] when no identifiers are
+/// provided.
+///
+/// ```
+/// # use quote::format_ident;
+/// # let ident = format_ident!("Ident");
+/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
+/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
+/// assert_eq!(my_ident, "MyIdentIsCool");
+/// ```
+///
+/// Alternatively, the span can be overridden by passing the `span` named
+/// argument.
+///
+/// ```
+/// # use quote::format_ident;
+/// # const IGNORE_TOKENS: &'static str = stringify! {
+/// let my_span = /* ... */;
+/// # };
+/// # let my_span = proc_macro2::Span::call_site();
+/// format_ident!("MyIdent", span = my_span);
+/// ```
+///
+/// [`Span`]: proc_macro2::Span
+/// [`Span::call_site`]: proc_macro2::Span::call_site
+///
+/// <p><br></p>
+///
+/// # Panics
+///
+/// This method will panic if the resulting formatted string is not a valid
+/// identifier.
+///
+/// <br>
+///
+/// # Examples
+///
+/// Composing raw and non-raw identifiers:
+/// ```
+/// # use quote::format_ident;
+/// let my_ident = format_ident!("My{}", "Ident");
+/// assert_eq!(my_ident, "MyIdent");
+///
+/// let raw = format_ident!("r#Raw");
+/// assert_eq!(raw, "r#Raw");
+///
+/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
+/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
+/// ```
+///
+/// Integer formatting options:
+/// ```
+/// # use quote::format_ident;
+/// let num: u32 = 10;
+///
+/// let decimal = format_ident!("Id_{}", num);
+/// assert_eq!(decimal, "Id_10");
+///
+/// let octal = format_ident!("Id_{:o}", num);
+/// assert_eq!(octal, "Id_12");
+///
+/// let binary = format_ident!("Id_{:b}", num);
+/// assert_eq!(binary, "Id_1010");
+///
+/// let lower_hex = format_ident!("Id_{:x}", num);
+/// assert_eq!(lower_hex, "Id_a");
+///
+/// let upper_hex = format_ident!("Id_{:X}", num);
+/// assert_eq!(upper_hex, "Id_A");
+/// ```
+#[macro_export]
+macro_rules! format_ident {
+ ($fmt:expr) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::None,
+ $fmt
+ ])
+ };
+
+ ($fmt:expr, $($rest:tt)*) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::None,
+ $fmt
+ ] $($rest)*)
+ };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! format_ident_impl {
+ // Final state
+ ([$span:expr, $($fmt:tt)*]) => {
+ $crate::__private::mk_ident(
+ &$crate::__private::format!($($fmt)*),
+ $span,
+ )
+ };
+
+ // Span argument
+ ([$old:expr, $($fmt:tt)*] span = $span:expr) => {
+ $crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
+ };
+ ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::Some::<$crate::__private::Span>($span),
+ $($fmt)*
+ ] $($rest)*)
+ };
+
+ // Named argument
+ ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
+ $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
+ };
+ ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
+ match $crate::__private::IdentFragmentAdapter(&$arg) {
+ arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
+ }
+ };
+
+ // Positional argument
+ ([$span:expr, $($fmt:tt)*] $arg:expr) => {
+ $crate::format_ident_impl!([$span, $($fmt)*] $arg,)
+ };
+ ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
+ match $crate::__private::IdentFragmentAdapter(&$arg) {
+ arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
+ }
+ };
+}