# Oracle Linux DTrace.
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.

BUILDLIBS += libdtrace-build
libdtrace-build_CPPFLAGS = -Ilibdtrace -Ilibproc -Ilibcommon -Iuts/intel -Ilibdtrace/$(ARCHINC) \
                           -DDTRACE_LIBDIR="\"$(LIBDIR)/dtrace\"" -DDTRACE_USER_UID=$(USER_UID) \
                           -DUNPRIV_UID=$(UNPRIV_UID) -DDUMPCAP_GROUP=\"$(DUMPCAP_GROUP)\" \
                           -DUNPRIV_HOME=\"$(UNPRIV_HOME)\"
libdtrace-build_TARGET = libdtrace
libdtrace-build_DIR := $(current-dir)
libdtrace-build_SOURCES = dt_aggregate.c \
			  dt_as.c \
			  dt_bpf.c \
			  dt_btf.c \
			  dt_buf.c \
			  dt_cc.c \
			  dt_cg.c \
			  dt_conf.c \
			  dt_consume.c \
			  dt_debug.c \
			  dt_decl.c \
			  dt_dis.c \
			  dt_dlibs.c \
			  dt_dof.c \
			  dt_error.c \
			  dt_errtags.c \
			  dt_grammar.c \
			  dt_handle.c \
			  dt_ident.c \
			  dt_lex.c \
			  dt_link.c \
			  dt_kernel_module.c \
			  dt_map.c \
			  dt_module.c \
			  dt_open.c \
			  dt_options.c \
			  dt_parser.c \
			  dt_pcap.c \
			  dt_pcb.c \
			  dt_peb.c \
			  dt_pid.c \
			  dt_pragma.c \
			  dt_printf.c \
			  dt_probe.c \
			  dt_proc.c \
			  dt_program.c \
			  dt_prov_cpc.c \
			  dt_prov_dtrace.c \
			  dt_prov_fbt.c \
			  dt_prov_io.c \
			  dt_prov_ip.c \
			  dt_prov_lockstat.c \
			  dt_prov_proc.c \
			  dt_prov_profile.c \
			  dt_prov_rawtp.c \
			  dt_prov_sched.c \
			  dt_prov_sdt.c \
			  dt_prov_syscall.c \
			  dt_prov_uprobe.c \
			  dt_provider.c \
			  dt_provider_sdt.c \
			  dt_provider_tp.c \
			  dt_regset.c \
			  dt_rodata.c \
			  dt_string.c \
			  dt_strtab.c \
			  dt_subr.c \
			  dt_symtab.c \
			  dt_work.c \
			  dt_xlator.c

libdtrace-build_SRCDEPS := dt_grammar.h $(objdir)/dt_git_version.h

SHLIBS += libdtrace

libdtrace_DIR := $(current-dir)
libdtrace_TARGET = libdtrace
ifdef HAVE_LIBCTF
libdtrace_LIBS := -lctf
else
libdtrace_LIBS := -ldtrace-ctf
endif
libdtrace_LIBS += -lelf -lz -lrt -lpcap -lpthread -ldl -lm -lpfm
libdtrace_VERSION := 2.0.0
libdtrace_SONAME := libdtrace.so.2
libdtrace_VERSCRIPT := libdtrace.ver
libdtrace_LIBSOURCES := libdtrace-build libproc libport libcommon
libdtrace_SECONDARY := libproc libport

# Required for dt_pid.c for varying instruction lengths on x86
ifeq ($(shell uname -m), x86_64)
libdtrace_LIBS += -lopcodes
endif

