This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] Fix the register() and u_register() tapset functions for x86


The register() and u_register() functions incorrectly read 16-bit
x86 registers as 32-bit on both i386 and x86_64.

Fixed the sign-extension of register values on i386.

Fixed a compilation error when using *register() in the dyninst
runtime mode on x86_64.

Also added support for 8-bit x86 reigsters like "al" and "bh" on both
i386 and x86_64.
---
 NEWS                                        |   4 +
 runtime/regs.c                              |  18 +++-
 tapset/i386/registers.stp                   | 120 ++++++++++++++++-----
 tapset/x86_64/registers.stp                 | 103 ++++++++++++++----
 testsuite/systemtap.base/register_x86.exp   | 155 ++++++++++++++++++++++++++++
 testsuite/systemtap.base/register_x86_1.c   |   9 ++
 testsuite/systemtap.base/register_x86_1.stp |  15 +++
 testsuite/systemtap.base/register_x86_2.c   |   9 ++
 testsuite/systemtap.base/register_x86_2.stp |  15 +++
 testsuite/systemtap.base/register_x86_3.c   |   9 ++
 testsuite/systemtap.base/register_x86_3.stp |  14 +++
 testsuite/systemtap.base/register_x86_4.c   |   9 ++
 testsuite/systemtap.base/register_x86_4.stp |  14 +++
 13 files changed, 451 insertions(+), 43 deletions(-)
 create mode 100644 testsuite/systemtap.base/register_x86.exp
 create mode 100644 testsuite/systemtap.base/register_x86_1.c
 create mode 100644 testsuite/systemtap.base/register_x86_1.stp
 create mode 100644 testsuite/systemtap.base/register_x86_2.c
 create mode 100644 testsuite/systemtap.base/register_x86_2.stp
 create mode 100644 testsuite/systemtap.base/register_x86_3.c
 create mode 100644 testsuite/systemtap.base/register_x86_3.stp
 create mode 100644 testsuite/systemtap.base/register_x86_4.c
 create mode 100644 testsuite/systemtap.base/register_x86_4.stp

diff --git a/NEWS b/NEWS
index 6708c184d..04e73650f 100644
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,10 @@
 - Parentheses after unary '&' with a target-symbol expression is
   now accepted in the script language.
 
+- Tapset functions register() and u_register() now support 8-bit
+  x86 register names "ah", "al", "bh", "bl", "ch", "cl", "dh", and
+  "dl" on both x86_64 and i386.
+
 * What's new in version 3.3, 2018-06-08
 
 - A new "stap --example FOO.stp" mode searches the example scripts
diff --git a/runtime/regs.c b/runtime/regs.c
index ade3ad9fc..0d4536f54 100644
--- a/runtime/regs.c
+++ b/runtime/regs.c
@@ -59,7 +59,7 @@ static long _stp_get_sp(struct pt_regs *regs)
 
 #endif	/* __x86_64__ */
 
-#if defined(__x86_64__) || defined(__ia64__)
+#if defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
 
 /* Ensure that the upper 32 bits of val are a sign-extension of the lower 32. */
 static int64_t __stp_sign_extend32(int64_t val)
@@ -68,7 +68,21 @@ static int64_t __stp_sign_extend32(int64_t val)
 	return *val_ptr32;
 }
 
-#endif	/* __x86_64__ || __ia64__ */
+/* Ensure that the upper 48 bits of val are a sign-extension of the lower 16. */
+static int64_t __stp_sign_extend16(int64_t val)
+{
+	int16_t *val_ptr16 = (int16_t*) &val;
+	return *val_ptr16;
+}
+
+/* Ensure that the upper 56 bits of val are a sign-extension of the lower 8. */
+static int64_t __stp_sign_extend8(int64_t val)
+{
+	int8_t *val_ptr8 = (int8_t*) &val;
+	return *val_ptr8;
+}
+
+#endif	/* __x86_64__ || __ia64__ || __i386__ */
 
 #if defined(__i386__) || defined(__x86_64__)
 /*
diff --git a/tapset/i386/registers.stp b/tapset/i386/registers.stp
index af792b40a..a47b457a3 100644
--- a/tapset/i386/registers.stp
+++ b/tapset/i386/registers.stp
@@ -5,7 +5,8 @@
 #endif
 %}
 
-@__private30 global _reg_offsets[34], _sp_offset, _ss_offset
+@__private30 global _reg_offsets[17], _r16_offsets[17], _r8_offsets[8],
+		_sp_offset, _ss_offset
 
 function test_x86_fs:long() %{ /* pure */
 #if defined(STAPCONF_X86_XFS) || defined (STAPCONF_X86_FS)
