mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
common/vsprintf: Add %ps and %pS format specifier support
Introduce the %ps and %pS format options for printing a symbol. %ps will print the symbol name and optional offset and size %pS will print the symbol name and unconditional offset and size Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
This commit is contained in:
1 parent
d41b853cc7
commit
9f6c545af9
2 files changed
+57
-2
No files matched your search
@@ -0,0 +1,17 @@
|
||||
Xen custom %p format options. A subset, borrowed from Linux.
|
||||
|
||||
All parameters to a %p option should be compatible with void*. Regular
|
||||
pointers are fine. Numbers should make use of the _p() macro.
|
||||
|
||||
Symbol/Function pointers:
|
||||
|
||||
%ps Symbol name with condition offset and size (iff offset != 0)
|
||||
e.g. printk
|
||||
default_idle+0x78/0x7d
|
||||
|
||||
%pS Symbol name with unconditional offset and size
|
||||
e.g. printk+0/0x48
|
||||
default_idle+0x78/0x7d
|
||||
|
||||
In the case that an appropriate symbol name can't be found, %p[sS] will
|
||||
fall back to '%p' and print the address in hex.
|
||||
+40
-2
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <xen/ctype.h>
|
||||
#include <xen/symbols.h>
|
||||
#include <xen/lib.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/page.h>
|
||||
@@ -261,10 +262,46 @@ static char *string(char *str, char *end, const char *s,
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *pointer(char *str, char *end,
|
||||
static char *pointer(char *str, char *end, const char **fmt_ptr,
|
||||
const void *arg, int field_width, int precision,
|
||||
int flags)
|
||||
{
|
||||
const char *fmt = *fmt_ptr, *s;
|
||||
|
||||
/* Custom %p suffixes. See XEN_ROOT/docs/misc/printk-formats.txt */
|
||||
switch ( fmt[1] )
|
||||
{
|
||||
case 's': /* Symbol name with offset and size (iff offset != 0) */
|
||||
case 'S': /* Symbol name unconditionally with offset and size */
|
||||
{
|
||||
unsigned long sym_size, sym_offset;
|
||||
char namebuf[KSYM_NAME_LEN+1];
|
||||
|
||||
/* Advance parents fmt string, as we have consumed 's' or 'S' */
|
||||
++*fmt_ptr;
|
||||
|
||||
s = symbols_lookup((unsigned long)arg, &sym_size, &sym_offset, namebuf);
|
||||
|
||||
/* If the symbol is not found, fall back to printing the address */
|
||||
if ( !s )
|
||||
break;
|
||||
|
||||
/* Print symbol name */
|
||||
str = string(str, end, s, -1, -1, 0);
|
||||
|
||||
if ( fmt[1] == 'S' || sym_offset != 0 )
|
||||
{
|
||||
/* Print '+<offset>/<len>' */
|
||||
str = number(str, end, sym_offset, 16, -1, -1, SPECIAL|SIGN|PLUS);
|
||||
if ( str <= end )
|
||||
*str++ = '/';
|
||||
str = number(str, end, sym_size, 16, -1, -1, SPECIAL);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
if ( field_width == -1 )
|
||||
{
|
||||
field_width = 2 * sizeof(void *);
|
||||
@@ -413,7 +450,8 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
str = pointer(str, end, va_arg(args, const void *),
|
||||
/* pointer() might advance fmt (%pS for example) */
|
||||
str = pointer(str, end, &fmt, va_arg(args, const void *),
|
||||
field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
|
||||