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