PERFORCE change 101278 for review

Howard Su howardsu at FreeBSD.org
Tue Jul 11 16:06:29 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=101278

Change 101278 by howardsu at su_laptop on 2006/07/11 16:05:38

	Reimplment SDT as Solaris way (invop).
	Remarks:
	1. this implementation only support SDT probe in kernel module now.
	   It doesn't support the ones in KERNEL image.
	2. Disabled "nested extern declaration warning" for kernel build
	3. Introduce a new MD api call in Link_elf to patch CALL to NOP.
	   I only implement the one in i386. Other platform's build may
	   break.
	4. The old implementation is removed.

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/dev/prototype.c#4 edit
.. //depot/projects/dtrace/src/sys/cddl/dev/sdt/sdt_subr.c#1 add
.. //depot/projects/dtrace/src/sys/conf/files#21 edit
.. //depot/projects/dtrace/src/sys/conf/kern.mk#5 edit
.. //depot/projects/dtrace/src/sys/contrib/opensolaris/uts/common/sys/sdt_impl.h#1 add
.. //depot/projects/dtrace/src/sys/i386/i386/elf_machdep.c#3 edit
.. //depot/projects/dtrace/src/sys/kern/kern_linker.c#15 edit
.. //depot/projects/dtrace/src/sys/kern/kern_sdt.c#4 delete
.. //depot/projects/dtrace/src/sys/kern/link_elf.c#5 edit
.. //depot/projects/dtrace/src/sys/modules/dtrace/sdt/Makefile#2 edit
.. //depot/projects/dtrace/src/sys/sys/linker.h#10 edit
.. //depot/projects/dtrace/src/sys/sys/sdt.h#4 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/dev/prototype.c#4 (text+ko) ====

@@ -49,6 +49,7 @@
 #include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
+#include <sys/sdt.h>
 #include <sys/selinfo.h>
 #include <sys/smp.h>
 #include <sys/syscall.h>
@@ -103,10 +104,8 @@
 static void
 prototype_provide(void *arg, dtrace_probedesc_t *desc)
 {
-	SDT_PROBE(prototype, provide, entry, arg, desc, 0, 0, 0);
-
-
-	SDT_PROBE(prototype, provide, return, arg, desc, 0, 0, 0);
+	DTRACE_PROBE(entry);
+	DTRACE_PROBE(ret);
 }
 
 /* ARGSUSED */

==== //depot/projects/dtrace/src/sys/conf/files#21 (text+ko) ====

@@ -1318,7 +1318,6 @@
 kern/kern_prot.c		standard
 kern/kern_resource.c		standard
 kern/kern_rwlock.c		standard
-kern/kern_sdt.c			standard
 kern/kern_sema.c		standard
 kern/kern_shutdown.c		standard
 kern/kern_sig.c			standard

==== //depot/projects/dtrace/src/sys/conf/kern.mk#5 (text+ko) ====

@@ -10,7 +10,7 @@
 #CWARNFLAGS=	-w2	# use this if you are terribly bored
 CWARNFLAGS=
 .else
-CWARNFLAGS?=	-Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes \
+CWARNFLAGS?=	-Wall -Wredundant-decls -Wstrict-prototypes \
 		-Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual \
 		${_wundef} -fformat-extensions
 .if !defined(NO_UNDEF)

==== //depot/projects/dtrace/src/sys/i386/i386/elf_machdep.c#3 (text+ko) ====

@@ -232,3 +232,19 @@
 
 	return (0);
 }
+
+#define SDT_NOP 0x90
+#define SDT_NOPS 5
+
+int
+sdt_reloc_resolve(uint8_t *instr, sdt_probedesc_t *sdp)
+{
+  int i;
+  sdp->sdpd_offset = (uintptr_t)instr;
+ 
+  for(i = 0; i < SDT_NOPS; i++) {
+	instr[i - 1] = SDT_NOP;
+  }
+
+  return (1);
+}

==== //depot/projects/dtrace/src/sys/kern/kern_linker.c#15 (text+ko) ====

@@ -95,6 +95,12 @@
 
 static struct sx kld_sx;	/* kernel linker lock */
 
