]> sourceware.org Git - systemtap.git/commitdiff
PR15932: printf %m/%M user variant
authorCody Santing <csanting@redhat.com>
Fri, 12 Aug 2016 19:03:13 +0000 (15:03 -0400)
committerCody Santing <csanting@redhat.com>
Fri, 12 Aug 2016 19:03:13 +0000 (15:03 -0400)
* man/stap.1.in: update documentation regarding %m/%M
* runtime/vsprintf.c: m/M cases in _stp_vsprint_memory now check for '#'/STP_SPECIAL flag
* testsuite/systemtap.printf/print_user_buffer.*: test case for new variant

man/stap.1.in
runtime/vsprintf.c
testsuite/systemtap.printf/print_user_buffer.c [new file with mode: 0644]
testsuite/systemtap.printf/print_user_buffer.exp [new file with mode: 0644]
testsuite/systemtap.printf/print_user_buffer.stp [new file with mode: 0644]

index 0f163de28e75ab36896698013f5ffa63bb745ec4..b6ee95d4c205c0ea43cf53d9b41f913048884506 100644 (file)
@@ -1532,7 +1532,7 @@ Character.
 Signed decimal.
 .TP
 %m
-Safely reads kernel memory at the given address, outputs its content.  The optional precision specifier (not field width) determines the number of bytes to read - default is 1 byte.  %10.4m prints 4 bytes of the memory in a 10-character-wide field.
+Safely reads kernel (without #) or user (with #) memory at the given address, outputs its content.  The optional precision specifier (not field width) determines the number of bytes to read - default is 1 byte.  %10.4m prints 4 bytes of the memory in a 10-character-wide field.  Note, on some architectures user memory can still be read without #.
 .TP
 %M
 Same as %m, but outputs in hexadecimal.  The minimal size of output is double the optional precision specifier - default is 1 byte (2 hex chars).  %10.4M prints 4 bytes of the memory as 8 hexadecimal characters in a 10-character-wide field.   %.*M hex-dumps a given number of bytes from a given buffer.
@@ -1563,7 +1563,8 @@ The
 .IR #
 flag selects the alternate forms.  For octal, this prefixes a 0.  For hex, this
 prefixes 0x or 0X, depending on case.  For characters, this escapes
-non-printing values with either C-like escapes or raw octal.
+non-printing values with either C-like escapes or raw octal.  In the case of %#m/%#M,
+this safely accesses user space memory rather than kernel space memory.
 .PP
 Examples:
 .SAMPLE
index 434020a24526d97dbd05b82321c022f2553997c5..0918bd957741aac9627017523a75e423ca58179e 100644 (file)
@@ -359,8 +359,12 @@ _stp_vsprint_memory(char * str, char * end, const char * ptr,
                 /* PR13386: Skip if called with null context */
                c = _stp_runtime_get_context();
                 if (c) for (i = 0; i < len && str < end; i++) {
-                       unsigned char c_tmp = kread((unsigned char *)(ptr));
-                       ptr++;
+                   unsigned char c_tmp;
+                         if (flags & STP_SPECIAL)
+                           c_tmp = uread((unsigned char *)(ptr));
+                         else
+                           c_tmp = kread((unsigned char *)(ptr));
+                         ptr++;
                        *str++ = _stp_hex_asc[(c_tmp & 0xf0) >> 4];
                        *str++ = _stp_hex_asc[(c_tmp & 0x0f)];
                }
@@ -370,8 +374,11 @@ _stp_vsprint_memory(char * str, char * end, const char * ptr,
                 /* PR13386: Skip if called with null context */
                c = _stp_runtime_get_context();
                if (c) for (i = 0; i < len && str <= end; ++i) {
-                       *str++ = kread((unsigned char *)(ptr));
-                       ptr++;
+                   if (flags & STP_SPECIAL)
+                       *str++ = uread((unsigned char *)(ptr));
+                    else
+                       *str++ = kread((unsigned char *)(ptr));
+                   ptr++;
                }
        }
        else                            /* %s format */
diff --git a/testsuite/systemtap.printf/print_user_buffer.c b/testsuite/systemtap.printf/print_user_buffer.c
new file mode 100644 (file)
index 0000000..84fd2ad
--- /dev/null
@@ -0,0 +1,12 @@
+#include <unistd.h>
+
+int main()
+{
+   char buffer[7] = "foobar\n";
+   write(1, buffer, 7);
+    
+   char buffer2[2] = {'\0','\n'};
+   write(1, buffer2, 2);
+
+   return 0;
+}
diff --git a/testsuite/systemtap.printf/print_user_buffer.exp b/testsuite/systemtap.printf/print_user_buffer.exp
new file mode 100644 (file)
index 0000000..c4eb727
--- /dev/null
@@ -0,0 +1,17 @@
+# Check that %#M and %#m within printf work correctly.
+
+set test "print_user_buffer"
+set srcfile "$srcdir/$subdir/$test.c"
+set exefile "[pwd]/$test.exe"
+set test_flags "additional_flags=-g"
+set res [target_compile "$srcfile" "$exefile" executable "$test_flags"]
+
+if { $res != ""} {
+  verbose "target_compile failed: $res" 2
+  fail "$test compile"
+  untested "$test"
+  return
+} else {
+  pass "$test compile"
+}
+stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -c "$exefile > /dev/null"
diff --git a/testsuite/systemtap.printf/print_user_buffer.stp b/testsuite/systemtap.printf/print_user_buffer.stp
new file mode 100644 (file)
index 0000000..4ac3d20
--- /dev/null
@@ -0,0 +1,38 @@
+global errors = 0
+
+probe begin { println("systemtap starting probe") }
+probe end 
+{
+       println("systemtap ending probe")       
+  if (!errors)
+     println("systemtap test success")
+}
+
+probe syscall.write
+{
+    if (!target_set_pid(pid())) next;
+    
+    value = sprintf("%#.*M",$count, $buf)       
+    if (value != "666f6f6261720a"&& value!= "000a")
+         errors++                  
+    
+    value = sprintf("%#.*m",$count, $buf)
+    if (value != "foobar\n" && value !="\0\n")
+         errors++
+
+    try {
+       errors++
+       value = sprintf("%#.*M",$count, $fd)
+    } 
+    catch {
+         errors--
+    }
+    try {
+       errors++
+        value = sprintf("%#.*m", $count, $fd)
+    }
+    catch {
+           errors--
+    }
+
+}
This page took 0.035992 seconds and 5 git commands to generate.