Frank Ch. Eigler [Sat, 30 Oct 2021 23:50:21 +0000 (19:50 -0400)]
staprun/relay.c: bypass compiler warning
Newly added code did a read(2), deliberately ignoring how many bytes
were read. Some gcc versions complain. Phrase the same operation
differently to make gcc happier.
Frank Ch. Eigler [Sat, 30 Oct 2021 19:21:31 +0000 (15:21 -0400)]
PR28449: fix cross-cpu message ordering
Correct unintended loss of cross-cpu message total-ordering via commit 8819e2a04596d by packetizing normal printf() traffic. This also
restores bulk mode / stap-merge operation to same as before. staprun
now has a builtin merge equivalent built on threads, with some
message-loss fault-tolerance. A new "dumpalot" test produces ample
output with varying "-s BUFFER" runs. While in the vicinity, the old
"relay_old.c" (<=rhel5) file is nuked; it was not even compiled.
William Cohen [Thu, 28 Oct 2021 20:13:56 +0000 (16:13 -0400)]
Adjust analysis code to compile with older Dyninst 9
The Block getInsn method and InsnLoc constructor have different
signature in older Dyninst 9. To hide those differences between
version of Dyninst just put the method invocation in the constructor
and let the compiler figure out which type the parameter is.
William Cohen [Thu, 28 Oct 2021 17:38:02 +0000 (13:38 -0400)]
Tolerate dyninst10's need for -lboost_system in analysis.cxx
The analysis code uses dyninst. As a result the new analysis code in
the translator will need to link in the boost_system library like
commit 891810c246d6de05a2df80c5b3e9f9aaa13231f7 does for stapdyn.
William Cohen [Wed, 27 Oct 2021 17:49:12 +0000 (13:49 -0400)]
Make the liveness warning 32-bit agnostic
On 32-bit platforms Dwarf_Addr is long long unsigned int which doesn't
match the %lx (long unsigned int) print format to print the warning.
Cast the variable as (void *) so %p format can be used to print its
value on both 32-bit and 64-bit platforms.
William Cohen [Wed, 13 Oct 2021 19:56:21 +0000 (15:56 -0400)]
Assert that anything other than 32-bit or 64-bit processors will not be seen
One last diagnostic print to remove. In this case the mapping between
dwarf register and Dyninst register name needs to take into account
whether this is 32-bit or 64-bit code. However, there is a default in
the switch case to catch the anything other than 4 or 8 bytes. If the
code see something other than one of those two values, something is
very wrong. Figured best to just have an assert stop things, so the
problem is examined.
William Cohen [Wed, 13 Oct 2021 19:27:30 +0000 (15:27 -0400)]
Add caching for the liveness data structure
Dyninst already caches information to make future queries at the same
location less expensive for an executable. Thus, it is enough for the
code to cache the LivenessAnalyzer data on a per executable basis.
This information is stored in the cachedLivenessInfo member of
LivenessAnalyzer class.
William Cohen [Thu, 30 Sep 2021 19:18:59 +0000 (15:18 -0400)]
Use the elf_path in mod_info as that always points to the executable
For kernel probes q.dw.module_name just lists "kernel" rather than
the actual path to the binary. The mod_info elf_path has more accurate
path to the actual executable, using that instead.
William Cohen [Fri, 24 Sep 2021 16:04:21 +0000 (12:04 -0400)]
Eliminate unnecessary CodeRegion discovery
Documentation on findFuncs method seemed to require a CodeRegion passed in.
However, Dyninst developers said in this case can just pass in a NULL
(https://github.com/dyninst/dyninst/issues/1102). Simplified
the code to eliminate the uneeded CodeRegion information.
William Cohen [Wed, 22 Sep 2021 21:34:25 +0000 (17:34 -0400)]
Do liveness analysis after location information set and use regno info
Initially the call to the liveness analysis was being done before
the location information was setup. Relocated the call after the
location information has been setup.
Corrected liveness analysis code to use the register number. Also
added print out the function the liveness analysis is being run on.
Note that for probes on inlined functions this name will be different
than the probe point function name, it will be the actual function
that the code was inlined into.
William Cohen [Tue, 21 Sep 2021 19:36:08 +0000 (15:36 -0400)]
Add support to handle 32-bit x86 binaries
Dyninst liveness analysis treats the analysis of 32-bit x86 and 64-bit
x86_64 code differently. In dyninst the register names are different.
Thus, trying to get the liveness results for rdi (the 64-bit register
name) on 32-bit analysis will fail. The analysis also needs to treat
32-bit and 64-bit a bit differently as there are difference in the
calling ABIs.
Right now the code dummy up using edi/rdi register which is the holds
the first argument in the register. Doing this because the
location_context cts doesn't hold information outside the variable name.
William Cohen [Mon, 20 Sep 2021 13:46:04 +0000 (09:46 -0400)]
Show the liveness information at points being probed
This code is work-in-progress and to check whether the liveness
analysis is working. Currently, the location context information for
the variable isn't being passed in and the setup of that is disabled.
William Cohen [Mon, 30 Aug 2021 18:32:57 +0000 (14:32 -0400)]
Update configure machinery and add files to hold Dyninst analysis
The analysis uses tooling in Dyninst to do the analysis. However,
Dyninst is not available for some architectures. Needed to make the
configuration machinery only enable the Dyninst-based analysis for
supported machines such as x86-64 and aarch64.
The analysis.cxx is not currently connected to anything and doesn't do
any analysis. For the moment it uses a couple Dyninst functions
verify that Dyninst libraries are being linked in. This has been
tested to compile on both architectures that support Dyninst (x86_64)
and do not support Dyninst (32-bit Arm).
William Cohen [Mon, 25 Oct 2021 15:32:46 +0000 (11:32 -0400)]
Update syscall_any number<->name maps to include syscallent-common.h entries.
Some syscalls information had been moved to syscallent-common.h in
the strace code. Need to use the #include in the syscallent*.h files
to get those entries.
William Cohen [Mon, 25 Oct 2021 15:23:47 +0000 (11:23 -0400)]
Pull in the includes to get strace syscall info from syscallent-common.h
There are now a number of syscall in strace that are described in
src/linux/generic/syscall-common.h which is pulled into a number of
different architecture syscallent*.h includes. Don't want to miss
those additional syscalls in the mappings.
Serguei Makarov [Thu, 14 Oct 2021 20:44:23 +0000 (16:44 -0400)]
stap_run.exp: accept 'WARNING: Child process exited due to signal'
This was causing numerous spurious FAIL outcomes on RHEL[89].
The extra "WARNING: Child process exited due to signal" is not an error,
it's merely stap communicating to the user that the child
process was interrupted, which is exactly what we do.
Not sure why it's printed on some systems and not others.
XXX There may be a deeper issue in that the tiny do-nothing binary
probed by the testcase (e.g. testsuite/systemtap.base/at_register.c)
was supposed to stop on its own and didn't.
Adding a delay to the first kill -INT $mypid makes the problem
more obvious.
Stan Cox [Wed, 13 Oct 2021 16:43:35 +0000 (12:43 -0400)]
Support softfloat by dyninst backend.
The softfloat library has conflicting types for some types defined in
stdint.h, which -dyninst includes, so avoid by using cpp to redefine
them. Add a float test to sdt_types.c. Only test dyninst with
V3_uprobe. Add x8664 float registers to register definition used by
dyninst.
Frank Ch. Eigler [Tue, 12 Oct 2021 15:41:32 +0000 (11:41 -0400)]
BZ2012907 systemtap.spec: use sysuser.d/* for user/group management
Newer systemd systems (Fedora 32+) have an a declarative mechanism for
creation of system users/groups, instead of groupadd/useradd calls in
the %pre scripts. Switch to this scheme for modern enough systems.
William Cohen [Mon, 11 Oct 2021 20:26:06 +0000 (16:26 -0400)]
Update syscall_num.stp mappings between syscall number and name
Need to generate new versions of syscall_num.stp files that include
the preprocessor architecture guards so multiple syscall_num.stp
can be used by BPF code at the same time.
William Cohen [Mon, 11 Oct 2021 20:17:41 +0000 (16:17 -0400)]
Allow multiple architecture syscall_num.stp files to be used by bpf backend
Systemtap's BPF still has the concept of target architecture and isn't
write once run anywhere for BPF code. Thus, to make the syscall_any
tapset work the tapset needs to have all the different architecture
initialization code available and select the appropriate one based on
the architecture. Thus, each syscalls_num.stp file has preprocessing
guards to make them empty unless the architecture matches.
William Cohen [Mon, 11 Oct 2021 19:49:33 +0000 (15:49 -0400)]
Update dump-syscalls.sh to work with newer strace-code
There have been some changes in the strace-code:
-Header files now in strace-code/src/linux/*/syscallent.h
-mips headers use BASE_NR and file needs to be massaged to get numeric value
-corrected the name of riscv architecture name to riscv64
There are lots of races when printing warnings/errors/dbugs in staprun
because multiple eprintf() calls are used to print a single message and
stderr is not line-buffered. As a result, warnings/errors/dbugs race with
the relayfs reader threads printing to stdout and with other stap scripts
running concurrently in the same PTY. This causes the messages printed to
stderr and stdout to be garbled.
Fix all of this by using a single eprintf() for each warning/error/dbug
message, and by making stderr line-buffered so that we don't need to worry
about differing libc implementations potentially flushing a single message
in chunks rather than flushing the whole message in one go.
Sultan Alsawaf [Thu, 30 Sep 2021 02:42:26 +0000 (19:42 -0700)]
runtime: make _stp_vlog() more robust to avoid truncating log messages
Currently, _stp_vlog() very readily drops or truncates warnings, errors,
and debug messages. In the case of warnings and errors, this is quite
problematic because these messages are of high importance and, as such,
are even sent to stapio via the control channel rather than the relay
transport.
The reason why _stp_vlog() truncates and even drops these messages so
easily is twofold: the normal print buffer is used directly without any
attempt to flush it when there isn't enough space and it's used as
temporary storage for warnings and errors.
When warnings and errors are sent to the control channel, they are
copied into a new buffer, which is wasteful due to the copy operation
and the effort put into scrounging for space in the print buffer.
Instead of using a temporary buffer to construct warnings and errors,
it's more reliable and efficient to construct the message in one of the
control channel's buffers that would've been used anyway to send the
message.
In the case of debug messages, the print buffer can take appropriate
steps to ensure there's enough space via _stp_reserve_bytes(). Now, the
length of a debug message is calculated before it's generated, making it
possible to use _stp_reserve_bytes().
Altogether, this makes _stp_vlog() very resistant to losing both normal
debug messages and high-priority warning and error messages.
Stan Cox [Thu, 30 Sep 2021 20:11:29 +0000 (16:11 -0400)]
PR27829: Support floating point values passed through sdt.h markers
Add the type to the individual arg entries in the .notes.stapsdt section;
currently SP@A, where S is optional '-' sign, P is precision of type and A is
address. Revised format is SPT@A where T is optional 'f' for float variables.
Add x8664 float registers xmm8 - xmm15 and aarch64 float registers v8 - v31.
Parse the type field; result is currently ignored. asm statements are
restricted to 30 arguments; sdt probes can have up to 12 arguments. To fit
this into a single asm statement, precision and type are encoded into a single
field: 0xSSTT where SS is the precision and TT is the type as encoded by
__builtin_classify_type. The sign S, precision P, and type T are decoded by
_SDT_SIGN, _SDT_SIZE, and _SDT_TYPE. Test that the revised
.notes.stapsdt section interacts correctly with eu-elfutils and gdb.
Make this test case operable without kernel debuginfo by using
@cast( ..., "kernel<header>") to extract iocb / iovec decls
from headers. Rename IO_CMD_* values to IOCB_CMD_* to match
linux aio_abi.h
Sultan Alsawaf [Fri, 17 Sep 2021 21:17:16 +0000 (14:17 -0700)]
Fix races in perf probe task finder callback
The task finder callback for a perf probe can run concurrently across
different tasks' workers, resulting in redundant registrations since
_stp_perf_init() and _stp_perf_del() lack synchronization. This results
in the redundant perf events never being removed and a use-after-free
scenario occurring in the kernel's core perf code after the stap module
is unloaded. Adding a mutex lock to the task finder callback fixes the
issue.
Di Chen [Thu, 2 Sep 2021 04:52:47 +0000 (12:52 +0800)]
The /* pc=0x... */ is no longer printed by "stap -v -L 'kernel.function("*")'
The disappeared /* pc=0x... */ resulted from the missing implementation
of the function "dwarf_derived_probe::printsig_nonest".
Which makes "p->printsig_nonest(sig)" in main.cxx end up calling
"derived_probe::printsig_nonest", and the type of "p" is
(gdb) ptype /m p
type = /* real type = dwarf_derived_probe * */
This patch added "dwarf_derived_probe::printsig_nonest" for PC value
print.
William Cohen [Tue, 14 Sep 2021 01:32:38 +0000 (21:32 -0400)]
Use task_state tapset function to avoid task_struct changes
The Linux 5.14 kernel's task_struct changed the state field to
__state. The task_state tapset function selects the appropriate
version. Make the scheduler.stp tapset and schedtimes.stp example use
the task_state function rather than directly trying to access the
task_struct state field (and get it wrong for newer kernels).
William Cohen [Mon, 17 May 2021 01:00:14 +0000 (09:00 +0800)]
Avoid generating problematic asynchronous unwind tables on RISC-V
By default SystemTap turns on the generations of asynchronous
unwind tables for all processor. When this was enabled for RISC-V
kernel modules would be generated, but the resulting kernel modules
would fail to load because the kernel's module loader could not
handle the R_RISCV_32_PCREL relocations in the .ko files.
Disabling the asynchronous unwind tables for RISC-V is a
work around to get things functioning for RISC-V.
There's a circular dependency because _stp_cleanup_and_exit() may send a
message over the control channel to indicate an issue, like with
_stp_warn(). The reordering thus causes this crash:
The original bug that the reorder attempted to fix is already fixed by 166a95089 ("runtime: fix panics when polling on the control channel
while unloading"). That commit doesn't allow delete_module() to run when
there are open file descriptors to the control channel, which guarantees
that the control channel cannot be in use during module cleanup. Thus,
we can simply restore the old ordering.
Sultan Alsawaf [Wed, 25 Aug 2021 02:27:43 +0000 (19:27 -0700)]
runtime: fix panics when polling on the control channel while unloading
When the stapio pselect() runs while the given stap module is unloading,
there's a use-after-free opportunity in do_select(). This occurs because
the control channel's poll function, _stp_ctl_poll_cmd(), passes a
pointer to a global variable along to do_select(), which can then
dereference the pointer after the stap module is unloaded.
Normally, this wouldn't be a problem because do_select() uses get_file()
and fput(), which respectively grab and release references to the module
owner specified in `file->f_op->owner`. However, procfs doesn't provide
any interface to pass in a module owner, and instead all procfs files
use an internal `struct file_operations` declared in fs/proc/inode.c.
As a result, we cannot bolster procfs files with module reference
count protection through any normal means, so we must inject a module
owner the hard way.
A module owner is now patched into the control channel's file ops when
the file is opened by making a copy of the existing file ops and then
setting the module owner inside the copy, which then replaces the old
`file->f_op` pointer. This neatly fixes the race because procfs *does*
guarantee that none of the procfs callback functions are still running
after an entry is removed, and because _stp_ctl_poll_cmd() cannot be
reached without first passing through _stp_ctl_open_cmd().
Since delete_module() can now return EWOULDBLOCK, we must make staprun
aware that it's not a fatal error and that the module deletion should
be retried. EWOULDBLOCK simply indicates that a pselect() on the control
channel has yet to finish, so it will go away after a brief wait.
This can be easily reproduced by having a background thread quickly loop
on trying to rmmod any stap modules, resulting in the module's exit
routine running concurrently with the STP_START command from stapio.
Closing the control channel before attempting clean-up fixes this race.
pr23478 WIP: rework bpf foreach to handle multi-key array
The major addition is a new ELF section giving details on each
foreach loop in the program, including where the sort column
is located within a composite key.
Previously all the foreach info was packed into a uint64_t
flags parameter to stapbpf's map_get_next_key userspace-only
helper function, which would not work for this nor for future
foreach work (sort_aggr, array slicing).
* bpf-internal.h (BPF_MAXKEYLEN,BPF_MAXKEYLEN_PLUS): new const.
(SORT_FLAGS etc): deprecate, but still read from old .bo files.
(globals::foreach_info): new struct with info for bpfinterp.cxx.
(globals::foreach_loop_info): vector of foreach_info structs.
(typedef interned_foreach_info): serialized foreach_info.
({intern,deintern}_loop_info): [de]serialize foreach_info.
(loop_idx): alias for index into foreach_loop_info vector.
* bpf-shared-globals.h ({intern,deintern}_loop_info): crudely
[de]serialize foreach_info by putting the fields in a vector.
* bpf-translate.cxx (bpf_unparser::visit_foreach_loop): change
to generate foreach_info, handle multi-key array iteration.
(output_foreach_info): serialize foreach_loop_info into a
new 'stapbpf_foreach_loop_info' ELF section.
(translate_bpf_pass): add 'stapbpf_foreach_loop_info' ELF section.
* stapbpf/stapbpf.cxx (foreach_loop_info): global table
of foreach loop information.
(load_bpf_file): load 'stapbpf_foreach_loop_info' ELF section.
(init_perf_transport): add foreach_loop_info to bpf_transport_context.
(main): add foreach_loop_info to bpf_transport_context.
* stapbpf/bpfinterp.h (struct bpf_transport_context): add
field for storing foreach_loop_info data.
(bpf_transport_context::bpf_transport_context): add
field for storing foreach_loop_info data.
* stapbpf/bpfinterp.cxx (struct foreach_state): represent an
in-progress foreach loop iteration including sorted values.
(foreach_info): alias for bpf::globals::foreach_info.
(foreach_state_add): new function.
(foreach_cmp_{str,int}): new functions.
(foreach_state_sort): new function.
(foreach_state_empty): new function.
(convert_key): new function.
(_foreach_state_next,foreach_state_next): new functions.
(foreach_state_cleanup): new function. Avoid C++ destructor.
(typedef foreach_stack): stack of foreach_state, used for
handling nested foreach loop iteration.
(map_get_next_key): rewrite to use foreach_info,foreach_state
and handle multi-key arrays (storing large keys in map_values).
(bpf_interpret): pass map_values to map_get_next_key, to be
used for storing composite keys in addition to values.
(struct map_keys): replaced by struct foreach_state.
(convert_{int,str}_{key,kp}): deleted functions.
(convert_{key,kp}): deleted functions.
(computed_key_size): deleted function.
(map_sort,map_next): deleted functions.
The testsuite has been observed to intermittently hang on 5.13+
generation kernels. This is caused by some test binaries (especially
recv*.c) suffering a segv and terminating, but their forked child
process pals still hanging around (indefinitely). This patch adds an
alarm(30) to each such test, so the children will burn twice as
bright, but half as long, or something.
releng: ditch custom pie/ssp CFLAGS engine in configure.ac
Just inherit the desired c*flags from autoconf via environment
variables from the distro spec files. This lets us automatically
benefit from centralized hardening flags on some distros. OTOH
distros without that now will need to add such settings to the build
scripts that invoke this configure script.
Linux commit ab3257042c2 makes it necessary for us to stop overriding
CONFIG_STACK_VALIDATION= (originally a workaround for a 2016 rawhide
bug). This fixes the tracepoints.stp test case.
Linux kbuild commit d936eb23874 sets $subject CFLAGS, so to play
catch-up, we also need to use gcc attribute(fallthrough) to label such
spots in switch() statements in our runtime / tapset. Tested on
linux5.14 gcc11 rawhide and linux3.10 gcc4 rhel7.
William Cohen [Tue, 20 Jul 2021 15:32:27 +0000 (11:32 -0400)]
PR27984: Adjust the address so dwfl_module_addrinfo finds correct function name
PR27984 discovered that the logic to determine when a location was
part of a partially inlined function was not operating correctly for
shared libraries. The existing systemtap.base/partial-inline.exp
verified that the test worked for executables, but shared libraries
include a non-zero bias that needs to be added in. Added code to get
the required bias and add it to the address so the correct name is
returned by dwfl_module_addrinfo.
PR27934: give fuller diagnosis for pass-5 probe-registration errors
While we cannot solve or prevent runtime probe registration errors, we
can help users understand them. Add a new warning::pass5 man page,
and point registration error messages at it.
PR27820 tapset/bpf/logging.stp: implement abort() tapset function
A more obsessively accurate implementation would add a check
equivalent to if (c->aborted) to the start of each probe,
but it would be an imperfect solution in any case.
PR27820 tapset/bpf/logging.stp: move bpf versions of functions
Follows the same scheme as what I instituted earlier for the
uconversions.stp tapsets: toplevel has functions common to
all 3 backends or common to lkm+dyninst (guarded by a
runtime != "bpf" conditional). BPF implementations are
moved to tapset/bpf.
* tapset/bpf/logging.stp: New file.
* logging.stp: Move bpf versions of functions.
Sultan Alsawaf [Mon, 12 Jul 2021 20:31:36 +0000 (15:31 -0500)]
task_finder_vma: add autoconf check for hlist_add_tail_rcu()
The 3.10 version check for hlist_add_tail_rcu() only works for RHEL
kernels. Kernels older than 4.7 that lack the hlist_add_tail_rcu() backport
won't compile (such as Debian kernels). Add an autoconf stub to know for
certain if hlist_add_tail_rcu() is present.
Sultan Alsawaf [Mon, 12 Jul 2021 20:01:57 +0000 (16:01 -0400)]
Don't fail vma tracking mmap callback if module is already known.
An -EEXIST returned by stap_add_vma_map_info() just indicates that the
module is currently in stap's vma cache; it isn't a real issue. Calling
_stp_error() when this occurs causes stap to exit when there isn't a
real bug. Ignore the -EEXIST error to avoid breakage.