@@ -27,27 +28,39 @@ probe init {
 
 	/* Same order as pt_regs */
 	_offset = 0
-	_reg_offsets["ebx"] = _reg_offsets["bx"] = _offset
-	_reg_offsets["ecx"] = _reg_offsets["cx"] = (_offset += 4)
-	_reg_offsets["edx"] = _reg_offsets["dx"] = (_offset += 4)
-	_reg_offsets["esi"] = _reg_offsets["si"] = (_offset += 4)
-	_reg_offsets["edi"] = _reg_offsets["di"] = (_offset += 4)
-	_reg_offsets["ebp"] = _reg_offsets["bp"] = (_offset += 4)
-	_reg_offsets["eax"] = _reg_offsets["ax"] = (_offset += 4)
-	_reg_offsets["xds"] = _reg_offsets["ds"] = (_offset += 4)
-	_reg_offsets["xes"] = _reg_offsets["es"] = (_offset += 4)
+	_reg_offsets["ebx"] = _r16_offsets["bx"] = _r8_offsets["bl"] = _offset
+	_r8_offsets["bh"] = _offset + 1
+
+	_reg_offsets["ecx"] = _r16_offsets["cx"] = _r8_offsets["cl"]
+		= (_offset += 4)
+	_r8_offsets["ch"] = _offset + 1
+
+	_reg_offsets["edx"] = _r16_offsets["dx"] = _r8_offsets["dl"]
+		= (_offset += 4)
+	_r8_offsets["dh"] = _offset + 1
+
+	_reg_offsets["esi"] = _r16_offsets["si"] = (_offset += 4)
+	_reg_offsets["edi"] = _r16_offsets["di"] = (_offset += 4)
+	_reg_offsets["ebp"] = _r16_offsets["bp"] = (_offset += 4)
+
+	_reg_offsets["eax"] = _r16_offsets["ax"] = _r8_offsets["al"]
+		= (_offset += 4)
+	_r8_offsets["ah"] = _offset + 1
+
+	_reg_offsets["xds"] = _r16_offsets["ds"] = (_offset += 4)
+	_reg_offsets["xes"] = _r16_offsets["es"] = (_offset += 4)
 if (test_x86_fs()) {
-	_reg_offsets["xfs"] = _reg_offsets["fs"] = (_offset += 4)
+	_reg_offsets["xfs"] = _r16_offsets["fs"] = (_offset += 4)
 }
 if (test_x86_gs()) {
-	_reg_offsets["xgs"] = _reg_offsets["gs"] = (_offset += 4)
+	_reg_offsets["xgs"] = _r16_offsets["gs"] = (_offset += 4)
 }
-	_reg_offsets["orig_eax"] = _reg_offsets["orig_ax"] = (_offset += 4)
-	_reg_offsets["eip"] = _reg_offsets["ip"] = (_offset += 4)
-	_reg_offsets["xcs"] = _reg_offsets["cs"] = (_offset += 4)
-	_reg_offsets["eflags"] = _reg_offsets["flags"] = (_offset += 4)
-	_reg_offsets["esp"] = _reg_offsets["sp"] = _sp_offset = (_offset += 4)
-	_reg_offsets["xss"] = _reg_offsets["ss"] = _ss_offset = (_offset += 4)
+	_reg_offsets["orig_eax"] = _r16_offsets["orig_ax"] = (_offset += 4)
+	_reg_offsets["eip"] = _r16_offsets["ip"] = (_offset += 4)
+	_reg_offsets["xcs"] = _r16_offsets["cs"] = (_offset += 4)
+	_reg_offsets["eflags"] = _r16_offsets["flags"] = (_offset += 4)
+	_reg_offsets["esp"] = _r16_offsets["sp"] = _sp_offset = (_offset += 4)
+	_reg_offsets["xss"] = _r16_offsets["ss"] = _ss_offset = (_offset += 4)
 }
 
 function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
