summaryrefslogtreecommitdiff
blob: fabe953189d0cfb8a79def0a31a028b161ae5ade (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# Copyright 2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit edo flag-o-matic linux-info systemd toolchain-funcs udev

DESCRIPTION="Dynamic BPF-based system-wide tracing tool"
HOMEPAGE="https://github.com/oracle/dtrace-utils https://wiki.gentoo.org/wiki/DTrace"

if [[ ${PV} == 9999 ]]; then
	EGIT_BRANCH="devel"
	EGIT_REPO_URI="https://github.com/oracle/dtrace-utils"
	inherit git-r3
else
	SRC_URI="https://github.com/oracle/dtrace-utils/archive/refs/tags/${PV}.tar.gz -> ${P}.tar.gz"
	S="${WORKDIR}"/dtrace-utils-${PV}

	KEYWORDS="-* ~amd64 ~arm64"
fi

LICENSE="UPL-1.0"
SLOT="0"
IUSE="systemd test-install"

# XXX: right now, we auto-adapt to whether multilibs are present:
# should we force them to be? how?
#
# TODO: can we make the wireshark dep conditional?
DEPEND="
	dev-libs/elfutils
	dev-libs/libbpf
	dev-libs/libpfm:=
	net-analyzer/wireshark[dumpcap]
	net-libs/libpcap
	>=sys-fs/fuse-3.2.0:3
	>=sys-libs/binutils-libs-2.42:=
	sys-libs/zlib
	systemd? ( sys-apps/systemd )
"
RDEPEND="
	${DEPEND}
	!dev-debug/systemtap[dtrace-symlink(+)]
	net-analyzer/wireshark
	test-install? (
		app-alternatives/bc
		app-editors/vim-core
		dev-build/make
		dev-lang/perl
		dev-util/perf
		net-fs/nfs-utils
		sys-apps/coreutils
		sys-fs/xfsprogs
		sys-process/time
		virtual/jdk
		virtual/perl-IO-Socket-IP
	)
"
BDEPEND="
	dev-build/make
	sys-apps/gawk
	sys-devel/bison
	>=sys-devel/bpf-toolchain-14.1.0
	sys-devel/flex
"
# This isn't yet optional, valgrind.h is included unconditionally
# https://github.com/oracle/dtrace-utils/issues/80
DEPEND+=" dev-debug/valgrind"

QA_PRESTRIPPED="
	usr/.*/dtrace/testsuite/test/triggers/.*
"
QA_FLAGS_IGNORED="
	usr/.*/dtrace/testsuite/test/triggers/.*
"

# TODO: report upstream (bug #938221) although it seems like it's
# not relevant given it's a BPF object.
QA_EXECSTACK="
	usr/*/dtrace/bpf_dlib.*
"

pkg_pretend() {
	# TODO: optional kernel patches

	# Basics for debugging information, BPF
	local CONFIG_CHECK="~BPF ~DEBUG_INFO_BTF ~KALLSYMS_ALL"

	CONFIG_CHECK+=" ~CUSE"

	# Tracing
	CONFIG_CHECK+=" ~TRACING"
	CONFIG_CHECK+=" ~UPROBES ~UPROBE_EVENTS"
	CONFIG_CHECK+=" ~FTRACE ~FTRACE_SYSCALLS ~DYNAMIC_FTRACE ~FUNCTION_TRACER"
	CONFIG_CHECK+=" ~FPROBE"
	# DTrace can fallback to kprobes for fbt but people often want them off
	# for security and newer kernels work fine with BPF for that, so
	# let's omit it. kprobes are slower and scale poorly.

	# https://gcc.gnu.org/PR84052
	CONFIG_CHECK+=" !GCC_PLUGIN_RANDSTRUCT"

	if use test-install ; then
		# See test/modules
		CONFIG_CHECK+=" ~EXT4_FS ~ISO9660_FS ~NFS_FS ~RDS ~TUN"
	fi

	check_extra_config
}

pkg_setup() {
	eval unset ${!LC_*} LANG
}

src_configure() {
	if tc-is-cross-compiler; then
		die "DTrace does not yet support cross-compilation."
	fi

	tc-export CC

	# https://github.com/oracle/dtrace-utils/issues/78
	tc-enables-fortify-source && append-cppflags -U_FORTIFY_SOURCE

	# lld does this by default, so fix that, although lld fails anyway...
	# 'LIBDTRACE_1.0' to symbol 'dtrace_provider_modules' failed: symbol not defined
	append-ldflags $(test-flags-CCLD -Wl,--undefined-version)
	# mold and lld can't cope with some relocation types used, e.g.
	#  'test-triggers--usdt-tst-forker-prov.o:(.SUNW_dof): unknown relocation: R_X86_64_GLOB_DAT'
	tc-ld-force-bfd

	# -fno-semantic-interposition seems to lead to a broken dtrace
	# that can't actually obtain results from probes, even trivial examples
	# just hang.
	filter-flags -fno-semantic-interposition
	# https://github.com/oracle/dtrace-utils/issues/86
	filter-lto

	local confargs=(
		# TODO: Maybe we should set the UNPRIV_UID to something? -3 is a bit... kludgy
		--prefix="${EPREFIX}"/usr
		# See https://github.com/oracle/dtrace-utils/issues/106 for man8 suffix
		--mandir="${EPREFIX}"/usr/share/man/man8
		--docdir="${EPREFIX}"/usr/share/doc/${PF}
		HAVE_LIBCTF=yes
		HAVE_LIBSYSTEMD=$(usex systemd)
		HAVE_BPFV3=yes
	)

	edo ./configure "${confargs[@]}"
}

src_compile() {
	# -j1: https://github.com/oracle/dtrace-utils/issues/82
	emake verbose=1 -j1 $(usev !test-install TRIGGERS='')
}

src_test() {
	# Needs root and is also very time-consuming
	:;
}

src_install() {
	emake DESTDIR="${D}" -j1 install $(usev test-install install-test)

	# Stripping the BPF libs breaks them
	dostrip -x "/usr/$(get_libdir)"

	# It's a binary (TODO: move it?)
	docompress -x /usr/share/doc/${PF}/showUSDT

	newinitd "${FILESDIR}"/dtprobed.init dtprobed
}

pkg_postinst() {
	# We need a udev reload to pick up the CUSE device node rules.
	udev_reload

	if [[ -n ${REPLACING_VERSIONS} ]]; then
		# TODO: Make this more intelligent wrt comparison
		# One option for this is to detect when it's needed (DOF stash layout changes)
		# and then e.g. sleep and restart for the user.
		if systemd_is_booted ; then
			einfo "Restart the DTrace 'dtprobed' service after upgrades once all dtraces are stopped with:"
			einfo " systemctl try-restart dtprobed"
		else
			einfo "Restart the DTrace 'dtprobed' service after upgrades once all dtraces are stopped with:"
			einfo " /etc/init.d/dtprobed restart"
		fi
	else
		einfo "See https://wiki.gentoo.org/wiki/DTrace for getting started."

		# We can't do magic for people with ROOT=.
		if [[ -n ${ROOT} ]] ; then
			einfo "Enable and start the DTrace 'dtprobed' service for systemd with:"
			einfo " systemctl enable --now dtprobed"
			einfo
			einfo "Enable and start the DTrace 'dtprobed' service for OpenRC with:"
			einfo " rc-update add dtprobed"
			einfo " /etc/init.d/dtprobed start"
			return
		fi

		# For first installs, we enable the service and start it.
		#
		# This is unusual, but the behaviour without dtprobed running
		# is untested/unsupported. It's not a network service, it
		# has no configuration, reads a single device node, and
		# does all parsing within a seccomp jail. It also leads
		# to hard-to-diagnose issues because USDT probes won't
		# be registered and an application might have already
		# started up which needs to be traced.
		if systemd_is_booted ; then
			ebegin "Enabling & starting DTrace 'dtprobed' service"
			systemctl enable --now dtprobed
			eend $?
		else
			ebegin "Enabling DTrace 'dtprobed' service"
			rc-update add dtprobed
			eend $?

			ebegin "Starting DTrace 'dtprobed' service"
			rc-service start dtprobed
			eend $?
		fi
	fi
}

pkg_postrm() {
	udev_reload
}