diff options
-rw-r--r-- | lib/vsprintf.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7536acea135b..756ccafa9cec 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -408,6 +408,8 @@ enum format_type { | |||
408 | FORMAT_TYPE_LONG_LONG, | 408 | FORMAT_TYPE_LONG_LONG, |
409 | FORMAT_TYPE_ULONG, | 409 | FORMAT_TYPE_ULONG, |
410 | FORMAT_TYPE_LONG, | 410 | FORMAT_TYPE_LONG, |
411 | FORMAT_TYPE_UBYTE, | ||
412 | FORMAT_TYPE_BYTE, | ||
411 | FORMAT_TYPE_USHORT, | 413 | FORMAT_TYPE_USHORT, |
412 | FORMAT_TYPE_SHORT, | 414 | FORMAT_TYPE_SHORT, |
413 | FORMAT_TYPE_UINT, | 415 | FORMAT_TYPE_UINT, |
@@ -573,12 +575,15 @@ static char *string(char *buf, char *end, char *s, struct printf_spec spec) | |||
573 | } | 575 | } |
574 | 576 | ||
575 | static char *symbol_string(char *buf, char *end, void *ptr, | 577 | static char *symbol_string(char *buf, char *end, void *ptr, |
576 | struct printf_spec spec) | 578 | struct printf_spec spec, char ext) |
577 | { | 579 | { |
578 | unsigned long value = (unsigned long) ptr; | 580 | unsigned long value = (unsigned long) ptr; |
579 | #ifdef CONFIG_KALLSYMS | 581 | #ifdef CONFIG_KALLSYMS |
580 | char sym[KSYM_SYMBOL_LEN]; | 582 | char sym[KSYM_SYMBOL_LEN]; |
581 | sprint_symbol(sym, value); | 583 | if (ext != 'f') |
584 | sprint_symbol(sym, value); | ||
585 | else | ||
586 | kallsyms_lookup(value, NULL, NULL, NULL, sym); | ||
582 | return string(buf, end, sym, spec); | 587 | return string(buf, end, sym, spec); |
583 | #else | 588 | #else |
584 | spec.field_width = 2*sizeof(void *); | 589 | spec.field_width = 2*sizeof(void *); |
@@ -690,7 +695,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, | |||
690 | * | 695 | * |
691 | * Right now we handle: | 696 | * Right now we handle: |
692 | * | 697 | * |
693 | * - 'F' For symbolic function descriptor pointers | 698 | * - 'F' For symbolic function descriptor pointers with offset |
699 | * - 'f' For simple symbolic function names without offset | ||
694 | * - 'S' For symbolic direct pointers | 700 | * - 'S' For symbolic direct pointers |
695 | * - 'R' For a struct resource pointer, it prints the range of | 701 | * - 'R' For a struct resource pointer, it prints the range of |
696 | * addresses (not the name nor the flags) | 702 | * addresses (not the name nor the flags) |
@@ -713,10 +719,11 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
713 | 719 | ||
714 | switch (*fmt) { | 720 | switch (*fmt) { |
715 | case 'F': | 721 | case 'F': |
722 | case 'f': | ||
716 | ptr = dereference_function_descriptor(ptr); | 723 | ptr = dereference_function_descriptor(ptr); |
717 | /* Fallthrough */ | 724 | /* Fallthrough */ |
718 | case 'S': | 725 | case 'S': |
719 | return symbol_string(buf, end, ptr, spec); | 726 | return symbol_string(buf, end, ptr, spec, *fmt); |
720 | case 'R': | 727 | case 'R': |
721 | return resource_string(buf, end, ptr, spec); | 728 | return resource_string(buf, end, ptr, spec); |
722 | case 'm': | 729 | case 'm': |
@@ -853,11 +860,15 @@ qualifier: | |||
853 | spec->qualifier = -1; | 860 | spec->qualifier = -1; |
854 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || | 861 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || |
855 | *fmt == 'Z' || *fmt == 'z' || *fmt == 't') { | 862 | *fmt == 'Z' || *fmt == 'z' || *fmt == 't') { |
856 | spec->qualifier = *fmt; | 863 | spec->qualifier = *fmt++; |
857 | ++fmt; | 864 | if (unlikely(spec->qualifier == *fmt)) { |
858 | if (spec->qualifier == 'l' && *fmt == 'l') { | 865 | if (spec->qualifier == 'l') { |
859 | spec->qualifier = 'L'; | 866 | spec->qualifier = 'L'; |
860 | ++fmt; | 867 | ++fmt; |
868 | } else if (spec->qualifier == 'h') { | ||
869 | spec->qualifier = 'H'; | ||
870 | ++fmt; | ||
871 | } | ||
861 | } | 872 | } |
862 | } | 873 | } |
863 | 874 | ||
@@ -919,6 +930,11 @@ qualifier: | |||
919 | spec->type = FORMAT_TYPE_SIZE_T; | 930 | spec->type = FORMAT_TYPE_SIZE_T; |
920 | } else if (spec->qualifier == 't') { | 931 | } else if (spec->qualifier == 't') { |
921 | spec->type = FORMAT_TYPE_PTRDIFF; | 932 | spec->type = FORMAT_TYPE_PTRDIFF; |
933 | } else if (spec->qualifier == 'H') { | ||
934 | if (spec->flags & SIGN) | ||
935 | spec->type = FORMAT_TYPE_BYTE; | ||
936 | else | ||
937 | spec->type = FORMAT_TYPE_UBYTE; | ||
922 | } else if (spec->qualifier == 'h') { | 938 | } else if (spec->qualifier == 'h') { |
923 | if (spec->flags & SIGN) | 939 | if (spec->flags & SIGN) |
924 | spec->type = FORMAT_TYPE_SHORT; | 940 | spec->type = FORMAT_TYPE_SHORT; |
@@ -943,7 +959,8 @@ qualifier: | |||
943 | * | 959 | * |
944 | * This function follows C99 vsnprintf, but has some extensions: | 960 | * This function follows C99 vsnprintf, but has some extensions: |
945 | * %pS output the name of a text symbol | 961 | * %pS output the name of a text symbol |
946 | * %pF output the name of a function pointer | 962 | * %pF output the name of a function pointer with its offset |
963 | * %pf output the name of a function pointer without its offset | ||
947 | * %pR output the address range in a struct resource | 964 | * %pR output the address range in a struct resource |
948 | * | 965 | * |
949 | * The return value is the number of characters which would | 966 | * The return value is the number of characters which would |
@@ -1087,6 +1104,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1087 | case FORMAT_TYPE_PTRDIFF: | 1104 | case FORMAT_TYPE_PTRDIFF: |
1088 | num = va_arg(args, ptrdiff_t); | 1105 | num = va_arg(args, ptrdiff_t); |
1089 | break; | 1106 | break; |
1107 | case FORMAT_TYPE_UBYTE: | ||
1108 | num = (unsigned char) va_arg(args, int); | ||
1109 | break; | ||
1110 | case FORMAT_TYPE_BYTE: | ||
1111 | num = (signed char) va_arg(args, int); | ||
1112 | break; | ||
1090 | case FORMAT_TYPE_USHORT: | 1113 | case FORMAT_TYPE_USHORT: |
1091 | num = (unsigned short) va_arg(args, int); | 1114 | num = (unsigned short) va_arg(args, int); |
1092 | break; | 1115 | break; |
@@ -1363,6 +1386,10 @@ do { \ | |||
1363 | case FORMAT_TYPE_PTRDIFF: | 1386 | case FORMAT_TYPE_PTRDIFF: |
1364 | save_arg(ptrdiff_t); | 1387 | save_arg(ptrdiff_t); |
1365 | break; | 1388 | break; |
1389 | case FORMAT_TYPE_UBYTE: | ||
1390 | case FORMAT_TYPE_BYTE: | ||
1391 | save_arg(char); | ||
1392 | break; | ||
1366 | case FORMAT_TYPE_USHORT: | 1393 | case FORMAT_TYPE_USHORT: |
1367 | case FORMAT_TYPE_SHORT: | 1394 | case FORMAT_TYPE_SHORT: |
1368 | save_arg(short); | 1395 | save_arg(short); |
@@ -1391,7 +1418,8 @@ EXPORT_SYMBOL_GPL(vbin_printf); | |||
1391 | * | 1418 | * |
1392 | * The format follows C99 vsnprintf, but has some extensions: | 1419 | * The format follows C99 vsnprintf, but has some extensions: |
1393 | * %pS output the name of a text symbol | 1420 | * %pS output the name of a text symbol |
1394 | * %pF output the name of a function pointer | 1421 | * %pF output the name of a function pointer with its offset |
1422 | * %pf output the name of a function pointer without its offset | ||
1395 | * %pR output the address range in a struct resource | 1423 | * %pR output the address range in a struct resource |
1396 | * %n is ignored | 1424 | * %n is ignored |
1397 | * | 1425 | * |
@@ -1538,6 +1566,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
1538 | case FORMAT_TYPE_PTRDIFF: | 1566 | case FORMAT_TYPE_PTRDIFF: |
1539 | num = get_arg(ptrdiff_t); | 1567 | num = get_arg(ptrdiff_t); |
1540 | break; | 1568 | break; |
1569 | case FORMAT_TYPE_UBYTE: | ||
1570 | num = get_arg(unsigned char); | ||
1571 | break; | ||
1572 | case FORMAT_TYPE_BYTE: | ||
1573 | num = get_arg(signed char); | ||
1574 | break; | ||
1541 | case FORMAT_TYPE_USHORT: | 1575 | case FORMAT_TYPE_USHORT: |
1542 | num = get_arg(unsigned short); | 1576 | num = get_arg(unsigned short); |
1543 | break; | 1577 | break; |