@@ -104,18 +117,79 @@ function _stp_kernel_ss:long () %{ /* pure */
 	STAP_RETVALUE = ss;
 %}
 
-/* Return the named register value as a signed value. */
-function register:long (name:string) {
+/*
+ * _stp_sign_extend32() is callable from a script function.
+ * __stp_sign_extend32() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend32:long (value:long) %{ /* pure */
+	STAP_RETVALUE = __stp_sign_extend32(STAP_ARG_value);
+%}
+
+/*
+ * _stp_sign_extend16() is callable from a script function.
+ * __stp_sign_extend16() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend16:long (value:long) %{ /* pure */
+	STAP_RETVALUE = __stp_sign_extend16(STAP_ARG_value);
+%}
+
+/*
+ * _stp_sign_extend8() is callable from a script function.
+ * __stp_sign_extend8() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend8:long (value:long) %{ /* pure */
+	STAP_RETVALUE = __stp_sign_extend8(STAP_ARG_value);
+%}
+
+function _stp_register:long (name:string, sign_extend:long) {
+	reg16 = 0
+	reg8 = 0
   assert(registers_valid(), "cannot access CPU registers in this context")
 	offset = _reg_offsets[name]
-  assert(offset != 0 || (name in _reg_offsets), "Unknown register: " . name)
+	if (offset == 0 && !(name in _reg_offsets)) {
+		offset = _r16_offsets[name]
+		if (offset == 0 && !(name in _r16_offsets)) {
+			offset = _r8_offsets[name]
+			if (offset == 0 && !(name in _r8_offsets)) {
+				assert(0, "Unknown register: " . name)
+			} else {
+				reg8 = 1;
+			}
+		} else {
+			reg16 = 1;
+		}
+	}
+
 	if (_stp_probing_kernel()) {
 		if (offset == _sp_offset)
 			return _stp_kernel_sp(_sp_offset)
 		else if (offset == _ss_offset)
 			return _stp_kernel_ss()
 	}
-	return _stp_get_register_by_offset(offset)
+
+	value = _stp_get_register_by_offset(offset)
+	if (reg16) {
+		if (sign_extend)
+			value = _stp_sign_extend16(value)
+		else
+			value &= 0xffff
+	} else if (reg8) {
+		if (sign_extend)
+			value = _stp_sign_extend8(value)
+		else
+			value &= 0xff
+	} else {
+		if (sign_extend)
+			value = _stp_sign_extend32(value)
+		else
+			value &= 0xffffffff
+	}
+	return value
+}
+
+/* Return the named register value as a signed value. */
+function register:long (name:string) {
+	return _stp_register (name, 1)
 }
 
 /*
@@ -123,7 +197,7 @@ function register:long (name:string) {
  * don't sign-extend the register value when promoting it to 64 bits.
  */
 function u_register:long (name:string) {
-	return register(name) & 0xffffffff;
+	return _stp_register(name, 0)
 }
 
 /* Return the value of function arg #argnum (1=first arg) as a signed value. */
diff --git a/tapset/x86_64/registers.stp b/tapset/x86_64/registers.stp
index 61701d038..54dbe2204 100644
--- a/tapset/x86_64/registers.stp
+++ b/tapset/x86_64/registers.stp
@@ -5,7 +5,8 @@
 #endif
 %}
 
