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; str = number(str, end, sym_size, 16, -1, -1, SPECIAL); } return str; } } if ( field_width == -1 ) { field_width = 2 * sizeof(void *); flags |= ZEROPAD; } return number(str, end, (unsigned long)arg, 16, field_width, precision, flags); }
/* Replace "%s" in format with address, or returns -errno. */ void __print_symbol(const char *fmt, unsigned long address) { const char *name; unsigned long offset, size, flags; static DEFINE_SPINLOCK(lock); static char namebuf[KSYM_NAME_LEN+1]; #define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \ 2*(BITS_PER_LONG*3/10) + 1 static char buffer[BUFFER_SIZE]; spin_lock_irqsave(&lock, flags); name = symbols_lookup(address, &size, &offset, namebuf); if (!name) snprintf(buffer, BUFFER_SIZE, "???"); else snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size); printk(fmt, buffer); spin_unlock_irqrestore(&lock, flags); }
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 'h': /* Raw buffer as hex string. */ { const uint8_t *hex_buffer = arg; unsigned int i; /* Consumed 'h' from the format string. */ ++*fmt_ptr; /* Bound user count from %* to between 0 and 64 bytes. */ if ( field_width <= 0 ) return str; if ( field_width > 64 ) field_width = 64; for ( i = 0; ; ) { /* Each byte: 2 chars, 0-padded, base 16, no hex prefix. */ str = number(str, end, hex_buffer[i], 16, 2, -1, ZEROPAD); if ( ++i == field_width ) return str; if ( str < end ) *str = ' '; ++str; } } 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; str = number(str, end, sym_size, 16, -1, -1, SPECIAL); } return str; } case 'v': /* d<domain-id>v<vcpu-id> from a struct vcpu */ { const struct vcpu *v = arg; ++*fmt_ptr; if ( str < end ) *str = 'd'; str = number(str + 1, end, v->domain->domain_id, 10, -1, -1, 0); if ( str < end ) *str = 'v'; return number(str + 1, end, v->vcpu_id, 10, -1, -1, 0); } } if ( field_width == -1 ) { field_width = 2 * sizeof(void *); flags |= ZEROPAD; } return number(str, end, (unsigned long)arg, 16, field_width, precision, flags); }