diff options
-rw-r--r-- | runtime/vsprintf.c | 31 | ||||
-rw-r--r-- | stap.1.in | 2 | ||||
-rw-r--r-- | testsuite/systemtap.printf/memory1.stp | 14 |
3 files changed, 34 insertions, 13 deletions
diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c index 38ab0e2d..23810e75 100644 --- a/runtime/vsprintf.c +++ b/runtime/vsprintf.c @@ -361,18 +361,16 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) else len = 1; + if (*fmt_copy == 'M') + len = len * 2; /* hex dump print size */ + if (!(flags & STP_LEFT)) { while (len < field_width--) { num_bytes++; } } - if (*fmt_copy == 'M') { - num_bytes += number_size((unsigned long) *(uint64_t *) s, - 16, field_width, len, flags); - } - else { - num_bytes += len; - } + + num_bytes += len; while (len < field_width--) { num_bytes++; @@ -636,16 +634,25 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) len = 1; if (!(flags & STP_LEFT)) { - while (len < field_width--) { + int actlen = len; + if (*fmt == 'M') + actlen = len * 2; + while (actlen < field_width--) { if (str <= end) *str = ' '; ++str; } } - if (*fmt == 'M') { - str = number(str, str + len - 1 < end ? str + len - 1 : end, - (unsigned long) *(uint64_t *) s, - 16, field_width, len, flags); + if (*fmt == 'M') { /* stolen from kernel: trace_seq_putmem_hex() */ + const char _stp_hex_asc[] = "0123456789abcdef"; + int j; + for (i = 0, j = 0; i < len; i++) { + *str = _stp_hex_asc[((*s) & 0xf0) >> 4]; + str++; + *str = _stp_hex_asc[((*s) & 0x0f)]; + str++; s++; + } + len = len * 2; /* the actual length */ } else { for (i = 0; i < len; ++i) { @@ -674,7 +674,7 @@ Signed decimal. Safely reads kernel memory at the given address, outputs its content. The precision specifier determines the number of bytes to read. Default is 1 byte. .TP %M -Same as %m, but outputs in hexadecimal. The precision specifier determines the number of hexadecimal digits to output. Default is 1 digit. +Same as %m, but outputs in hexadecimal. The minimal size of output is double the precision specifier. .TP %o Unsigned octal. diff --git a/testsuite/systemtap.printf/memory1.stp b/testsuite/systemtap.printf/memory1.stp index f9cbf60b..15aa565b 100644 --- a/testsuite/systemtap.printf/memory1.stp +++ b/testsuite/systemtap.printf/memory1.stp @@ -113,6 +113,20 @@ probe syscall.open { success = 0; } + expected_16_actual = sprintf (" %02x%02x%02x%02x%02x%02x", + stringat(filename, 0), + stringat(filename, 1), + stringat(filename, 2), + stringat(filename, 3), + stringat(filename, 4), + stringat(filename, 5)); + testName = "%M dynamic width larger than dynamic precision"; + result = sprintf ("%*.*M", 14, 6, $filename); + if (result != expected_16_actual) { + printf ("Test %s failed\n", testName); + success = 0; + } + if (success) print ("Test passed\n"); |