From 9b6ab531858028b4ede462f41992a61be49b0c17 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 6 Jul 2008 16:43:12 -0700 Subject: [PATCH] --- yaml --- r: 98751 b: refs/heads/master c: 0fe1ef24f7bd0020f29ffe287dfdb9ead33ca0b2 h: refs/heads/master i: 98749: 0b6b6c7f45b3fa3eab611df91cb181f29d45f8ed 98747: 0187a5fba719d672dc41ab2092c78fbf9debab84 98743: cac416eaa0bde4374e7e98c2f81798a975bb8ce5 98735: 93f3eb8ab771ad7d0ebd36ec37b6c15ca63ab149 98719: 343d816817530870934bf1104fa2d203a333754b 98687: 116eb12d572e27c75a1b95ceb9dcb16aa254e41a v: v3 --- [refs] | 2 +- trunk/lib/vsprintf.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 1cf4c6539961..daa81dfc30b2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4d8a743cdd2690c0bc8d1b8cbd02cffb1ead849f +refs/heads/master: 0fe1ef24f7bd0020f29ffe287dfdb9ead33ca0b2 diff --git a/trunk/lib/vsprintf.c b/trunk/lib/vsprintf.c index 5d6f0718b6d9..1dc2d1d18fa8 100644 --- a/trunk/lib/vsprintf.c +++ b/trunk/lib/vsprintf.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include /* for PAGE_SIZE */ #include @@ -511,15 +513,52 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio return buf; } +static inline void *dereference_function_descriptor(void *ptr) +{ +#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) + void *p; + if (!probe_kernel_address(ptr, p)) + ptr = p; +#endif + return ptr; +} + +static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) +{ + unsigned long value = (unsigned long) ptr; +#ifdef CONFIG_KALLSYMS + char sym[KSYM_SYMBOL_LEN]; + sprint_symbol(sym, value); + return string(buf, end, sym, field_width, precision, flags); +#else + field_width = 2*sizeof(void *); + flags |= SPECIAL | SMALL | ZEROPAD; + return number(buf, end, value, 16, field_width, precision, flags); +#endif +} + /* * 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 don't actually handle any such, but we will.. + * Right now we just handle 'F' (for symbolic Function descriptor pointers) + * and 'S' (for Symbolic direct 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 field_width, int precision, int flags) { + switch (*fmt) { + case 'F': + ptr = dereference_function_descriptor(ptr); + /* Fallthrough */ + case 'S': + return symbol_string(buf, end, ptr, field_width, precision, flags); + } flags |= SMALL; if (field_width == -1) { field_width = 2*sizeof(void *);