# Disable certain warnings for these files
dt_bpf.c_CFLAGS := -Wno-pedantic
dt_btf.c_CFLAGS := -Wno-pedantic
dt_consume.c_CFLAGS := -Wno-pedantic
dt_debug.c_CFLAGS := -Wno-prio-ctor-dtor
dt_cg.c_CFLAGS := -Wno-pedantic
dt_dis.c_CFLAGS := -Wno-pedantic
dt_pid.c_CFLAGS := -Wno-pedantic
dt_proc.c_CFLAGS := -Wno-pedantic
dt_prov_cpc.c_CFLAGS := -Wno-pedantic
dt_prov_dtrace.c_CFLAGS := -Wno-pedantic
dt_prov_fbt.c_CFLAGS := -Wno-pedantic
dt_prov_io.c_CFLAGS := -Wno-pedantic
dt_prov_ip.c_CFLAGS := -Wno-pedantic
dt_prov_lockstat.c_CFLAGS := -Wno-pedantic
dt_prov_proc.c_CFLAGS := -Wno-pedantic
dt_prov_profile.c_CFLAGS := -Wno-pedantic
dt_prov_rawfbt.c_CFLAGS := -Wno-pedantic
dt_prov_rawtp.c_CFLAGS := -Wno-pedantic
dt_prov_sched.c_CFLAGS := -Wno-pedantic
dt_prov_sdt.c_CFLAGS := -Wno-pedantic
dt_prov_syscall.c_CFLAGS := -Wno-pedantic
dt_prov_uprobe.c_CFLAGS := -Wno-pedantic
dt_debug.c_CFLAGS := -Wno-prio-ctor-dtor

