}
}
%}
+
+%{
+#include <linux/kexec.h>
+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);
+%}
+
# 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()
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,
# 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,
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 ?
{
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 ?
{
--- /dev/null
+/* COVERAGE: kexec_load */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/capability.h>
+
+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;
+}
--- /dev/null
+/* COVERAGE: set_tid_address */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+
+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;
+}