From: Martin Cermak Date: Tue, 28 Apr 2015 04:45:02 +0000 (+0200) Subject: PR18337: Test coverage improvements, tapset extension. X-Git-Tag: release-2.8~78 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=8d4c7e8139830807d82ea0c22ecd1a63adc1d7b6;p=systemtap.git PR18337: Test coverage improvements, tapset extension. * tapset/linux/aux_syscalls.stp: New auxiliary function _kexec_flags_str() * tapset/linux/nd_syscalls.stp: Fix types and nesting for kexec_load * tapset/linux/syscalls.stp: Likewise * testsuite/buildok/nd_syscalls-detailed.stp: Test the flags_str variable * testsuite/buildok/syscalls-detailed.stp: Likewise * testsuite/systemtap.syscall/kexec_load.c: New testcase * testsuite/systemtap.syscall/set_tid_address.c: New testcase --- diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp index caaa76b88..a46e3d8ba 100644 --- a/tapset/linux/aux_syscalls.stp +++ b/tapset/linux/aux_syscalls.stp @@ -5595,3 +5595,38 @@ function _struct_sysinfo_u:string(uaddr:long) } } %} + +%{ +#include +static const _stp_val_array const _stp_kexec_flags_list[] = { + V(KEXEC_ON_CRASH), +#ifdef KEXEC_PRESERVE_CONTEXT + V(KEXEC_PRESERVE_CONTEXT), +#endif + V(KEXEC_ARCH_DEFAULT), + V(KEXEC_ARCH_386), + V(KEXEC_ARCH_X86_64), + V(KEXEC_ARCH_PPC), + V(KEXEC_ARCH_PPC64), + V(KEXEC_ARCH_IA_64), +#ifdef KEXEC_ARCH_ARM + V(KEXEC_ARCH_ARM), +#endif + V(KEXEC_ARCH_S390), + V(KEXEC_ARCH_SH), +#ifdef KEXEC_ARCH_MIPS_LE + V(KEXEC_ARCH_MIPS_LE), +#endif +#ifdef KEXEC_ARCH_MIPS + V(KEXEC_ARCH_MIPS), +#endif + {0, NULL} +}; +%} + +function _kexec_flags_str:string(flags:long) +%{ /* pure */ + unsigned long flags = (unsigned int)STAP_ARG_flags; + _stp_lookup_or_str(_stp_kexec_flags_list, flags, STAP_RETVALUE, MAXSTRINGLEN); +%} + diff --git a/tapset/linux/nd_syscalls.stp b/tapset/linux/nd_syscalls.stp index a1c076e2e..11589cd79 100644 --- a/tapset/linux/nd_syscalls.stp +++ b/tapset/linux/nd_syscalls.stp @@ -3032,8 +3032,8 @@ probe nd_syscall.ioprio_set.return = kprobe.function("sys_ioprio_set").return ? # struct compat_kexec_segment __user *segments, # unsigned long flags) # -probe nd_syscall.kexec_load = kprobe.function("compat_sys_kexec_load") ?, - kprobe.function("sys_kexec_load") ? +probe nd_syscall.kexec_load = __nd_syscall.kexec_load ?, + kprobe.function("compat_sys_kexec_load") ? { name = "kexec_load" asmlinkage() @@ -3041,14 +3041,23 @@ probe nd_syscall.kexec_load = kprobe.function("compat_sys_kexec_load") ?, nr_segments = ulong_arg(2) segments_uaddr = pointer_arg(3) flags = ulong_arg(4) - argstr = sprintf("%p, %d, %p, %d", entry, nr_segments, segments_uaddr, flags) + flags_str = _kexec_flags_str(flags) + argstr = sprintf("%p, %u, %p, %s", entry, nr_segments, segments_uaddr, flags_str) } -probe nd_syscall.kexec_load.return = kprobe.function("compat_sys_kexec_load").return ?, - kprobe.function("sys_kexec_load").return ? +probe __nd_syscall.kexec_load = kprobe.function("sys_kexec_load") +{ + @__syscall_gate_compat_simple +} +probe nd_syscall.kexec_load.return = __nd_syscall.kexec_load.return ?, + kprobe.function("compat_sys_kexec_load").return ? { name = "kexec_load" retstr = returnstr(1) } +probe __nd_syscall.kexec_load.return = kprobe.function("sys_kexec_load").return +{ + @__syscall_gate_compat_simple +} # keyctl _____________________________________________________ # long sys_keyctl(int option, diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp index 39e5dca15..d2cd10ac5 100644 --- a/tapset/linux/syscalls.stp +++ b/tapset/linux/syscalls.stp @@ -2842,22 +2842,31 @@ probe syscall.ioprio_set.return = kernel.function("sys_ioprio_set").return ? # struct compat_kexec_segment __user *segments, # unsigned long flags) # -probe syscall.kexec_load = kernel.function("compat_sys_kexec_load").call ?, - kernel.function("sys_kexec_load").call ? +probe syscall.kexec_load = __syscall.kexec_load.call, + kernel.function("compat_sys_kexec_load").call ? { name = "kexec_load" - entry = $entry - nr_segments = $nr_segments + entry = __ulong($entry) + nr_segments = __ulong($nr_segments) segments_uaddr = $segments - flags = $flags - argstr = sprintf("%p, %d, %p, %d", $entry, $nr_segments, $segments, $flags) + flags = __ulong($flags) + flags_str = _kexec_flags_str(flags) + argstr = sprintf("%p, %u, %p, %s", entry, nr_segments, segments_uaddr, flags_str) +} +probe __syscall.kexec_load.call = kernel.function("sys_kexec_load").call +{ + @__syscall_gate_compat_simple } -probe syscall.kexec_load.return = kernel.function("compat_sys_kexec_load").return ?, - kernel.function("sys_kexec_load").return ? +probe syscall.kexec_load.return = __syscall.syscall.kexec_load.return, + kernel.function("compat_sys_kexec_load").return ? { name = "kexec_load" retstr = return_str(1, $return) } +probe __syscall.syscall.kexec_load.return = kernel.function("sys_kexec_load").return +{ + @__syscall_gate_compat_simple +} # keyctl _____________________________________________________ # long sys_keyctl(int option, diff --git a/testsuite/buildok/nd_syscalls-detailed.stp b/testsuite/buildok/nd_syscalls-detailed.stp index 6ffda76db..b0f37183d 100755 --- a/testsuite/buildok/nd_syscalls-detailed.stp +++ b/testsuite/buildok/nd_syscalls-detailed.stp @@ -1037,7 +1037,8 @@ probe nd_syscall.ioprio_set.return ? probe nd_syscall.kexec_load ? { printf("%s, %s\n", name, argstr) - printf("%d, %d, %p, %d\n", entry, nr_segments, segments_uaddr, flags) + printf("%d, %u, %p, %d, %s\n", entry, nr_segments, segments_uaddr, + flags, flags_str) } probe nd_syscall.kexec_load.return ? { diff --git a/testsuite/buildok/syscalls-detailed.stp b/testsuite/buildok/syscalls-detailed.stp index 7d35d540a..01b9291ee 100755 --- a/testsuite/buildok/syscalls-detailed.stp +++ b/testsuite/buildok/syscalls-detailed.stp @@ -1035,7 +1035,8 @@ probe syscall.ioprio_set.return ? probe syscall.kexec_load ? { printf("%s, %s\n", name, argstr) - printf("%d, %d, %p, %d\n", entry, nr_segments, segments_uaddr, flags) + printf("%d, %u, %p, %d, %s\n", entry, nr_segments, segments_uaddr, + flags, flags_str) } probe syscall.kexec_load.return ? { diff --git a/testsuite/systemtap.syscall/kexec_load.c b/testsuite/systemtap.syscall/kexec_load.c new file mode 100644 index 000000000..03dc14a34 --- /dev/null +++ b/testsuite/systemtap.syscall/kexec_load.c @@ -0,0 +1,60 @@ +/* COVERAGE: kexec_load */ + +#define _GNU_SOURCE +#include +#include +#include + +static struct __user_cap_header_struct header; +static struct __user_cap_data_struct data; + +// KEXEC_LOAD(2): The required constants are in the Linux kernel source file +// linux/kexec.h, which is not currently exported to glibc. Therefore, these +// constants must be defined manually. + +// kexec flags for different usage scenarios +#define KEXEC_ON_CRASH 0x00000001 +// These values match the ELF architecture values. +#define KEXEC_ARCH_DEFAULT ( 0 << 16) +#define KEXEC_ARCH_386 ( 3 << 16) + +int main() +{ + // Ensure the syscall won't be able to succeed + header.version = _LINUX_CAPABILITY_VERSION; + header.pid = getpid(); + capget(&header, &data); + data.effective &= ~(1 << CAP_SYS_BOOT); + capset(&header, &data); + + // Test normal operation + syscall(__NR_kexec_load, NULL, 0, NULL, KEXEC_ON_CRASH|KEXEC_ARCH_386); + //staptest// [[[[kexec_load (0x0, 0, 0x0, KEXEC_ON_CRASH|KEXEC_ARCH_386)!!!!ni_syscall ()]]]] = NNNN + + // Limit testing + syscall(__NR_kexec_load, (unsigned long)-1, 0, NULL, KEXEC_ARCH_DEFAULT); +#if __WORDSIZE == 64 + //staptest// [[[[kexec_load (0xffffffffffffffff, 0, 0x0, KEXEC_ARCH_DEFAULT)!!!!ni_syscall ()]]]] = -NNNN +#else + //staptest// [[[[kexec_load (0xffffffff, 0, 0x0, KEXEC_ARCH_DEFAULT)!!!!ni_syscall ()]]]] = -NNNN +#endif + + syscall(__NR_kexec_load, NULL, (unsigned long)-1, NULL, KEXEC_ARCH_DEFAULT); +#if __WORDSIZE == 64 + //staptest// [[[[kexec_load (0x0, 18446744073709551615, 0x0, KEXEC_ARCH_DEFAULT)!!!!ni_syscall ()]]]] = -NNNN +#else + //staptest// [[[[kexec_load (0x0, 4294967295, 0x0, KEXEC_ARCH_DEFAULT)!!!!ni_syscall ()]]]] = -NNNN +#endif + + syscall(__NR_kexec_load, NULL, 0, (struct kexec_segment *)-1, KEXEC_ARCH_DEFAULT); +#ifdef __s390__ + //staptest// kexec_load (0x0, 0, 0x[7]?[f]+, KEXEC_ARCH_DEFAULT) = -NNNN +#else + //staptest// [[[[kexec_load (0x0, 0, 0x[f]+, KEXEC_ARCH_DEFAULT)!!!!ni_syscall ()]]]] = -NNNN +#endif + + syscall(__NR_kexec_load, NULL, 0, NULL, (unsigned long)-1); + //staptest// [[[[kexec_load (0x0, 0, 0x0, KEXEC_ON_CRASH|[^)]+)!!!!ni_syscall ()]]]] = -NNNN + + return 0; +} diff --git a/testsuite/systemtap.syscall/set_tid_address.c b/testsuite/systemtap.syscall/set_tid_address.c new file mode 100644 index 000000000..f1a433c9e --- /dev/null +++ b/testsuite/systemtap.syscall/set_tid_address.c @@ -0,0 +1,32 @@ +/* COVERAGE: set_tid_address */ + +#define _GNU_SOURCE +#include +#include + +int main() +{ + int i; + + // set_tid_address() is being called as a part of the testcase + // initialization. To ensure that our staptests are correctly + // matching code under test, we'll do the limit testing first. + // Using syscall() avoids link time issues. + + // Limit testing + syscall(__NR_set_tid_address, (int *)-1); +#ifdef __s390__ + //staptest// set_tid_address (0x[7]?[f]+) = NNNN +#else + //staptest// set_tid_address (0x[f]+) = NNNN +#endif + + // Test normal operation + syscall(__NR_set_tid_address, &i); + //staptest// set_tid_address (XXXX) = NNNN + + syscall(__NR_set_tid_address, NULL); + //staptest// set_tid_address (0x0) = NNNN + + return 0; +}