SHORTKERNELS := $(foreach kernel,$(KERNELS),$(shell printf %s $(kernel) | sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/'))

-include libdtrace/$(ARCHINC)/Build

$(libdtrace-build_DIR)dt_errtags.c: $(libdtrace-build_DIR)dt_errtags.h $(libdtrace-build_DIR)/mkerrtags.sh
	sh $(libdtrace-build_DIR)mkerrtags.sh < $(libdtrace-build_DIR)dt_errtags.h | sed -e 's/\\n/\n/g' > $@

$(libdtrace-build_DIR)%.h $(libdtrace-build_DIR)%.c: $(libdtrace-build_DIR)%.y
	$(call describe-target,YACC,$(libdtrace-build_DIR)$*.c)
	bison -o $(libdtrace-build_DIR)$*.c -d $(libdtrace-build_DIR)$*.y

$(libdtrace-build_DIR)dt_lex.c: $(libdtrace-build_DIR)dt_grammar.h $(libdtrace-build_DIR)dt_lex.l
	$(call describe-target,LEX,$(libdtrace-build_DIR)dt_lex.c)
	flex -o$(libdtrace-build_DIR)dt_lex.c $(libdtrace-build_DIR)dt_lex.l

M4_DLIBS += \
	procfs.d \
	io.d \
	sysevent.d

BUILD_DLIBS += \
	$(M4_DLIBS) \
	errno.d \
	regs.d \
	signal.d

WORKING_DLIBS = errno.d \
                io.d \
                ip.d \
                lockstat.d \
                net.d \
                pcap.d \
                procfs.d \
                regs.d \
                sched.d \
                signal.d \
                tcp.d \
                udp.d \
                unistd.d

# M4-driven substitutions.

override dir-dlib-targets = $(foreach kernel,$(SHORTKERNELS), \
	$(objdir)/dlibs/$(kernel)/.dir.stamp)
override m4-dlib-targets = $(foreach kernel,$(SHORTKERNELS), \
	$(addprefix $(objdir)/dlibs/$(kernel)/, \
	$(filter $(WORKING_DLIBS),$(M4_DLIBS))))
override other-dlib-targets = $(foreach kernel,$(SHORTKERNELS), \
	$(addprefix $(objdir)/dlibs/$(kernel)/, \
	$(filter-out $(M4_DLIBS),$(WORKING_DLIBS))))

$(objdir)/dlibs/.dir.stamp:
	mkdir -p $(objdir)/dlibs $(objdir)/dlibs/drti
	@touch $(objdir)/dlibs/.dir.stamp
	ln -srf $(libdtrace-build_DIR)/drti-vers $(objdir)/dlibs/drti
	$(call describe-target,CP,dlibs)
	cp -rp dlibs/$(ARCH)/* $(objdir)/dlibs

$(foreach kernel,$(SHORTKERNELS),$(objdir)/dlibs/$(kernel)/.dir.stamp):
	mkdir -p $(dir $@)
	@touch $@

define dlib-kernel-ver-template
$(objdir)/dlibs/$(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/')/%.d: override SHORTKERNELVER := $(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/' | awk -F. '{ print $$1 * 1000 * 1000 + $$2 * 1000 + $$3 }')
$(objdir)/dlibs/$(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/')/%.d: override KERNELVER := $(1)
$(objdir)/dlibs/$(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/')/%.d: override KERNELSRCDIR ?= $(KERNELMODDIR)/$(1)/$(KERNELSRCNAME)
$(objdir)/dlibs/$(shell printf %s $(1) | sed -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$$/\1.\2.\3/')/%.d: override KERNELOBJDIR ?= $(KERNELMODDIR)/$(1)/$(KERNELBLDNAME)
endef

$(foreach kernel,$(KERNELS),$(eval $(call dlib-kernel-ver-template,$(kernel))))

# The include order here is derived from the LINUXINCLUDE definition in
# the top-level kernel Makefile (which incorporates the USERINCLUDE
# definition in turn.)
$(m4-dlib-targets): $(objdir)/dlibs/%.d: $$(foreach name,$$(notdir %.d.in), \
			$$(call src-name,libdtrace,$$(name))) \
			$(dir-dlib-targets)
	$(call describe-target,M4,$<)
	$(PREPROCESS) -P -x c -Ilibdtrace/$(ARCHINC) \
		      -I$(KERNELSRCDIR)/arch/$(KERNELARCH)/include \
		      -I$(KERNELOBJDIR)/arch/$(KERNELARCH)/include/generated/uapi \
		      -I$(KERNELOBJDIR)/arch/$(KERNELARCH)/include/generated \
		      -I$(KERNELOBJDIR)/include \
		      -I$(KERNELSRCDIR)/include \
		      -I$(KERNELSRCDIR)/arch/$(KERNELARCH)/include/uapi \
		      -I$(KERNELOBJDIR)/include/generated/uapi \
		      -I$(KERNELSRCDIR)/include/uapi \
		      -D_KERNEL -D__KERNEL__ $(basename $(basename $<)).m4 2>$@.h.err | grep -v '^# [0-9]' | tee $@.h | \
	m4 --prefix-builtins -DSUBST_KERNEL=$(SHORTKERNELVER) -DSUBST_ARCH=$(KERNELARCH) $(libdtrace-build_DIR)def-start.m4 \
		$(libdtrace-build_DIR)def-replace.m4 - $(libdtrace-build_DIR)/d-subst.m4 \
                $(libdtrace-build_DIR)m4-utils.m4 $(libdtrace-build_DIR)/d-kern.m4 \
		$(libdtrace-build_DIR)def-end.m4 $< > $@; \
        if [[ $$? -ne 0 ]]; then \
		cat $@.h.err >&2; \
		echo "Error: Not all tokens in $< defined in headers." >&2; \
		rm -f $@.h $@.h.err; \
		exit 1; \
	fi
	if ! grep -q __def_replace $@.h; then \
		cat @$.h 2>/dev/null; \
                cat $@.h.err >&2; \
		echo "Error: Preprocessing of header included in $< failed." >&2; \
		rm -f $@.h $@.h.err; \
		exit 1; \
	fi
	rm -f $@.h $@.h.err;

$(other-dlib-targets): $(objdir)/dlibs/%.d: $$(foreach name,$$(notdir %.d), \
			$$(call src-name,libdtrace,$$(name))) \
			$(dir-dlib-targets)
	$(call describe-target,CP,$<)
	cp -f $< $@

PHONIES += dlibs
dlibs: $(dir-dlib-targets) $(m4-dlib-targets) $(other-dlib-targets)

PHONIES += objs
TARGETS += objs
BUILD_DRTI_OBJ = $(objdir)/drti.o
DRTI_OBJ = $(objdir)/dlibs/drti/drti.o
BUILD_DRTI32_OBJ = $(objdir)/drti32.o
DRTI32_OBJ = $(if $(NATIVE_BITNESS_ONLY),,$(objdir)/dlibs/drti/drti32.o)

objs: $(DRTI_OBJ) $(DRTI32_OBJ)
$(BUILD_DRTI_OBJ): $(libdtrace-build_DIR)drti.c
	$(call describe-target,CC,$<)
	$(CC) $(filter-out --coverage,$(CFLAGS)) -fPIC $(CPPFLAGS) $(libdtrace-build_CPPFLAGS) -MP -MMD -Wno-prio-ctor-dtor -fno-lto -c -o $@ $<
$(DRTI_OBJ): $(BUILD_DRTI_OBJ) $(objdir)/dlibs/.dir.stamp
	ln -sf $(BUILD_DRTI_OBJ) $(DRTI_OBJ)
$(BUILD_DRTI32_OBJ): $(libdtrace-build_DIR)drti.c
	$(call describe-target,CC-32,$<)
	$(CC) $(filter-out --coverage,$(CFLAGS)) -m32 -fPIC $(CPPFLAGS) $(libdtrace-build_CPPFLAGS) -MP -MMD -Wno-prio-ctor-dtor -fno-lto -c -o $@ $<
$(DRTI32_OBJ): $(BUILD_DRTI32_OBJ) $(objdir)/dlibs/.dir.stamp
	ln -sf $(BUILD_DRTI32_OBJ) $(DRTI32_OBJ)

# Custom substitutions.

# Though we use errno.h, the sensitive dependency is linux/errno.h,
# which is deeper in the include chain and supplied by a different package.
$(libdtrace-build_DIR)errno.d: /usr/include/linux/errno.h $(libdtrace-build_DIR)mkerrno.sh
	$(call describe-target,AWK,$(libdtrace-build_DIR)errno.d)
	echo '#include <errno.h>' | $(CC) -x c -E -dD - \
	| grep '^#define E' | $(libdtrace-build_DIR)mkerrno.sh > $@

$(libdtrace-build_DIR)signal.d: /usr/include/signal.h $(libdtrace-build_DIR)mksignal.sh
	$(call describe-target,AWK,$(libdtrace-build_DIR)signal.d)
	echo '#include <signal.h>' | $(CC) -x c -E -dD - \
	| grep '^#define SIG' | $(libdtrace-build_DIR)mksignal.sh > $@

$(libdtrace-build_DIR)regs.d: $(libdtrace-build_DIR)$(ARCHINC)/regs.d
	cp $< $@

clean::
	$(call describe-target,CLEAN,libdtrace)
	rm -f $(libdtrace-build_DIR)dt_errtags.c
	rm -f $(libdtrace-build_DIR)dt_grammar.h $(libdtrace-build_DIR)dt_grammar.c
	rm -f $(libdtrace-build_DIR)dt_lex.c
	rm -f $(addprefix $(libdtrace-build_DIR),$(BUILD_DLIBS))

install::
	mkdir -p $(INSTLIBDIR)/dtrace $(INSTLIBDIR)/dtrace/drti $(INSTINCLUDEDIR)
	$(call describe-install-target,$(INSTINCLUDEDIR),dtrace.h)
	install -m 644 $(libdtrace-build_DIR)dtrace.h $(INSTINCLUDEDIR)
	$(call describe-install-target,$(INSTLIBDIR),$(libdtrace_TARGET).so.$(libdtrace_VERSION))
	install -m 755 $(objdir)/$(libdtrace_TARGET).so.$(libdtrace_VERSION) $(INSTLIBDIR)
	$(call describe-install-target,$(INSTLIBDIR),$(libdtrace_SONAME))
	ln -sf libdtrace.so.$(libdtrace_VERSION) $(INSTLIBDIR)/$(libdtrace_SONAME)
	$(call describe-install-target,$(INSTLIBDIR),$(libdtrace_TARGET).so)
	ln -sf libdtrace.so.$(libdtrace_VERSION) $(INSTLIBDIR)/$(libdtrace_TARGET).so
	$(call describe-install-target,$(INSTLIBDIR)/dtrace/drti,$(DRTI_OBJ))
	install -m 644 $(DRTI_OBJ) $(INSTLIBDIR)/dtrace/drti
	$(call describe-install-target,$(INSTLIBDIR)/dtrace/drti,$(DRTI32_OBJ))
	$(if $(NATIVE_BITNESS_ONLY),,install -m 644 $(DRTI32_OBJ) $(INSTLIBDIR)/dtrace/drti)
	$(call describe-install-target,$(INSTLIBDIR)/dtrace/drti,drti-vers)
	install -m 644 $(objdir)/dlibs/drti/drti-vers $(INSTLIBDIR)/dtrace/drti
	for kernel in $$(cd $(objdir)/dlibs; echo [0-9]*); do \
		$(call describe-expanded-install-target,$(INSTLIBDIR)/dtrace/$$kernel,$(WORKING_DLIBS)) \
		mkdir -p $(INSTLIBDIR)/dtrace/$$kernel && \
		cd $(objdir)/dlibs/$$kernel && install -m 644 $(WORKING_DLIBS) $(INSTLIBDIR)/dtrace/$$kernel; \
	done
