Date: Tue, 11 Jul 2006 16:06:19 GMT From: Howard Su <howardsu@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 101278 for review Message-ID: <200607111606.k6BG6JMb056966@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=101278 Change 101278 by howardsu@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@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607111606.k6BG6JMb056966>