-@__private30 global _reg_offsets[34], _r32_offsets[10]
+@__private30 global _reg_offsets[21], _r32_offsets[10], _r16_offsets[13],
+		_r8_offsets[8]
 
 probe init {
 	/* Same order as pt_regs */
@@ -13,23 +14,23 @@ probe init {
 	_reg_offsets["r14"] = 8
 	_reg_offsets["r13"] = 16
 	_reg_offsets["r12"] = 24
-	_reg_offsets["rbp"] = 32	_reg_offsets["bp"] = 32
-	_reg_offsets["rbx"] = 40	_reg_offsets["bx"] = 40
+	_reg_offsets["rbp"] = 32
+	_reg_offsets["rbx"] = 40
 	_reg_offsets["r11"] = 48
 	_reg_offsets["r10"] = 56
 	_reg_offsets["r9"]  = 64
 	_reg_offsets["r8"]  = 72
-	_reg_offsets["rax"] = 80	_reg_offsets["ax"] = 80
-	_reg_offsets["rcx"] = 88	_reg_offsets["cx"] = 88
-	_reg_offsets["rdx"] = 96	_reg_offsets["dx"] = 96
-	_reg_offsets["rsi"] = 104	_reg_offsets["si"] = 104
-	_reg_offsets["rdi"] = 112	_reg_offsets["di"] = 112
-	_reg_offsets["orig_rax"] = 120	_reg_offsets["orig_ax"] = 120
-	_reg_offsets["rip"] = 128	_reg_offsets["ip"] = 128
-	_reg_offsets["xcs"] = 136	_reg_offsets["cs"] = 136
-	_reg_offsets["eflags"] = 144	_reg_offsets["flags"] = 144
-	_reg_offsets["rsp"] = 152	_reg_offsets["sp"] = 152
-	_reg_offsets["xss"] = 160	_reg_offsets["ss"] = 160
+	_reg_offsets["rax"] = 80
+	_reg_offsets["rcx"] = 88
+	_reg_offsets["rdx"] = 96
+	_reg_offsets["rsi"] = 104
+	_reg_offsets["rdi"] = 112
+	_reg_offsets["orig_rax"] = 120
+	_reg_offsets["rip"] = 128
+	_reg_offsets["xcs"] = 136
+	_reg_offsets["eflags"] = 144
+	_reg_offsets["rsp"] = 152
+	_reg_offsets["xss"] = 160
 
 	_r32_offsets["ebp"] = 32
 	_r32_offsets["ebx"] = 40
@@ -41,6 +42,29 @@ probe init {
 	_r32_offsets["orig_eax"] = 120
 	_r32_offsets["eip"] = 128
 	_r32_offsets["esp"] = 152
+
+	_r16_offsets["bp"] = 32
+	_r16_offsets["bx"] = 40
+	_r16_offsets["ax"] = 80
+	_r16_offsets["cx"] = 88
+	_r16_offsets["dx"] = 96
+	_r16_offsets["si"] = 104
+	_r16_offsets["di"] = 112
+	_r16_offsets["orig_ax"] = 120
+	_r16_offsets["ip"] = 128
+	_r16_offsets["cs"] = 136
+	_r16_offsets["flags"] = 144
+	_r16_offsets["sp"] = 152
+	_r16_offsets["ss"] = 160
+
+	_r8_offsets["al"] = 80
+	_r8_offsets["ah"] = 81
+	_r8_offsets["bl"] = 40
+	_r8_offsets["bh"] = 41
+	_r8_offsets["cl"] = 88
+	_r8_offsets["ch"] = 89
+	_r8_offsets["dl"] = 96
+	_r8_offsets["dh"] = 97
 }
 
 function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
@@ -53,7 +77,7 @@ function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
 	}
 	if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) {
 		snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
-				"Bad register offset: %lld", STAP_ARG_offset);
+				"Bad register offset: %lld", (long long) STAP_ARG_offset);
 		CONTEXT->last_error = CONTEXT->error_buffer;
 		return;
 	}
@@ -69,14 +93,46 @@ function _stp_sign_extend32:long (value:long) %{ /* pure */
 	STAP_RETVALUE = __stp_sign_extend32(STAP_ARG_value);
 %}
 
