From: Andrew Morton <akpm@linux-foundation.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linuxppc-dev@ozlabs.org, linux-ia64@vger.kernel.org,
"David S. Miller" <davem@davemloft.net>,
Peter Anvin <hpa@zytor.com>
Subject: Re: the printk problem
Date: Fri, 04 Jul 2008 20:27:16 +0000 [thread overview]
Message-ID: <20080704132716.f1e12554.akpm@linux-foundation.org> (raw)
In-Reply-To: <alpine.LFD.1.10.0807041250220.2815@woody.linux-foundation.org>
On Fri, 4 Jul 2008 13:02:05 -0700 (PDT) Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
>
> On Fri, 4 Jul 2008, Linus Torvalds wrote:
> >
> > so I think we could easily just say that we extend %p in various ways:
> >
> > - %pS - print pointer as a symbol
> >
> > and leave tons of room for future extensions for different kinds of
> > pointers.
>
> So here's a totally untested example patch of this, which could probably
> easily be extended to to other things.
>
> I actually made it '%pF' and '%pS' for a Function descriptor pointer and
> normal Symbolic pointer respectively, because of the stupid things ia64
> and PPC64 do with the pointer indirection through function descriptors.
>
> That function descriptor indirection is totally untested, and I did it
> with a
>
> pagefault_disable();
> __get_user(..)
> pagefault_enable();
>
> thing because I thought it would be nice if printk() was always safe, and
> passing bogus function pointers to '%pF' should try to work, but quite
> frankly, I didn't even check that that part compiles, much less works.
probe_kernel_address() should be usable here.
> ia64/ppc lists cc'd, just in case somebody wants to test this.
>
> NOTE! There are no current actual users of this, but the _idea_ is that we
> should be able to just do
>
> printk("%pF\n", desc->handle_irq);
>
> instead of using
>
> print_symbol("%s\n", (unsigned long)desc->handle_irq);
>
> The latter is from kernel/irq/internals.h, and actually looks incorrect -
> shouldn't it use print_fn_descriptor_symbol(), since it's a C level
> function pointer? We should use "print_symbol()" for return pointers we
> find on the stack and data pointers, but not for stuff that actually has a
> C type that is a function pointer?
>
> Somebody who cares about the insane function descriptors should take a
> deeper look.
>
> NOTE AGAIN! UNTESTED! I could easily have screwed up printk() _entirely_,
> since I had to factor out the string handling into a function of its own.
>
> Linus
> ---
> lib/vsprintf.c | 102 ++++++++++++++++++++++++++++++++++++++++---------------
> 1 files changed, 74 insertions(+), 28 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 6021757..148b656 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -22,6 +22,7 @@
> #include <linux/string.h>
> #include <linux/ctype.h>
> #include <linux/kernel.h>
> +#include <linux/kallsyms.h>
>
> #include <asm/page.h> /* for PAGE_SIZE */
> #include <asm/div64.h>
> @@ -482,6 +483,72 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
> return buf;
> }
>
> +static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
> +{
> + int len, i;
> +
> + if ((unsigned long)s < PAGE_SIZE)
> + s = "<NULL>";
hm, is that needed for other reasons than "it will fault"?
otherwise we could walk the whole string with probe_kernel_address()
before we do anything with it.
That's slightly racy against vunmap and CONFIG_DEBUG_PAGEALLOC and
stuff. Fixable by *never* dereferencing that pointer except via
probe_kernel_address().
> + len = strnlen(s, precision);
> +
> + if (!(flags & LEFT)) {
> + while (len < field_width--) {
> + if (buf < end)
> + *buf = ' ';
> + ++buf;
> + }
> + }
> + for (i = 0; i < len; ++i) {
> + if (buf < end)
> + *buf = *s;
> + ++buf; ++s;
> + }
> + while (len < field_width--) {
> + if (buf < end)
> + *buf = ' ';
> + ++buf;
> + }
> + return buf;
> +}
> +
> +/*
> + * Show a '%p' thing. A kernel extension is that the '%p' is followed
> + * by an extra set of alphanumeric characters that are extended format
> + * specifiers. Right now we just handle 'F' (for symbolic Function
> + * pointers) and 'S' (for Symbolic data pointers), but this can easily
> + * be extended in the future (network address types etc).
> + *
> + * The difference between 'S' and 'F' is that on ia64 and ppc64 function
> + * pointers are really function descriptors, which contain a pointer the
> + * real address.
> + */
> +static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int base, int size, int precision, int type)
> +{
> + char sym[KSYM_SYMBOL_LEN];
> + switch (*fmt) {
> + case 'F': /* Function pointer */
> +#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
> + { void *p;
> + pagefault_disable();
> + if (!__get_user((void **)ptr, &p))
> + ptr = p;
> + pagefault_enable();
> + }
> +#endif
> + /* Fallthrough */
> + case 'S': /* Other pointer */
> +#if CONFIG_KALLSYMS
> + sprint_symbol(sym, (unsigned long) ptr);
> + return string(buf, end, sym, size, precision, type);
> +#else
> + type |= SPECIAL;
> + break;
> +#endif
> + }
> + return number(buf, end, (unsigned long long) ptr, base, size, precision, type);
> +}
If this takes off we might want a register-your-printk-handler
interface. Maybe.
We also jump through hoops to print things like sector_t and
resource_size_t. They always need to be cast to `unsiged long long',
which generates additional stack space and text in some setups.
And then there's the perennial "need to cast u64 to unsigned long long
to print it". If we were to do
printk("%SL", (void *)some_u64);
then that's still bloody ugly, but it'll save a little text-n-stack.
WARNING: multiple messages have this Message-ID (diff)
From: Andrew Morton <akpm@linux-foundation.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linuxppc-dev@ozlabs.org, linux-ia64@vger.kernel.org,
"David S. Miller" <davem@davemloft.net>,
Peter Anvin <hpa@zytor.com>
Subject: Re: the printk problem
Date: Fri, 4 Jul 2008 13:27:16 -0700 [thread overview]
Message-ID: <20080704132716.f1e12554.akpm@linux-foundation.org> (raw)
In-Reply-To: <alpine.LFD.1.10.0807041250220.2815@woody.linux-foundation.org>
On Fri, 4 Jul 2008 13:02:05 -0700 (PDT) Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
>
> On Fri, 4 Jul 2008, Linus Torvalds wrote:
> >
> > so I think we could easily just say that we extend %p in various ways:
> >
> > - %pS - print pointer as a symbol
> >
> > and leave tons of room for future extensions for different kinds of
> > pointers.
>
> So here's a totally untested example patch of this, which could probably
> easily be extended to to other things.
>
> I actually made it '%pF' and '%pS' for a Function descriptor pointer and
> normal Symbolic pointer respectively, because of the stupid things ia64
> and PPC64 do with the pointer indirection through function descriptors.
>
> That function descriptor indirection is totally untested, and I did it
> with a
>
> pagefault_disable();
> __get_user(..)
> pagefault_enable();
>
> thing because I thought it would be nice if printk() was always safe, and
> passing bogus function pointers to '%pF' should try to work, but quite
> frankly, I didn't even check that that part compiles, much less works.
probe_kernel_address() should be usable here.
> ia64/ppc lists cc'd, just in case somebody wants to test this.
>
> NOTE! There are no current actual users of this, but the _idea_ is that we
> should be able to just do
>
> printk("%pF\n", desc->handle_irq);
>
> instead of using
>
> print_symbol("%s\n", (unsigned long)desc->handle_irq);
>
> The latter is from kernel/irq/internals.h, and actually looks incorrect -
> shouldn't it use print_fn_descriptor_symbol(), since it's a C level
> function pointer? We should use "print_symbol()" for return pointers we
> find on the stack and data pointers, but not for stuff that actually has a
> C type that is a function pointer?
>
> Somebody who cares about the insane function descriptors should take a
> deeper look.
>
> NOTE AGAIN! UNTESTED! I could easily have screwed up printk() _entirely_,
> since I had to factor out the string handling into a function of its own.
>
> Linus
> ---
> lib/vsprintf.c | 102 ++++++++++++++++++++++++++++++++++++++++---------------
> 1 files changed, 74 insertions(+), 28 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 6021757..148b656 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -22,6 +22,7 @@
> #include <linux/string.h>
> #include <linux/ctype.h>
> #include <linux/kernel.h>
> +#include <linux/kallsyms.h>
>
> #include <asm/page.h> /* for PAGE_SIZE */
> #include <asm/div64.h>
> @@ -482,6 +483,72 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
> return buf;
> }
>
> +static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
> +{
> + int len, i;
> +
> + if ((unsigned long)s < PAGE_SIZE)
> + s = "<NULL>";
hm, is that needed for other reasons than "it will fault"?
otherwise we could walk the whole string with probe_kernel_address()
before we do anything with it.
That's slightly racy against vunmap and CONFIG_DEBUG_PAGEALLOC and
stuff. Fixable by *never* dereferencing that pointer except via
probe_kernel_address().
> + len = strnlen(s, precision);
> +
> + if (!(flags & LEFT)) {
> + while (len < field_width--) {
> + if (buf < end)
> + *buf = ' ';
> + ++buf;
> + }
> + }
> + for (i = 0; i < len; ++i) {
> + if (buf < end)
> + *buf = *s;
> + ++buf; ++s;
> + }
> + while (len < field_width--) {
> + if (buf < end)
> + *buf = ' ';
> + ++buf;
> + }
> + return buf;
> +}
> +
> +/*
> + * Show a '%p' thing. A kernel extension is that the '%p' is followed
> + * by an extra set of alphanumeric characters that are extended format
> + * specifiers. Right now we just handle 'F' (for symbolic Function
> + * pointers) and 'S' (for Symbolic data pointers), but this can easily
> + * be extended in the future (network address types etc).
> + *
> + * The difference between 'S' and 'F' is that on ia64 and ppc64 function
> + * pointers are really function descriptors, which contain a pointer the
> + * real address.
> + */
> +static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int base, int size, int precision, int type)
> +{
> + char sym[KSYM_SYMBOL_LEN];
> + switch (*fmt) {
> + case 'F': /* Function pointer */
> +#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
> + { void *p;
> + pagefault_disable();
> + if (!__get_user((void **)ptr, &p))
> + ptr = p;
> + pagefault_enable();
> + }
> +#endif
> + /* Fallthrough */
> + case 'S': /* Other pointer */
> +#if CONFIG_KALLSYMS
> + sprint_symbol(sym, (unsigned long) ptr);
> + return string(buf, end, sym, size, precision, type);
> +#else
> + type |= SPECIAL;
> + break;
> +#endif
> + }
> + return number(buf, end, (unsigned long long) ptr, base, size, precision, type);
> +}
If this takes off we might want a register-your-printk-handler
interface. Maybe.
We also jump through hoops to print things like sector_t and
resource_size_t. They always need to be cast to `unsiged long long',
which generates additional stack space and text in some setups.
And then there's the perennial "need to cast u64 to unsigned long long
to print it". If we were to do
printk("%SL", (void *)some_u64);
then that's still bloody ugly, but it'll save a little text-n-stack.
next prev parent reply other threads:[~2008-07-04 20:27 UTC|newest]
Thread overview: 111+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-25 13:11 [PATCH] handle failure of irqchip->set_type in setup_irq Uwe Kleine-König
2008-07-02 9:17 ` Uwe Kleine-König
2008-07-02 9:49 ` Andrew Morton
2008-07-02 10:09 ` Uwe Kleine-König
2008-07-04 10:46 ` [PATCH v2] " Uwe Kleine-König
2008-07-04 17:17 ` Andrew Morton
2008-07-04 18:43 ` Uwe Kleine-König
2008-07-04 19:08 ` Andrew Morton
2008-07-09 13:13 ` Uwe Kleine-König
2008-07-09 21:52 ` Andrew Morton
2008-07-10 8:23 ` Uwe Kleine-König
2008-07-10 8:28 ` Andrew Morton
[not found] ` <20080704111540.ddffd241.akpm@linux-foundation.org>
[not found] ` <alpine.LFD.1.10.0807041147450.2815@woody.linux-foundation.org>
2008-07-04 20:02 ` the printk problem Linus Torvalds
2008-07-04 20:02 ` Linus Torvalds
2008-07-04 20:27 ` Andrew Morton [this message]
2008-07-04 20:27 ` Andrew Morton
2008-07-04 20:41 ` Linus Torvalds
2008-07-04 20:41 ` Linus Torvalds
2008-07-04 20:42 ` Matthew Wilcox
2008-07-04 20:42 ` Matthew Wilcox
2008-07-04 22:01 ` Andrew Morton
2008-07-04 22:01 ` Andrew Morton
2008-07-04 22:01 ` Andrew Morton
2008-07-05 2:03 ` Matthew Wilcox
2008-07-05 2:03 ` Matthew Wilcox
2008-07-05 2:03 ` Matthew Wilcox
2008-07-22 10:05 ` [PATCH] Make u64 long long on all architectures (was: the printk problem) Andrew Morton
2008-07-22 10:05 ` Andrew Morton
2008-07-22 10:05 ` [PATCH] Make u64 long long on all architectures (was: the Andrew Morton
2008-07-22 10:36 ` [PATCH] Make u64 long long on all architectures (was: the printk problem) Michael Ellerman
2008-07-22 10:36 ` Michael Ellerman
2008-07-22 10:36 ` [PATCH] Make u64 long long on all architectures (was: the Michael Ellerman
2008-07-22 10:53 ` [PATCH] Make u64 long long on all architectures (was: the printk problem) Andrew Morton
2008-07-22 10:53 ` Andrew Morton
2008-07-22 10:53 ` [PATCH] Make u64 long long on all architectures (was: the Andrew Morton
2008-07-22 11:36 ` [PATCH] Make u64 long long on all architectures (was: the printk problem) Benjamin Herrenschmidt
2008-07-22 11:36 ` Benjamin Herrenschmidt
2008-07-22 11:36 ` [PATCH] Make u64 long long on all architectures (was: the Benjamin Herrenschmidt
2008-07-22 11:35 ` [PATCH] Make u64 long long on all architectures (was: the printk problem) Benjamin Herrenschmidt
2008-07-22 11:35 ` Benjamin Herrenschmidt
2008-07-22 11:35 ` [PATCH] Make u64 long long on all architectures (was: the Benjamin Herrenschmidt
2008-07-05 10:20 ` the printk problem Denys Vlasenko
2008-07-05 10:20 ` Denys Vlasenko
2008-07-05 10:20 ` Denys Vlasenko
2008-07-05 11:33 ` Jan Engelhardt
2008-07-05 11:33 ` Jan Engelhardt
2008-07-05 11:33 ` Jan Engelhardt
2008-07-04 22:58 ` Benjamin Herrenschmidt
2008-07-04 22:58 ` Benjamin Herrenschmidt
2008-07-04 20:36 ` Matthew Wilcox
2008-07-04 20:36 ` Matthew Wilcox
2008-07-08 1:44 ` Kyle McMartin
2008-07-08 1:44 ` Kyle McMartin
2008-07-04 23:00 ` Benjamin Herrenschmidt
2008-07-04 23:00 ` Benjamin Herrenschmidt
2008-07-04 23:25 ` Linus Torvalds
2008-07-04 23:25 ` Linus Torvalds
2008-07-05 22:32 ` Linus Torvalds
2008-07-05 22:32 ` Linus Torvalds
2008-07-05 22:57 ` Arjan van de Ven
2008-07-05 22:57 ` Arjan van de Ven
2008-07-06 5:27 ` Ingo Molnar
2008-07-06 5:27 ` Ingo Molnar
2008-07-06 5:37 ` Linus Torvalds
2008-07-06 5:37 ` Linus Torvalds
2008-07-06 5:37 ` Linus Torvalds
2008-07-06 5:53 ` Ingo Molnar
2008-07-06 5:53 ` Ingo Molnar
2008-07-06 5:53 ` Ingo Molnar
2008-07-06 6:13 ` Ingo Molnar
2008-07-06 6:13 ` Ingo Molnar
2008-07-06 6:13 ` Ingo Molnar
2008-07-07 1:14 ` Benjamin Herrenschmidt
2008-07-07 1:14 ` Benjamin Herrenschmidt
2008-07-07 3:26 ` Stephen Rothwell
2008-07-07 3:28 ` Michael Ellerman
2008-07-07 4:59 ` Stephen Rothwell
2008-07-07 3:43 ` Benjamin Herrenschmidt
2008-07-05 12:52 ` Vegard Nossum
2008-07-05 12:52 ` Vegard Nossum
2008-07-05 12:52 ` Vegard Nossum
2008-07-05 13:24 ` Jan Engelhardt
2008-07-05 13:24 ` Jan Engelhardt
2008-07-05 13:24 ` Jan Engelhardt
2008-07-05 13:50 ` Vegard Nossum
2008-07-05 13:50 ` Vegard Nossum
2008-07-05 13:50 ` Vegard Nossum
2008-07-05 14:07 ` Jan Engelhardt
2008-07-05 14:07 ` Jan Engelhardt
2008-07-05 14:07 ` Jan Engelhardt
2008-07-05 17:56 ` Linus Torvalds
2008-07-05 17:56 ` Linus Torvalds
2008-07-05 17:56 ` Linus Torvalds
2008-07-05 18:40 ` Jan Engelhardt
2008-07-05 18:40 ` Jan Engelhardt
2008-07-05 18:40 ` Jan Engelhardt
2008-07-05 18:44 ` Linus Torvalds
2008-07-05 18:44 ` Linus Torvalds
2008-07-05 18:44 ` Linus Torvalds
2008-07-05 18:41 ` Vegard Nossum
2008-07-05 18:41 ` Vegard Nossum
2008-07-05 18:41 ` Vegard Nossum
2008-07-05 18:52 ` Matthew Wilcox
2008-07-05 18:52 ` Matthew Wilcox
2008-07-05 18:52 ` Matthew Wilcox
2008-07-06 0:02 ` Pekka Enberg
2008-07-06 0:02 ` Pekka Enberg
2008-07-06 0:02 ` Pekka Enberg
2008-07-06 5:17 ` Randy Dunlap
2008-07-06 5:17 ` Randy Dunlap
2008-07-06 5:17 ` Randy Dunlap
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080704132716.f1e12554.akpm@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=hpa@zytor.com \
--cc=linux-ia64@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.