diff --git a/rhbz1941722.patch b/rhbz1941722.patch new file mode 100644 index 0000000..073afcf --- /dev/null +++ b/rhbz1941722.patch @@ -0,0 +1,447 @@ +commit ea81249b90b92a589d304c051efbc5bbad7ce073 +Author: Frank Ch. Eigler +Date: Thu Jan 28 22:12:48 2021 -0500 + + PR27273: port to linux 5.11 + + Main change is removal/movement of TIF_IA32 in linux commit ff170cd05953 + and nearby. Now using single a central wrapper _stp_is_compat_task() and + _stp_is_compat_task2() functions, instead of sprinkling + test_tsk_thread_flag(...) around the code base. + + Also, suppressing CONFIG_DEBUG_INFO_BTF_MODULES generation for stap + modules, for diagnostic noise reduction. + +diff --git a/buildrun.cxx b/buildrun.cxx +index e36fd930fd14..05248078c44e 100644 +--- a/buildrun.cxx ++++ b/buildrun.cxx +@@ -116,6 +116,9 @@ make_any_make_cmd(systemtap_session& s, const string& dir, const string& target) + // PR13847: suppress debuginfo creation by default + "CONFIG_DEBUG_INFO=", + ++ // linux 5.11 wants btf but no, baby, no ++ "CONFIG_DEBUG_INFO_BTF_MODULES=", ++ + // RHBZ1321628: suppress stack validation; expected to be temporary + "CONFIG_STACK_VALIDATION=", + }; +diff --git a/runtime/compatdefs.h b/runtime/compatdefs.h +index ced68b1c8709..0bca4f67da5a 100644 +--- a/runtime/compatdefs.h ++++ b/runtime/compatdefs.h +@@ -10,47 +10,50 @@ + #ifndef _STP_COMPAT_H_ /* -*- linux-c -*- */ + #define _STP_COMPAT_H_ + +-#ifdef CONFIG_COMPAT +- +-/* x86_64 has a different flag name from all other arches and s390... */ ++#if defined(CONFIG_COMPAT) + #include +-#if defined (__x86_64__) +- #define TIF_32BIT TIF_IA32 +-#endif +-#if defined(__s390__) || defined(__s390x__) +- #define TIF_32BIT TIF_31BIT +-#endif +-#if defined (__mips__) && !defined(TIF_32BIT) +- #ifdef CONFIG_MIPS32_O32 +- #define TIF_32BIT TIF_32BIT_REGS +- #elif defined(CONFIG_MIPS32_N32) +- #define TIF_32BIT TIF_32BIT_ADDR +- #endif +-#endif + +-#if !defined(TIF_32BIT) +-#error architecture not supported, no TIF_32BIT flag +-#endif + + /* _stp_is_compat_task - returns true if this is a 32-on-64 bit user task. + Note that some kernels/architectures define a function called + is_compat_task(), but that just tests for being inside a 32bit compat + syscall. We want to test whether the current task is a 32 bit compat + task itself.*/ +-static inline int _stp_is_compat_task(void) ++static inline int _stp_is_compat_task2(struct task_struct* tsk) + { +- return test_thread_flag(TIF_32BIT); ++/* x86_64 has a different flag name from all other arches and s390... */ ++#if defined (__x86_64__) && defined(TIF_IA32) ++ return test_tsk_thread_flag(tsk, TIF_IA32); ++#elif defined (__x86_64__) /* post TIF_IA32 */ ++ return (tsk->mm && (tsk->mm->context.flags & MM_CONTEXT_UPROBE_IA32)); ++#elif defined(__s390__) || defined(__s390x__) ++ return test_tsk_thread_flag(tsk, TIF_31BIT); ++#elif defined (__mips__) && !defined(TIF_32BIT) ++ #ifdef CONFIG_MIPS32_O32 ++ return test_tsk_thread_flag(tsk, TIF_32BIT_REGS); ++ #elif defined(CONFIG_MIPS32_N32) ++ return test_tsk_thread_flag(tsk, TIF_32BIT_ADDR); ++ #endif ++#else ++#error architecture not supported, no TIF_32BIT flag? ++#endif + } +- + #else + +-static inline int _stp_is_compat_task(void) ++static inline int _stp_is_compat_task2(struct task_struct* tsk) + { + return 0; + } + + #endif /* CONFIG_COMPAT */ + ++static inline int _stp_is_compat_task(void) ++{ ++ return _stp_is_compat_task2(current); ++} ++ ++ ++ + /* task_pt_regs is used in some core tapset functions, so try to make + * sure something sensible is defined. task_pt_regs is required for + * the tracehook interface api so is normally defined already. +diff --git a/runtime/linux/regs.c b/runtime/linux/regs.c +index 7d28e68f9c3b..5bcd1031c731 100644 +--- a/runtime/linux/regs.c ++++ b/runtime/linux/regs.c +@@ -346,7 +346,7 @@ static int _stp_probing_app_with_32bit_regs(struct pt_regs *regs) + if (!regs) + return 0; + return (user_mode(regs) && +- test_tsk_thread_flag(current, TIF_32BIT_REGS)); ++ _stp_is_compat_task()); + } + + void _stp_print_regs(struct pt_regs * regs) +diff --git a/runtime/linux/uprobes2/uprobes_x86.h b/runtime/linux/uprobes2/uprobes_x86.h +index f88a87daa763..21ddc25a7419 100644 +--- a/runtime/linux/uprobes2/uprobes_x86.h ++++ b/runtime/linux/uprobes2/uprobes_x86.h +@@ -38,7 +38,7 @@ typedef u8 uprobe_opcode_t; + #ifdef CONFIG_X86_32 + #define SLOT_IP(tsk) 12 + #else +-#define SLOT_IP(tsk) (test_tsk_thread_flag(tsk, TIF_IA32) ? 12 : 16) ++#define SLOT_IP(tsk) (_stp_is_compat_task2(tsk) ? 12 : 16) + #endif + + #define BREAKPOINT_SIGNAL SIGTRAP +@@ -111,7 +111,7 @@ static inline unsigned long arch_get_cur_sp(struct pt_regs *regs) + static inline unsigned long arch_predict_sp_at_ret(struct pt_regs *regs, + struct task_struct *tsk) + { +- if (test_tsk_thread_flag(tsk, TIF_IA32)) ++ if (_stp_is_compat_task2(tsk)) + return (unsigned long) (regs->sp + 4 + STRUCT_RETURN_SLOP); + else + return (unsigned long) (regs->sp + 8); +diff --git a/runtime/sym.c b/runtime/sym.c +index 521aebe48eb8..1527a9a3dbdd 100644 +--- a/runtime/sym.c ++++ b/runtime/sym.c +@@ -142,7 +142,7 @@ static struct _stp_module *_stp_umod_lookup(unsigned long addr, + void *user = NULL; + #ifdef CONFIG_COMPAT + /* Handle 32bit signed values in 64bit longs, chop off top bits. */ +- if (test_tsk_thread_flag(task, TIF_32BIT)) ++ if (_stp_is_compat_task2(task)) + addr &= ((compat_ulong_t) ~0); + #endif + if (stap_find_vma_map_info(task->group_leader, addr, +@@ -181,8 +181,8 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, + /* Handle 32bit signed values in 64bit longs, chop off top bits. + _stp_umod_lookup does the same, but we need it here for the + binary search on addr below. */ +- if (test_tsk_thread_flag(task, TIF_32BIT)) +- addr &= ((compat_ulong_t) ~0); ++ if (_stp_is_compat_task2(task)) ++ addr &= ((compat_ulong_t) ~0); + #endif + m = _stp_umod_lookup(addr, task, modname, &vm_start, &vm_end); + if (m) +@@ -376,8 +376,8 @@ unsigned long _stp_linenumber_lookup(unsigned long addr, struct task_struct *tas + unsigned long vm_end = 0; + #ifdef CONFIG_COMPAT + /* Handle 32bit signed values in 64bit longs, chop off top bits. */ +- if (test_tsk_thread_flag(task, TIF_32BIT)) +- addr &= ((compat_ulong_t) ~0); ++ if (_stp_is_compat_task2(task)) ++ addr &= ((compat_ulong_t) ~0); + #endif + m = _stp_umod_lookup(addr, task, &modname, &vm_start, &vm_end); + } +diff --git a/runtime/syscall.h b/runtime/syscall.h +index 8a1566afee4f..6b4b3071a724 100644 +--- a/runtime/syscall.h ++++ b/runtime/syscall.h +@@ -35,19 +35,19 @@ + #define __MUNMAP_SYSCALL_NO_X86_64 11 + #define __MREMAP_SYSCALL_NO_X86_64 25 + # if defined(CONFIG_IA32_EMULATION) +-#define MMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \ ++#define MMAP_SYSCALL_NO(tsk) (_stp_is_compat_task2(tsk) \ + ? __MMAP_SYSCALL_NO_IA32 \ + : __MMAP_SYSCALL_NO_X86_64) +-#define MMAP2_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \ ++#define MMAP2_SYSCALL_NO(tsk) (_stp_is_compat_task2(tsk) \ + ? __MMAP2_SYSCALL_NO_IA32 \ + : __MMAP2_SYSCALL_NO_X86_64) +-#define MPROTECT_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \ ++#define MPROTECT_SYSCALL_NO(tsk) (_stp_is_compat_task2(tsk) \ + ? __MPROTECT_SYSCALL_NO_IA32 \ + : __MPROTECT_SYSCALL_NO_X86_64) +-#define MUNMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \ ++#define MUNMAP_SYSCALL_NO(tsk) (_stp_is_compat_task2(tsk) \ + ? __MUNMAP_SYSCALL_NO_IA32 \ + : __MUNMAP_SYSCALL_NO_X86_64) +-#define MREMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_IA32)) \ ++#define MREMAP_SYSCALL_NO(tsk) (_stp_is_compat_task2(tsk) \ + ? __MREMAP_SYSCALL_NO_IA32 \ + : __MREMAP_SYSCALL_NO_X86_64) + # else +@@ -279,7 +279,7 @@ syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) + // an argument and then returned won't compare correctly anymore. So, + // for now, disable this code. + # if 0 +- if (test_tsk_thread_flag(task, TIF_IA32)) ++ if (_stp_is_compat_task2(task)) + // Sign-extend the value so (int)-EFOO becomes (long)-EFOO + // and will match correctly in comparisons. + regs->ax = (long) (int) regs->ax; +@@ -345,7 +345,7 @@ _stp_syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + #endif + #elif defined(__x86_64__) + #ifdef CONFIG_IA32_EMULATION +- if (test_tsk_thread_flag(task, TIF_IA32)) { ++ if (_stp_is_compat_task2(task)) { + switch (i) { + #if defined(STAPCONF_X86_UNIREGS) + case 0: +diff --git a/session.cxx b/session.cxx +index 96719e5db79c..5d376380434f 100644 +--- a/session.cxx ++++ b/session.cxx +@@ -494,7 +494,7 @@ systemtap_session::version () + "Copyright (C) 2005-2020 Red Hat, Inc. and others\n" // PRERELEASE + "This is free software; see the source for copying conditions.\n", + version_string().c_str()); +- cout << _F("tested kernel versions: %s ... %s\n", "2.6.32", "5.10.0-rc"); // PRERELEASE ++ cout << _F("tested kernel versions: %s ... %s\n", "2.6.32", "5.11.0-rc"); // PRERELEASE + + cout << _("enabled features:") + #ifdef HAVE_AVAHI + +commit 65bed2e17ecd31ec9e061435a28059fe2b3e3e0c +Author: Frank Ch. Eigler +Date: Fri Jan 29 20:54:42 2021 +0000 + + PR27273: port to linux 5.11, kretprobes + + Linux commit d741bf41d7c changed how kretprobe_instances can + find their kretprobes. Adapt with an autoconf and wrapper + function. + +diff --git a/buildrun.cxx b/buildrun.cxx +index 05248078c44e..e0d69a5f730e 100644 +--- a/buildrun.cxx ++++ b/buildrun.cxx +@@ -378,6 +378,7 @@ compile_pass (systemtap_session& s) + output_autoconf(s, o, cs, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL); + output_autoconf(s, o, cs, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL); + output_autoconf(s, o, cs, "autoconf-hlist-4args.c", "STAPCONF_HLIST_4ARGS", NULL); ++ output_autoconf(s, o, cs, "autoconf-get-kretprobe.c", "STAPCONF_GET_KRETPROBE", NULL); + output_exportconf(s, o2, "tsc_khz", "STAPCONF_TSC_KHZ"); + output_exportconf(s, o2, "cpu_khz", "STAPCONF_CPU_KHZ"); + output_exportconf(s, o2, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS"); +diff --git a/runtime/compatdefs.h b/runtime/compatdefs.h +index 0bca4f67da5a..44807518f31d 100644 +--- a/runtime/compatdefs.h ++++ b/runtime/compatdefs.h +@@ -104,4 +104,14 @@ static inline int _stp_task_pt_regs_valid(struct task_struct *task, + return 0; + } + ++ ++#ifndef STAPCONF_GET_KRETPROBE ++/* prior to linux commit d741bf41d7c7db4898 */ ++static inline struct kretprobe* get_kretprobe(struct kretprobe_instance *inst) ++{ ++ return inst->rp; ++} ++#endif ++ ++ + #endif /* _STP_COMPAT_H_ */ +diff --git a/runtime/linux/autoconf-get-kretprobe.c b/runtime/linux/autoconf-get-kretprobe.c +new file mode 100644 +index 000000000000..ae5b4ab517b8 +--- /dev/null ++++ b/runtime/linux/autoconf-get-kretprobe.c +@@ -0,0 +1,6 @@ ++#include ++ ++void* foo(struct kretprobe_instance* ri) ++{ ++ return get_kretprobe(ri); ++} +diff --git a/tapsets.cxx b/tapsets.cxx +index b1a0e83d3d66..db75a4f62044 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -6274,7 +6274,7 @@ generic_kprobe_derived_probe_group::emit_module_decls (systemtap_session& s) + s.op->newline(); + s.op->newline() << "static int enter_kretprobe_common (struct kretprobe_instance *inst,"; + s.op->line() << " struct pt_regs *regs, int entry) {"; +- s.op->newline(1) << "struct kretprobe *krp = inst->rp;"; ++ s.op->newline(1) << "struct kretprobe *krp = get_kretprobe(inst);"; + + // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS + s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_kprobes)/sizeof(struct stap_kprobe);"; +@@ -6302,7 +6302,7 @@ generic_kprobe_derived_probe_group::emit_module_decls (systemtap_session& s) + s.op->newline() << "{"; + s.op->newline(1) << "unsigned long kprobes_ip = REG_IP(c->kregs);"; + s.op->newline() << "if (entry)"; +- s.op->newline(1) << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);"; ++ s.op->newline(1) << "SET_REG_IP(regs, (unsigned long) get_kretprobe(inst)->kp.addr);"; + s.op->newline(-1) << "else"; + s.op->newline(1) << "SET_REG_IP(regs, (unsigned long)inst->ret_addr);"; + s.op->newline(-1) << "(sp->ph) (c);"; + +commit 676c0b9096208edac2299f4c6d150fcb3959f678 +Author: Frank Ch. Eigler +Date: Fri Jan 29 20:54:42 2021 +0000 + + PR27273: port to linux 5.11, kretprobes - unwinding + + Missed one. + +diff --git a/runtime/linux/regs.c b/runtime/linux/regs.c +index 5bcd1031c731..26423164b78f 100644 +--- a/runtime/linux/regs.c ++++ b/runtime/linux/regs.c +@@ -36,7 +36,7 @@ + * @param ri Pointer to the struct kretprobe_instance. + * @return The function's address + */ +-#define _stp_probe_addr_r(ri) (ri->rp->kp.addr) ++#define _stp_probe_addr_r(ri) (get_kretprobe(ri)->kp.addr) + + #if defined (__x86_64__) + + +commit 932d93c9be45c96ab818301d3cf6c0cf7b8cb157 +Author: William Cohen +Date: Sun Jan 31 22:16:49 2021 -0500 + + Add CONFIG_COMPAT 32-bit support for aarch64 and powerpc + + The aarch64 and powerpc kernels may be built with support for 32-bit + user-space applications. On Fedora 33 the aarch64 kernel is + configured with CONFIG_COMPAT enabled. Needed to provide some support + in _stp_is_compat_task2 for the aarch64. The Fedora 33 ppc64le + kernels by default do not have CONFIG_COMPAT enabled, but included + similar check in there for powerpc in case locally built kernels + enable it. + +diff --git a/runtime/compatdefs.h b/runtime/compatdefs.h +index 44807518f31d..fc099215fcbe 100644 +--- a/runtime/compatdefs.h ++++ b/runtime/compatdefs.h +@@ -34,6 +34,8 @@ static inline int _stp_is_compat_task2(struct task_struct* tsk) + #elif defined(CONFIG_MIPS32_N32) + return test_tsk_thread_flag(tsk, TIF_32BIT_ADDR); + #endif ++#elif defined (__aarch64__) || defined(__powerpc__) ++ return test_tsk_thread_flag(tsk, TIF_32BIT); + #else + #error architecture not supported, no TIF_32BIT flag? + #endif + +commit 799d26992ca6ef880b57e867896b20c1e602c76d +Author: Frank Ch. Eigler +Date: Sat Feb 6 21:09:24 2021 -0500 + + PR27361 part 1: enable typequery result memoization & operation on linux 5.11 + + Linux 5.11 rejects previous kmod_typequery .c files because they don't + have a MODULE_LICENSE bit. Here, stap tries and tries and tries + building kmod_typequery files, up to thousands (!). We solve the + first by adding the MODULE_LICENSE. We solve the second by memoizing + typequery build results (whether they succeed or fail) in the + systemtap_session object. + +diff --git a/buildrun.cxx b/buildrun.cxx +index 42f2908d3db2..9408dcb2c345 100644 +--- a/buildrun.cxx ++++ b/buildrun.cxx +@@ -1116,9 +1116,14 @@ make_typequery_kmod(systemtap_session& s, const vector& headers, string& + omf << "obj-m := " + basename + ".o" << endl; + omf.close(); + +- // create our empty source file ++ // create our -nearly- empty source file + string source(dir + "/" + basename + ".c"); + ofstream osrc(source.c_str()); ++ ++ // this is mandated by linux kbuild as of 5.11+ ++ osrc << "#include " << endl; ++ osrc << "MODULE_LICENSE(\"GPL\");" << endl; ++ + osrc.close(); + + // make the module +@@ -1165,6 +1170,13 @@ make_typequery_umod(systemtap_session& s, const vector& headers, string& + int + make_typequery(systemtap_session& s, string& module) + { ++ // check our memoized cache first ++ if (s.typequery_memo.find(module) != s.typequery_memo.end()) ++ { ++ module = s.typequery_memo.at(module); ++ return 0; ++ } ++ + int rc; + string new_module; + vector headers; +@@ -1192,6 +1204,10 @@ make_typequery(systemtap_session& s, string& module) + else + rc = make_typequery_umod(s, headers, new_module); + ++ // memoize the result --- even if it failed (rc != 0), so as to avoid ++ // repeated attempts to rebuild the same thing ++ s.typequery_memo[module] = new_module; ++ + if (!rc) + module = new_module; + +diff --git a/session.cxx b/session.cxx +index 5d376380434f..8ebac38ce2d7 100644 +--- a/session.cxx ++++ b/session.cxx +@@ -377,6 +377,7 @@ systemtap_session::systemtap_session (const systemtap_session& other, + no_global_var_display = other.no_global_var_display; + pass_1a_complete = other.pass_1a_complete; + timeout = other.timeout; ++ // don't bother copy typequery_memo + + include_path = other.include_path; + runtime_path = other.runtime_path; +diff --git a/session.h b/session.h +index 38f1d66def1a..c2c6fbaad7d2 100644 +--- a/session.h ++++ b/session.h +@@ -239,7 +239,8 @@ struct systemtap_session + bool monitor; + int monitor_interval; + int timeout; // in ms +- ++ std::map typequery_memo; ++ + enum + { dump_none, // no dumping requested + dump_probe_types, // dump standard tapset probes diff --git a/systemtap.spec b/systemtap.spec index a6df408..8cddd84 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -89,7 +89,7 @@ Name: systemtap Version: 4.4 -Release: 3%{?release_override}%{?dist} +Release: 4%{?release_override}%{?dist} # for version, see also configure.ac @@ -125,6 +125,8 @@ License: GPLv2+ URL: http://sourceware.org/systemtap/ Source: ftp://sourceware.org/pub/systemtap/releases/systemtap-%{version}.tar.gz +Patch0: rhbz1941722.patch + # Build* BuildRequires: gcc-c++ BuildRequires: cpio @@ -511,6 +513,7 @@ systemtap-runtime-virthost machine to execute systemtap scripts. %prep %setup -q +%patch0 -p1 %build @@ -1230,6 +1233,9 @@ done # PRERELEASE %changelog +- Mon Mar 22 2021 Frank Ch. Eigler - 4.4-4 +- Add kernel 5.11 compatibility backports + * Wed Feb 10 2021 Frank Ch. Eigler - 4.4-3 - Add debuginfod client-lib prereq for buildid probing