+/*
+ * Load counter used by clients to determine if a linker file has been
+ * re-loaded. This counter is incremented for each file load.
+ */
+static int loadcnt;
+
 static linker_class_list_t classes;
 static linker_file_list_t linker_files;
 static int next_file_id = 1;
@@ -542,6 +548,9 @@
 	LINKER_GET_NEXT_FILE_ID(lf->id);
 	lf->ndeps = 0;
 	lf->deps = NULL;
+	lf->loadcnt = ++loadcnt;
+	lf->sdt_probes = NULL;
+	lf->sdt_nprobes = 0;
 	STAILQ_INIT(&lf->common);
 	TAILQ_INIT(&lf->modules);
 	TAILQ_INSERT_TAIL(&linker_files, lf, link);

==== //depot/projects/dtrace/src/sys/kern/link_elf.c#5 (text+ko) ====

@@ -153,6 +153,8 @@
 static int		relocate_file(elf_file_t ef);
 static int		link_elf_preload_parse_symbols(elf_file_t ef);
 
+const char *sdt_prefix = "__dtrace_probe_";
+
 #ifdef GDB
 static void		r_debug_state(struct r_debug *dummy_one,
 				      struct link_map *dummy_two);
@@ -929,6 +931,29 @@
 }
 
 static int
+sdt_reloc_check(linker_file_t lf, const char *symname, uint8_t * instr)
+{
+    sdt_probedesc_t *sdp;
+    if (strncmp(symname, sdt_prefix, strlen(sdt_prefix)) != 0)
+        return (0);
+
+    symname += strlen(sdt_prefix);
+    sdp = malloc(sizeof(sdt_probedesc_t), M_LINKER, M_WAITOK);
+    sdp->sdpd_name = malloc(strlen(symname) + 1, M_LINKER, M_WAITOK);
+    strcpy(sdp->sdpd_name, symname);
+
+    if (sdt_reloc_resolve(instr, sdp)) {
+        sdp->sdpd_next = lf->sdt_probes;
+        lf->sdt_probes = sdp;
+        return (1);
+    } else {
+        free(sdp->sdpd_name, M_LINKER);
+        free(sdp, M_LINKER);
+        return (0);
+    }
+}
+
+static int
 relocate_file(elf_file_t ef)
 {
     const Elf_Rel *rellim;
@@ -945,8 +970,11 @@
 	    if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
 			  elf_lookup)) {
 		symname = symbol_name(ef, rel->r_info);
-		printf("link_elf: symbol %s undefined\n", symname);
-		return ENOENT;
+		if (!sdt_reloc_check(&ef->lf, symname,
+                  (uint8_t *) (ef->address + rel->r_offset))) {
+			printf("link_elf: symbol %s undefined\n", symname);
+			return ENOENT;
+		}
 	    }
 	    rel++;
 	}

==== //depot/projects/dtrace/src/sys/modules/dtrace/sdt/Makefile#2 (text+ko) ====

@@ -3,7 +3,7 @@
 .PATH: ${.CURDIR}/../../../cddl/dev/sdt
 
 KMOD=		sdt
-SRCS=		sdt.c
+SRCS=		sdt.c sdt_subr.c
 SRCS+=		bus_if.h device_if.h vnode_if.h
 
 CFLAGS+=	-I${.CURDIR}/../../../cddl/dev/sdt \

==== //depot/projects/dtrace/src/sys/sys/linker.h#10 (text+ko) ====

@@ -33,6 +33,7 @@
 
 #include <machine/elf.h>
 #include <sys/kobj.h>
+#include <sys/sdt.h>
 
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_LINKER);
@@ -92,6 +93,10 @@
      */
     int			nenabled;	/* number of enabled probes. */
     int			fbt_nentries;	/* number of fbt entries created. */