+/*
+ * _stp_sign_extend16() is callable from a script function.
+ * __stp_sign_extend16() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend16:long (value:long) %{ /* pure */
+	STAP_RETVALUE = __stp_sign_extend16(STAP_ARG_value);
+%}
+
+/*
+ * _stp_sign_extend8() is callable from a script function.
+ * __stp_sign_extend8() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend8:long (value:long) %{ /* pure */
+	STAP_RETVALUE = __stp_sign_extend8(STAP_ARG_value);
+%}
+
 function _stp_register:long (name:string, sign_extend:long) {
 	reg32 = 0
-  assert(registers_valid(), "cannot access CPU registers in this context")
+	reg16 = 0
+	reg8 = 0
+	assert(registers_valid(), "cannot access CPU registers in this context")
 	offset = _reg_offsets[name]
 	if (offset == 0 && !(name in _reg_offsets)) {
 		offset = _r32_offsets[name]
-    assert(offset != 0 || (name in _r32_offsets), "Unknown register: " . name)
-		reg32 = 1
+		if (offset == 0 && !(name in _r32_offsets)) {
+			offset = _r16_offsets[name]
+			if (offset == 0 && !(name in _r16_offsets)) {
+				offset = _r8_offsets[name]
+				if (offset == 0 && !(name in _r8_offsets)) {
+					assert(0, "Unknown register: " . name)
+				} else {
+					reg8 = 1;
+				}
+			} else {
+				reg16 = 1;
+			}
+
+		} else {
+			reg32 = 1
+		}
 	}
 	value =  _stp_get_register_by_offset(offset)
 	if (reg32) {
@@ -84,6 +140,17 @@ function _stp_register:long (name:string, sign_extend:long) {
 			value = _stp_sign_extend32(value)
 		else
 			value &= 0xffffffff
+	} else if (reg16) {
+		if (sign_extend)
+			value = _stp_sign_extend16(value)
+		else
+			value &= 0xffff
+	} else {
+		assert (reg8);
+		if (sign_extend)
+			value = _stp_sign_extend8(value)
+		else
+			value &= 0xff
 	}
 	return value
 }
diff --git a/testsuite/systemtap.base/register_x86.exp b/testsuite/systemtap.base/register_x86.exp
new file mode 100644
index 000000000..0f1371d47
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86.exp
@@ -0,0 +1,155 @@
+set test "register_x86"
+set testpath "$srcdir/$subdir"
+
+if {! [installtest_p]} { untested $test; return }
+if {! [uretprobes_p]} { untested $test; return }
+set arch [exec uname -i]
+if {$arch ne "i386" && $arch ne "x86_64"} { untested $test; return }
+
+# --- TEST 1 ---
+
+set subtest1 "TEST 1: 8-bit and 16-bit registers for eax"
+
+set res [target_compile ${testpath}/${test}_1.c ./a.out executable \
+    "additional_flags=-O additional_flags=-g additional_flags=-O0"]
+if {$res ne ""} {
+    verbose "target_compile failed: $res" 2
+    fail "$test: $subtest1: unable to compile ${test}_1.c"
+} else {
+    foreach runtime [get_runtime_list] {
+        if {$runtime eq ""} {
+            set runtime "kernel"
+        }
+        set test_name "$test: $subtest1 ($runtime)"
+        set cmd "stap --runtime=$runtime -c ./a.out '$srcdir/$subdir/${test}_1.stp'"
+        set exit_code [run_cmd_2way $cmd out stderr]
+        set exp_out "eax = 0xffffffffbeefdead
+u eax = 0xbeefdead
+
+ax = 0xffffffffffffdead
+u ax = 0xdead
+
+al = 0xffffffffffffffad
+u al = 0xad
+
+ah = 0xffffffffffffffde
+u ah = 0xde
+"
+        is "${test_name}: stdout" $out $exp_out
+        is "${test_name}: exit code" $exit_code 0
+        if {$stderr ne ""} {
+            send_log "stderr:\n$stderr"
+        }
+    }
+}
+
+# --- TEST 2 ---
+
+set subtest2 "TEST 2: 8-bit and 16-bit registers for edx"
+
+set res [target_compile ${testpath}/${test}_2.c ./a.out executable \
+    "additional_flags=-O additional_flags=-g additional_flags=-O0"]
+if {$res ne ""} {
+    verbose "target_compile failed: $res" 2
+    fail "$test: $subtest2: unable to compile ${test}_2.c"
+} else {
+    foreach runtime [get_runtime_list] {
+        if {$runtime eq ""} {
+            set runtime "kernel"
+        }
+        set test_name "$test: $subtest2 ($runtime)"
+        set cmd "stap --runtime=$runtime -c ./a.out '$srcdir/$subdir/${test}_2.stp'"
+        set exit_code [run_cmd_2way $cmd out stderr]
+        set exp_out "edx = 0xffffffffbeefdead
+u edx = 0xbeefdead
+
+dx = 0xffffffffffffdead
+u dx = 0xdead
+
+dl = 0xffffffffffffffad
+u dl = 0xad
+
+dh = 0xffffffffffffffde
+u dh = 0xde
+"
+        is "${test_name}: stdout" $out $exp_out
+        is "${test_name}: exit code" $exit_code 0
+        if {$stderr ne ""} {
+            send_log "stderr:\n$stderr"
+        }
+    }
+}
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: 8-bit and 16-bit registers for ecx"
+
+set res [target_compile ${testpath}/${test}_3.c ./a.out executable \
+    "additional_flags=-O additional_flags=-g additional_flags=-O0"]
+if {$res ne ""} {
+    verbose "target_compile failed: $res" 2
+    fail "$test: $subtest3: unable to compile ${test}_3.c"
+} else {
+    foreach runtime [get_runtime_list] {
+        if {$runtime eq ""} {
+            set runtime "kernel"
+        }
+        set test_name "$test: $subtest3 ($runtime)"
+        set cmd "stap --runtime=$runtime -c ./a.out '$srcdir/$subdir/${test}_3.stp'"
+        set exit_code [run_cmd_2way $cmd out stderr]
+        set exp_out "ecx = 0xffffffffbeefdead
+u ecx = 0xbeefdead
+
+cx = 0xffffffffffffdead
+u cx = 0xdead
+
+cl = 0xffffffffffffffad
+u cl = 0xad
+
+ch = 0xffffffffffffffde
+u ch = 0xde
+"
+        is "${test_name}: stdout" $out $exp_out
+        is "${test_name}: exit code" $exit_code 0
+        if {$stderr ne ""} {
+            send_log "stderr:\n$stderr"
+        }
+    }
+}
+
+# --- TEST 4 ---
+
+set subtest4 "TEST 4: 8-bit and 16-bit registers for eax"
+
+set res [target_compile ${testpath}/${test}_4.c ./a.out executable \
+    "additional_flags=-O additional_flags=-g additional_flags=-O0"]
+if {$res ne ""} {
+    verbose "target_compile failed: $res" 2
+    fail "$test: $subtest4: unable to compile ${test}_4.c"
+} else {
+    foreach runtime [get_runtime_list] {
+        if {$runtime eq ""} {
+            set runtime "kernel"
+        }
+        set test_name "$test: $subtest4 ($runtime)"
+        set cmd "stap --runtime=$runtime -c ./a.out '$srcdir/$subdir/${test}_4.stp'"
+        set exit_code [run_cmd_2way $cmd out stderr]
+        set exp_out "ebx = 0xffffffffbeefdead
+u ebx = 0xbeefdead
+
+bx = 0xffffffffffffdead
+u bx = 0xdead
+
+bl = 0xffffffffffffffad
+u bl = 0xad
+
+bh = 0xffffffffffffffde
+u bh = 0xde
+"
+        is "${test_name}: stdout" $out $exp_out
+        is "${test_name}: exit code" $exit_code 0
+        if {$stderr ne ""} {
+            send_log "stderr:\n$stderr"
+        }
+    }
+}
diff --git a/testsuite/systemtap.base/register_x86_1.c b/testsuite/systemtap.base/register_x86_1.c
new file mode 100644
index 000000000..2b9e5de8b
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_1.c
@@ -0,0 +1,9 @@
+void foo(void) {
+    asm("movl $0xbeefdead, %eax");
+    return;
+}
+
+int main(void) {
+    foo();
+    return 0;
+}
diff --git a/testsuite/systemtap.base/register_x86_1.stp b/testsuite/systemtap.base/register_x86_1.stp
new file mode 100644
index 000000000..5cadeceab
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_1.stp
@@ -0,0 +1,15 @@
+probe process.function("foo").return {
+    printf("eax = %#x\n", register("eax"));
+    printf("u eax = %#x\n\n", u_register("eax"));
+
+    printf("ax = %#x\n", register("ax"));
+    printf("u ax = %#x\n\n", u_register("ax"));
+
+    printf("al = %#x\n", register("al"));
+    printf("u al = %#x\n\n", u_register("al"));
+
+    printf("ah = %#x\n", register("ah"));
+    printf("u ah = %#x\n", u_register("ah"));
+
+    exit()
+}
diff --git a/testsuite/systemtap.base/register_x86_2.c b/testsuite/systemtap.base/register_x86_2.c
new file mode 100644
index 000000000..e057e4add
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_2.c
@@ -0,0 +1,9 @@
+void foo(void) {
+    asm("movl $0xbeefdead, %edx");
+    return;
+}
+
+int main(void) {
+    foo();
+    return 0;
+}
diff --git a/testsuite/systemtap.base/register_x86_2.stp b/testsuite/systemtap.base/register_x86_2.stp
new file mode 100644
index 000000000..356b47938
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_2.stp
@@ -0,0 +1,15 @@
+probe process.function("foo").return {
+    printf("edx = %#x\n", register("edx"));
+    printf("u edx = %#x\n\n", u_register("edx"));
+
+    printf("dx = %#x\n", register("dx"));
+    printf("u dx = %#x\n\n", u_register("dx"));
+
+    printf("dl = %#x\n", register("dl"));
+    printf("u dl = %#x\n\n", u_register("dl"));
+
+    printf("dh = %#x\n", register("dh"));
+    printf("u dh = %#x\n", u_register("dh"));
+
+    exit()
+}
diff --git a/testsuite/systemtap.base/register_x86_3.c b/testsuite/systemtap.base/register_x86_3.c
new file mode 100644
index 000000000..568784165
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_3.c
@@ -0,0 +1,9 @@
+void foo(void) {
+    asm("movl $0xbeefdead, %ecx");
+    return;
+}
+
+int main(void) {
+    foo();
+    return 0;
+}
diff --git a/testsuite/systemtap.base/register_x86_3.stp b/testsuite/systemtap.base/register_x86_3.stp
new file mode 100644
index 000000000..eed08fe1b
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_3.stp
@@ -0,0 +1,14 @@
+probe process.function("foo").return {
+    printf("ecx = %#x\n", register("ecx"));
+    printf("u ecx = %#x\n\n", u_register("ecx"));
+
+    printf("cx = %#x\n", register("cx"));
+    printf("u cx = %#x\n\n", u_register("cx"));
+
+    printf("cl = %#x\n", register("cl"));
+    printf("u cl = %#x\n\n", u_register("cl"));
+
+    printf("ch = %#x\n", register("ch"));
+    printf("u ch = %#x\n", u_register("ch"));
+    exit()
+}
diff --git a/testsuite/systemtap.base/register_x86_4.c b/testsuite/systemtap.base/register_x86_4.c
new file mode 100644
index 000000000..6ccc6f8bb
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_4.c
@@ -0,0 +1,9 @@
+void foo(void) {
+    asm("movl $0xbeefdead, %ebx");
+    return;
+}
+
+int main(void) {
+    foo();
+    return 0;
+}
diff --git a/testsuite/systemtap.base/register_x86_4.stp b/testsuite/systemtap.base/register_x86_4.stp
new file mode 100644
index 000000000..791ca0656
--- /dev/null
+++ b/testsuite/systemtap.base/register_x86_4.stp
@@ -0,0 +1,14 @@
+probe process.function("foo").return {
+    printf("ebx = %#x\n", register("ebx"));
+    printf("u ebx = %#x\n\n", u_register("ebx"));
+
+    printf("bx = %#x\n", register("bx"));
+    printf("u bx = %#x\n\n", u_register("bx"));
+
+    printf("bl = %#x\n", register("bl"));
+    printf("u bl = %#x\n\n", u_register("bl"));
+
+    printf("bh = %#x\n", register("bh"));
+    printf("u bh = %#x\n", u_register("bh"));
+    exit()
+}
-- 
2.11.0.295.gd7dffce


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]