On Wed, Jun 03 2026, Rasmus Villemoes <[email protected]> wrote: > On Wed, Jun 03 2026, "Arnd Bergmann" <[email protected]> wrote: > >> On Wed, Jun 3, 2026, at 09:15, Rasmus Villemoes wrote: >>> On Tue, Jun 02 2026, "Arnd Bergmann" <[email protected]> wrote: >>>> On Tue, Jun 2, 2026, at 20:59, Andy Shevchenko wrote: >>>>> On Tue, Jun 02, 2026 at 05:07:05PM +0200, Arnd Bergmann wrote: >>> >>> May I suggest a different approach, that avoids having that extra >>> function emitted (which presumably compiles to a single jump >>> instruction, but still, with retpoline and CFI and all that it all adds >>> up): Keep the declaration of __vsnprintf() in the header without the >>> __print() attribute, but then do >>> >>> int __vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args) >>> __alias(vsnprintf); >>> >>> in vsprintf.c. Aside from reusing the same entry point, I could well >>> imagine a compiler some day complaining about seeing the printf >>> attribute applied in a local extra declaration but not having it in the >>> header file. >>> >>> Presumably it will need its own EXPORT_SYMBOL if any of the intended >>> users are modular, and it certainly still needs a comment. >> >> I had tried that earlier but given up because the attributes have to >> match exactly. >> >> This definition works with all currently supported versions of gcc, >> but may have to change when the there is a new version that adds >> even more attributes: >> >> int >> __printf(3, 0) >> __attribute__((nothrow)) >> __attribute__((nonnull(1))) >> __vsnprintf(char *__restrict buf, size_t size, >> const char * __restrict fmt_str, va_list args) >> __alias(vsnprintf); >> > > Ah, I see. The documentation for the alias attribute does say that the > types have to match, but I didn't know that the nothrow and nonnull > attributes were considered part of the type identity. Oddly enough, if > one does > > typeof(vsnprintf) __vsnprintf __alias(vsnprintf); > > that still fails, but only complains about nothrow, not nonnull. > > I don't remember what minimum gcc we currently require, but gcc 9 > introduced another attribute that is apperently meant for cases like > this: 'copy'. This seems to build: > > diff --git a/lib/vsprintf.c b/lib/vsprintf.c > index 9f359b31c8d1..c1402d375429 100644 > --- a/lib/vsprintf.c > +++ b/lib/vsprintf.c > @@ -2988,6 +2988,9 @@ int vsnprintf(char *buf, size_t size, const char > *fmt_str, va_list args) > } > EXPORT_SYMBOL(vsnprintf); > > +int __vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args) > + __alias(vsnprintf) __attribute__((__copy__(vsnprintf))); > + > /** > * vscnprintf - Format a string and place it in a buffer > * @buf: The buffer to place the result into > > That at least should handle any future "gcc knows this-or-that about the > vsnprintf function". But I don't know if clang supports that copy > mechanism or if the minimum supported gcc is too old.
Ah, so we already have __copy in compiler-attributes.h, stating that it's not supported by clang. Our current minimum gcc version is 8. But judging from the commit message for c0d9782f5, perhaps it's not actually a problem that it just expands to nothing for gcc 8, as the "less restrictive attribute" warning was also introduced with gcc 9, and the __copy macro is already used for module init/exit functions. Which also suggests that it might not be a problem that clang doesn't support it. Rasmus
