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. Rasmus
