diff options
author | Wenji Huang <wenji.huang@oracle.com> | 2009-04-27 05:38:18 -0400 |
---|---|---|
committer | Wenji Huang <wenji.huang@oracle.com> | 2009-04-26 23:05:04 -0400 |
commit | c4f51a54acff992cf19902ffd56e8338158c5811 (patch) | |
tree | e09944d29060011dfc91c95748f07f673432df96 | |
parent | 40fc3e43cea224623400ac07b6f03c700d209dec (diff) | |
download | systemtap-steved-c4f51a54acff992cf19902ffd56e8338158c5811.tar.gz systemtap-steved-c4f51a54acff992cf19902ffd56e8338158c5811.tar.xz systemtap-steved-c4f51a54acff992cf19902ffd56e8338158c5811.zip |
PR10099: Extend %M directive to support hexdumping large buffers
This patch will make %M directive dump the variable width
buffer in hex format instead of returning uint64_t number
as before.
* runtime/vsprintf.c: Modify %M directive.
* stap.1.in: Update description.
* testsuite/systemtap.printf/memory1.stp: Add test case.
-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"); |