+  	sdt_probedesc_t *sdt_probes;
+  	int			sdt_nentries;
+  	size_t		sdt_nprobes;
+  	size_t		sdt_size;
 };
 
 /*
@@ -259,6 +264,7 @@
 int	elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
 const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx);
 const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx);
+int sdt_reloc_resolve(uint8_t *, sdt_probedesc_t *);
 
 int elf_cpu_load_file(linker_file_t);
 int elf_cpu_unload_file(linker_file_t);

==== //depot/projects/dtrace/src/sys/sys/sdt.h#4 (text+ko) ====

@@ -1,106 +1,119 @@
-/*-
- * Copyright 2006 John Birrell <jb at FreeBSD.org>
+/*
+ * CDDL HEADER START
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
  *
- * $FreeBSD$
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
  *
- * Statically Defined Tracing (SDT) definitions.
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
  *
+ * CDDL HEADER END
  */
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
 
 #ifndef _SYS_SDT_H
 #define	_SYS_SDT_H
 
 #ifndef _KERNEL
-#error "no user-servicable parts inside"
-#endif
+
+#define	DTRACE_PROBE(provider, name) {					\
+	extern void __dtrace_##provider##___##name(void);		\
+	__dtrace_##provider##___##name();				\
+}
+
+#define	DTRACE_PROBE1(provider, name, arg1) {				\
+	extern void __dtrace_##provider##___##name(unsigned long);	\
+	__dtrace_##provider##___##name((unsigned long)arg1);		\
+}
+
+#define	DTRACE_PROBE2(provider, name, arg1, arg2) {			\
+	extern void __dtrace_##provider##___##name(unsigned long,	\
+	    unsigned long);						\
+	__dtrace_##provider##___##name((unsigned long)arg1,		\
+	    (unsigned long)arg2);					\
+}
+
+#define	DTRACE_PROBE3(provider, name, arg1, arg2, arg3) {		\
+	extern void __dtrace_##provider##___##name(unsigned long,	\
+	    unsigned long, unsigned long);				\
+	__dtrace_##provider##___##name((unsigned long)arg1,		\
+	    (unsigned long)arg2, (unsigned long)arg3);			\
+}
+
+#define	DTRACE_PROBE4(provider, name, arg1, arg2, arg3, arg4) {		\
+	extern void __dtrace_##provider##___##name(unsigned long,	\
+	    unsigned long, unsigned long, unsigned long);		\
+	__dtrace_##provider##___##name((unsigned long)arg1,		\
+	    (unsigned long)arg2, (unsigned long)arg3,			\
+	    (unsigned long)arg4);					\
+}
+
+#define	DTRACE_PROBE5(provider, name, arg1, arg2, arg3, arg4, arg5) {	\
+	extern void __dtrace_##provider##___##name(unsigned long,	\
+	    unsigned long, unsigned long, unsigned long, unsigned long);\
+	__dtrace_##provider##___##name((unsigned long)arg1,		\
+	    (unsigned long)arg2, (unsigned long)arg3,			\
+	    (unsigned long)arg4, (unsigned long)arg5);			\
+}
+
+#else /* _KERNEL */
+
+#define	DTRACE_PROBE(name)	{					\
+	extern void __dtrace_probe_##name(void);			\
+	__dtrace_probe_##name();					\
+}
+
+#define	DTRACE_PROBE1(name, type1, arg1) {				\
+	extern void __dtrace_probe_##name(uintptr_t);			\
+	__dtrace_probe_##name((uintptr_t)(arg1));			\
+}
 
-#include <sys/kernel.h>
+#define	DTRACE_PROBE2(name, type1, arg1, type2, arg2) {			\
+	extern void __dtrace_probe_##name(uintptr_t, uintptr_t);	\
+	__dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2));	\
+}
 
-/*
- * This type definition must match that of dtrace_probe. It is defined this
- * way to avoid having to rely on CDDL code.
- */
-typedef	void (*sdt_probe_func_t)(u_int32_t, uintptr_t arg0, uintptr_t arg1,
-    uintptr_t arg2, uintptr_t arg3, uintptr_t arg4);
+#define	DTRACE_PROBE3(name, type1, arg1, type2, arg2, type3, arg3) {	\
+	extern void __dtrace_probe_##name(uintptr_t, uintptr_t, uintptr_t); \
+	__dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2),	\
+	    (uintptr_t)(arg3));						\
+}
 
-/*
- * The hook for the probe function. See kern_sdt.c which defaults this to
- * it's own stub. The 'sdt' provider will set it to dtrace_probe when it
- * loads.
- */
-extern sdt_probe_func_t	sdt_probe_func;
+#define	DTRACE_PROBE4(name, type1, arg1, type2, arg2, 			\
+    type3, arg3, type4, arg4) {						\
+	extern void __dtrace_probe_##name(uintptr_t, uintptr_t,		\
+	    uintptr_t, uintptr_t);					\
+	__dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2),	\
+	    (uintptr_t)(arg3), (uintptr_t)(arg4));			\
+}
 
-typedef enum {
-	SDT_UNINIT = 1,
-	SDT_INIT,
-	SDT_OFFSET_TOO_BIG,
-	SDT_UNEXPECTED_INSTR
-} sdt_state_t;
+#endif /* _KERNEL */
 
-struct sdt_ref {
-	int		version;	/* Set to sizeof(struct sdt_ref). */
-	sdt_state_t	state;		/* Initialisation state. */
-	TAILQ_ENTRY(sdt_ref)
-			list_entry;	/* SDT reference list entry. */
-	char		*mod;
-	char		*func;
-	char		*name;
-	id_t		id;		/* DTrace probe ID. */
-	caddr_t		probe_start;	/* Start probe address. */
-	caddr_t		probe_end;	/* End probe address. */
-#if defined(__i386__)
-	u_int8_t	probe_enable;	/* Instruction to enable the probe. */
-	u_int8_t	probe_disable;	/* Instruction to disable the probe. */
-#endif
-};
+extern const char *sdt_prefix;
 
-#define SDT_LABEL(lbl)			\
-	__asm__(".globl " #lbl);	\
-	__asm__(#lbl ":")
+typedef struct sdt_probedesc {
+	char			*sdpd_name;	/* name of this probe */
+	unsigned long		sdpd_offset;	/* offset of call in text */
+	struct sdt_probedesc	*sdpd_next;	/* next static probe */
+} sdt_probedesc_t;
 
-#define	_SDT_PROBE(ref, arg0, arg1, arg2, arg3 , arg4)					\
-	SYSINIT(ref##_sdt_init, SI_SUB_KDTRACE, SI_ORDER_SECOND,			\
-	    sdt_register, &ref##_sdt_ref);						\
-	SYSUNINIT(ref##_sdt_uninit, SI_SUB_KDTRACE, SI_ORDER_ANY,			\
-	    sdt_deregister, &ref##_sdt_ref);						\
-	SDT_LABEL(__##ref##_sdt_probe_start);						\
-	__asm__("jmp 0f; 0:");								\
-	if (ref##_sdt_ref.id != 0)							\
-		(*sdt_probe_func)(ref##_sdt_ref.id, (uintptr_t) arg0, (uintptr_t) arg1,	\
-		    (uintptr_t) arg2, (uintptr_t) arg3 , (uintptr_t) arg4);		\
-	SDT_LABEL(__##ref##_sdt_probe_end);
+#ifdef	__cplusplus
+}
+#endif
 
-#define	SDT_PROBE(mod, func, name, arg0, arg1, arg2, arg3 , arg4)			\
-	static struct sdt_ref mod##_##func##_##name##_sdt_ref = { 			\
-	    sizeof(struct sdt_ref), SDT_UNINIT, { NULL, NULL }, #mod, #func, #name,	\
-	    0, 0, 0, 0, 0 };								\
-	_SDT_PROBE(mod##_##func##_##name, arg0, arg1, arg2, arg3 , arg4)
+#endif	/* _SYS_SDT_H */
 
-void sdt_deregister(void *);
-void sdt_register(void *);
-void sdt_probe_stub(u_int32_t, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
-    uintptr_t arg3, uintptr_t arg4);
-int sdt_ref_listall(int (*)(struct sdt_ref *, void *), void *);
 
-#endif /* _SYS_SDT_H */


More information about the p4-projects mailing list