]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: implement SDT in kernel modules
authorKris Van Hees <kris.van.hees@oracle.com>
Tue, 17 Dec 2013 23:06:57 +0000 (18:06 -0500)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 21 Jul 2015 14:29:25 +0000 (15:29 +0100)
Full implementation of SDT probes in kernel modules.

The dtrace_sdt.sh script has been modified to handle both the creation
of the SDT stubs and the SDT info.  It's syntax has therefore changed:

  dtrace_sdt.sh sdtstub <stubfile> <object-file> <object-file>*
or
  dtrace_sdt.sh sdtinfo <infofile> vmlinux.o
or
  dtrace_sdt.sh sdtinfo <infofile> vmlinux.o .tmp_vmlinux1
or
  dtrace_sdt.sh sdtinfo <infofile> <kmod>.o kmod

The first form generates a stub file in assembler to ensure that the
(fake) functions that are called from SDT probe points will not longer
be reported as undefined symbols, and to ensure that when SDT is not
enabled, the probes become calls to a function that simply returns.

The second form creates the initial (dummy) SDT info file for the kernel
linking process, mainly to ensure that its size is known.  The third
form then creates the true SDT info file for the kernel, based on the
kernel object file and the first stage linked kernel image.

The fourth and final form generates SDT info for a kernel module, based
on its initial linked object.

This commit also enables the test probes in the dt_test module.

Orabug: 17851716

Reviewed-by: Jamie Iles <jamie.iles@oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Conflicts:
Makefile
scripts/Makefile.build

Makefile
include/linux/sdt.h
kernel/dtrace/dtrace_os.c
kernel/dtrace/dtrace_sdt.c
scripts/Makefile.build
scripts/Makefile.modpost
scripts/dtrace_sdt.sh
scripts/link-vmlinux.sh
scripts/mod/modpost.c

index 468d99cca309113291b7ab33263dfde0574f3036..44b7642082352791d664fbcab6ca12c7e54c570a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1452,8 +1452,8 @@ clean: $(clean-dirs)
        $(call cmd,rmfiles)
        @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-               -o -name '*.ko.*' \
-               -o -name '*.dwo'  \
+               -o -name '*.ko.*' -o -name '*.dwo' \
+               -o -name '*.sdtinfo.c' -o -name '*.sdtstub.S' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.symtypes' -o -name 'modules.order' \
                -o -name 'modules.builtin' -o -name 'objects.builtin' \
index affca435065b3de7de86ae433fc039ef2fa8b24a..57dcb93c4652dc694bd5a867a6ca4d248ddec7e7 100644 (file)
@@ -134,7 +134,9 @@ typedef struct dtrace_sdt_probeinfo {
        char name[0];
 } __aligned(sizeof(unsigned long)) dtrace_sdt_probeinfo_t;
 
+void dtrace_sdt_init(void);
 void dtrace_sdt_register(struct module *);
+void dtrace_sdt_exit(void);
 
 #endif /* __KERNEL__ */
 
@@ -434,7 +436,7 @@ typedef struct sdt_probedesc {
        struct sdt_probedesc    *sdpd_next;     /* next static probe */
 } sdt_probedesc_t;
 
-extern void dtrace_register_builtins(void);
+/* extern void dtrace_register_builtins(void); */
 
 #ifdef __cplusplus
 }
index 8f46d96174495cbd50a33f713d4581576348680e..4a371c867302886b1409aa0c121ff8455b399184 100644 (file)
@@ -58,6 +58,7 @@ void dtrace_os_init(void)
                                SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK,
                                NULL);
 
+       dtrace_sdt_init();
        dtrace_sdt_register(dtrace_kmod);
 }
 EXPORT_SYMBOL(dtrace_os_init);
index 0844941de070bef82ceafe4e0e7961d4966857a8..3b6d2b6f5636b3e9ccc71856a39e2d30f93c93d3 100644 (file)
@@ -19,6 +19,7 @@
 #define        SDT_NOP_SIZE    5
 
 const char             *sdt_prefix = "__dtrace_probe_";
+uint8_t                        nops[SDT_NOP_SIZE];
 
 /* This code is based on apply_alternatives and text_poke_early.  It needs to
  * run before SMP is initialized in order to avoid SMP problems with patching
@@ -44,15 +45,10 @@ static void __init_or_module text_poke_batch(struct text_poke_param *reqs,
        restart_nmi();
 }
 
-static int sdt_probe_add(struct module *mp, char *name, char *func,
-                        uintptr_t addr, struct text_poke_param *tpp,
-                        void *nops)
+static int sdt_probe_set(sdt_probedesc_t *sdp, char *name, char *func,
+                        uintptr_t addr, struct text_poke_param *tpp)
 {
-       sdt_probedesc_t *sdp;
-       uint8_t *instr;
-
-       if ((sdp = kmalloc(sizeof(sdt_probedesc_t), GFP_KERNEL)) == NULL)
-               return 1;
+       uint8_t         *instr;
 
        if ((sdp->sdpd_name = kstrdup(name, GFP_KERNEL)) == NULL) {
                kfree(sdp);
@@ -68,10 +64,7 @@ static int sdt_probe_add(struct module *mp, char *name, char *func,
        /* adjust relocation address to beginning of call instruction */
        instr = (uint8_t *)(addr - 1);
 
-       /* TBD: use a kernel list? */
        sdp->sdpd_offset = (uintptr_t)instr;
-       sdp->sdpd_next = mp->sdt_probes;
-       mp->sdt_probes = sdp;
 
        tpp->addr = instr;
        tpp->opcode = nops;
@@ -80,13 +73,17 @@ static int sdt_probe_add(struct module *mp, char *name, char *func,
        return 0;
 }
 
+/*
+ * Register the SDT probes for the core kernel, i.e. SDT probes that reside in
+ * vmlinux.  For SDT probes in kernel modules, we use dtrace_mod_notifier().
+ */
 void dtrace_sdt_register(struct module *mod)
 {
        int                     i, cnt;
        dtrace_sdt_probeinfo_t  *pi =
                                (dtrace_sdt_probeinfo_t *)&dtrace_sdt_probes;
        void                    *nextpi;
-       uint8_t                 nops[SDT_NOP_SIZE];
+       sdt_probedesc_t         *sdps;
        struct text_poke_param  *reqs;
 
        if (mod == NULL) {
@@ -95,19 +92,25 @@ void dtrace_sdt_register(struct module *mod)
                return;
        }
 
+       /*
+        * Just in case we run into failures further on...
+        */
+       mod->sdt_probes = NULL;
+       mod->num_dtrace_probes = 0;
+
        if (dtrace_sdt_nprobes == 0)
                return;
 
        /*
-        * A little unusual, but potentially necessary.  While we could use a
-        * single NOP sequence of length SDT_NOP_SIZE, we need to consider the
-        * fact that when a SDT probe point is enabled, a single invalid opcode
-        * is written on the first byte of this NOP sequence.  By using a
-        * sequence of a 1-byte NOP, followed by a (SDT_NOP_SIZE - 1) byte NOP
-        * sequence, we play it pretty safe.
+        * Allocate the array of SDT probe descriptions to be registered in the
+        * vmlinux pseudo-module.
         */
-       add_nops(nops, 1);
-       add_nops(nops + 1, SDT_NOP_SIZE - 1);
+       sdps = (sdt_probedesc_t *)vmalloc(dtrace_sdt_nprobes *
+                                         sizeof(sdt_probedesc_t));
+       if (sdps == NULL) {
+               pr_warning("%s: cannot allocate SDT probe array\n", __func__);
+               return;
+       }
 
        /*
         * Set up a batch of text_poke requests that will handle replacing all
@@ -118,16 +121,17 @@ void dtrace_sdt_register(struct module *mod)
                        vmalloc(dtrace_sdt_nprobes *
                                sizeof(struct text_poke_param));
        if (reqs == NULL) {
-               pr_warning("%s: failed to allocate text_poke_param array\n",
+               pr_warning("%s: cannot allocate text_poke_param array\n",
                           __func__);
+               vfree(sdps);
                return;
        }
 
        for (i = cnt = 0; cnt < dtrace_sdt_nprobes; i++) {
                char    *func = pi->name + pi->name_len + 1;
 
-               if (sdt_probe_add(dtrace_kmod, pi->name, func, pi->addr,
-                                 &reqs[cnt], nops))
+               if (sdt_probe_set(&sdps[cnt], pi->name, func, pi->addr,
+                                 &reqs[cnt]))
                        pr_warning("%s: failed to add SDT probe %s\n",
                                   __func__, pi->name);
                else
@@ -139,7 +143,12 @@ void dtrace_sdt_register(struct module *mod)
                pi = nextpi;
        }
 
+       mod->sdt_probes = sdps;
+       mod->num_dtrace_probes = cnt;
+
        text_poke_batch(reqs, cnt);
+
+       vfree(reqs);
 }
 
 static int __init nosdt(char *str)
@@ -151,6 +160,90 @@ static int __init nosdt(char *str)
 
 early_param("nosdt", nosdt);
 
+static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
+                              void *args)
+{
+       struct module           *mod = args;
+       struct text_poke_param  *reqs, *req;
+       int                     idx, cnt;
+       sdt_probedesc_t         *sdp;
+
+       /*
+        * We only need to capture modules in the COMING state, we need a valid
+        * module structure as argument, and the module needs to actually have
+        * SDT probes.  If not, ignore...
+        */
+       if (val != MODULE_STATE_COMING)
+               return NOTIFY_DONE;
+       if (!mod)
+               return NOTIFY_DONE;
+       if (mod->num_dtrace_probes == 0 || mod->sdt_probes == NULL)
+               return NOTIFY_DONE;
+
+       /*
+        * Set up a batch of text_poke requests that will handle replacing all
+        * calls at SDT probe locations with the NOP sequence.  Allocate the
+        * requests array, and then fill it in.
+        */
+       reqs = (struct text_poke_param *)
+                       vmalloc(dtrace_sdt_nprobes *
+                               sizeof(struct text_poke_param));
+       if (reqs == NULL) {
+               pr_warning("%s: cannot allocate text_poke_param array (%s)\n",
+                          __func__, mod->name);
+               return NOTIFY_DONE;
+       }
+
+       for (idx = cnt = 0, req = reqs, sdp = mod->sdt_probes;
+            idx < mod->num_dtrace_probes; idx++, sdp++) {
+               /*
+                * Fix-up the offset to reflect the relocated address of the
+                * probe.  We subtract 1 to put us at the beginning of the call
+                * instruction.  We verify that the offset won't put us beyond
+                * the module core, just to be safe.
+                */
+               sdp->sdpd_offset += (uintptr_t)mod->module_core - 1;
+               if (!within_module_core(sdp->sdpd_offset, mod)) {
+                       pr_warning("%s: SDT probe outside module core %s\n",
+                                  __func__, mod->name);
+                       continue;
+               }
+
+               req->addr = (uint8_t *)sdp->sdpd_offset;
+               req->opcode = nops;
+               req->len = SDT_NOP_SIZE;
+
+               cnt++;
+               req++;
+       }
+
+       text_poke_batch(reqs, cnt);
+
+       vfree(reqs);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block   dtrace_modfix = {
+       .notifier_call = dtrace_mod_notifier,
+};
+
+void dtrace_sdt_init(void)
+{
+       /*
+        * A little unusual, but potentially necessary.  While we could use a
+        * single NOP sequence of length SDT_NOP_SIZE, we need to consider the
+        * fact that when a SDT probe point is enabled, a single invalid opcode
+        * is written on the first byte of this NOP sequence.  By using a
+        * sequence of a 1-byte NOP, followed by a (SDT_NOP_SIZE - 1) byte NOP
+        * sequence, we play it pretty safe.
+        */
+       add_nops(nops, 1);
+       add_nops(nops + 1, SDT_NOP_SIZE - 1);
+
+       register_module_notifier(&dtrace_modfix);
+}
+
 #if defined(CONFIG_DT_DT_PERF) || defined(CONFIG_DT_DT_PERF_MODULE)
 void dtrace_sdt_perf(void)
 {
index 01df30af4d4a50f7ffec08993115b2e412128d1f..81ec4f729d5c284ffa355b875b91ab1a4332e375 100644 (file)
@@ -380,9 +380,38 @@ $($(subst $(obj)/,,$(@:.o=-y)))), $^)
 quiet_cmd_link_multi-y = LD      $@
 cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis)
 
+ifdef CONFIG_DTRACE
+
+# We need secondary expansion for the %.sdtstub.S creation rule
+.SECONDEXPANSION:
+
+sdtgen = scripts/dtrace_sdt.sh
+
+quiet_cmd_sdtstub = SDTSTB  $@
+      cmd_sdtstub = $(sdtgen) sdtstub $@ \
+                             $(filter $(addprefix $(obj)/, \
+                               $($(subst $(obj)/,,$(@:.sdtstub.S=-objs))) \
+                               $($(subst $(obj)/,,$(@:.sdtstub.S=-y)))), \
+                               $(multi-objs-m))
+
+$(multi-used-m:.o=.sdtstub.S) : %.sdtstub.S: $(multi-objs-m)
+       $(call if_changed,sdtstub)
+
+$(multi-used-m:.o=.sdtstub.o) : %.sdtstub.o: %.sdtstub.S
+       $(call if_changed,as_o_S)
+
+$(multi-used-m) : %.o: %.sdtstub.o
+
+quiet_cmd_link_multi-m = LD [M]  $@
+cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $*.sdtstub.o $(cmd_secanalysis)
+
+else
+
 quiet_cmd_link_multi-m = LD [M]  $@
 cmd_link_multi-m = $(cmd_link_multi-y)
 
+endif
+
 $(multi-used-y): FORCE
        $(call if_changed,link_multi-y)
 $(call multi_depend, $(multi-used-y), .o, -objs -y)
index ebeef7c8926901d78633c928edcdc9fc8ecbd34e..4cf971c3cc701660cc64c97e79056dba611da105 100644 (file)
@@ -105,18 +105,34 @@ vmlinux.o: FORCE
 $(symverfile):         __modpost ;
 $(modules:.ko=.mod.c): __modpost ;
 
-# Step 5), compile all *.mod.c files
+# Step 5), compile all *.mod.c files (includes the generation of SDT data)
 
 # modname is set to make c_flags define KBUILD_MODNAME
 modname = $(notdir $(@:.mod.o=))
 
 quiet_cmd_cc_o_c = CC      $@
       cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
-                  -c -o $@ $<
+                  -I$(dir $@) -c -o $@ $<
+
+ifdef CONFIG_DTRACE
+
+sdtgen = scripts/dtrace_sdt.sh
+
+quiet_cmd_sdtinfo = SDTINF  $@
+      cmd_sdtinfo = $(sdtgen) sdtinfo $@ $< kmod
+
+$(modules:.ko=.sdtinfo.c): %.sdtinfo.c: %.o
+       $(call cmd,sdtinfo)
+
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c %.sdtinfo.c FORCE
+       $(call if_changed_dep,cc_o_c)
+else
 
 $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
        $(call if_changed_dep,cc_o_c)
 
+endif
+
 targets += $(modules:.ko=.mod.o)
 
 # Step 6), generate CTF for the entire kernel, or for the module alone if this
index 73a0d11814f666a513135ce9821ec4b88195af8c..27979b8ed418042f108ca08d039a5501b7e3796e 100755 (executable)
@@ -2,12 +2,54 @@
 
 LANG=C
 
+opr="$1"
+shift
+if [ -z "$opr" ]; then
+    echo "ERROR: Missing operation" > /dev/stderr
+    exit 1
+fi
+
+tfn="$1"
+shift
+if [ -z "$tfn" ]; then
+    echo "ERROR: Missing target filename" > /dev/stderr
+    exit 1
+fi
+
 ofn="$1"
 lfn="$2"
 
+if [ -z "$ofn" ]; then
+    echo "ERROR: Missing object file argument" > /dev/stderr
+    exit 1
+fi
+
+if [ "$opr" = "sdtstub" ]; then
+    ${NM} -u $* | \
+       grep __dtrace_probe_ | sort | uniq | \
+       ${AWK} '{
+                   printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
+                          $2, $2, $2);
+                   count++;
+               }
+
+               END {
+                   if (count)
+                       print "\tret";
+                   else
+                       exit(1);
+               }' > $tfn
+    exit 0
+fi
+
+if [ "$opr" != "sdtinfo" ]; then
+    echo "ERROR: Invalid operation, should be sdtstub or sdtinfo" > /dev/stderr
+    exit 1
+fi
+
 (
     objdump -htr "$ofn" | \
-       awk -v lfn=${lfn} \
+       awk -v lfn="${lfn}" \
            '/^Sections:/ {
                 getline;
                 getline;
@@ -27,7 +69,7 @@ lfn="$2"
             $3 == "F" {
                 printf "%16s %s F %s\n", $4, $1, $6;
 
-                if (!lfn)
+                if (!lfn || lfn == "kmod")
                     printf "%s t %s\n", $1, $6;
 
                 next;
@@ -47,9 +89,10 @@ lfn="$2"
                 next;
             }' | \
        sort
-    [ "x${lfn}" != "x" ] && nm ${lfn}
+    [ "x${lfn}" != "x" -a "x${lfn}" != "xkmod" ] && nm ${lfn}
 ) | \
-    awk 'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
+    awk -v lfn="${lfn}" \
+       'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
             tmp = $0;
             if (length(v0) > 8) {
                 d = length(v0);
@@ -111,21 +154,27 @@ lfn="$2"
         }
 
         BEGIN {
-            print "#include <asm/types.h>";
-            print "#if BITS_PER_LONG == 64";
-            print "# define PTR .quad";
-            print "# define ALGN .align 8";
-            print "#else";
-            print "# define PTR .long";
-            print "# define ALGN .align 4";
-            print "#endif";
-
-            print "\t.section .rodata, \042a\042";
-            print "";
-
-            print ".globl dtrace_sdt_probes";
-            print "\tALGN";
-            print "dtrace_sdt_probes:";
+            if (lfn != "kmod") {
+                print "#include <asm/types.h>";
+                print "#if BITS_PER_LONG == 64";
+                print "# define PTR .quad";
+                print "# define ALGN .align 8";
+                print "#else";
+                print "# define PTR .long";
+                print "# define ALGN .align 4";
+                print "#endif";
+
+                print "\t.section .rodata, \042a\042";
+                print "";
+
+                print ".globl dtrace_sdt_probes";
+                print "\tALGN";
+                print "dtrace_sdt_probes:";
+            } else {
+                print "#include <linux/sdt.h>";
+            }
+
+            probec = 0;
         }
 
         $2 ~ /^[tT]$/ {
@@ -140,13 +189,21 @@ lfn="$2"
                 for (i = 1; i <= NF; i++) {
                     prb = $i;
                     pn = fun":"prb;
+                    ad = addl(baseaddr, poffst[pn]);
+
+                    if (lfn != "kmod") {
+                        print "\tPTR\t0x" ad;
+                        print "\tPTR\t" length(prb);
+                        print "\tPTR\t" length(fun);
+                        print "\t.asciz\t\042" prb "\042";
+                        print "\t.asciz\t\042" fun "\042";
+                        print "\tALGN";
+                    } else {
+                        if (probec == 0)
+                            print "static sdt_probedesc_t\t_sdt_probes[] = {";
 
-                    print "\tPTR\t0x" addl(baseaddr, poffst[pn]);
-                    print "\tPTR\t" length(prb);
-                    print "\tPTR\t" length(fun);
-                    print "\t.asciz\t\042" prb "\042";
-                    print "\t.asciz\t\042" fun "\042";
-                    print "\tALGN";
+                        print "  {\042" prb "\042, \042"fun"\042, 0x" ad " },";
+                    }
 
                     probec++;
                 }
@@ -175,14 +232,25 @@ lfn="$2"
         }
 
         END {
-            print "";
-            print ".globl dtrace_sdt_nprobes";
-            print "\tALGN";
-            print "dtrace_sdt_nprobes:";
-            print "\tPTR\t" probec;
+            if (lfn != "kmod") {
+                print "";
+                print ".globl dtrace_sdt_nprobes";
+                print "\tALGN";
+                print "dtrace_sdt_nprobes:";
+                print "\tPTR\t" probec;
+            } else {
+                if (probec > 0)
+                    print "};";
+                else
+                    print "#define _sdt_probes\tNULL";
+
+                print "#define _sdt_probec\t" probec;
+            }
 
             if (errc > 0) {
                 print errc " errors generating SDT probe data." > /dev/stderr;
                 exit 1;
             }
-        }'
+        }' > $tfn
+
+exit 0
index c61eca2494ae98b3949f742546470491c20ab14c..bd9e6c288bf67393ceac615b596dce36e6e5177a 100755 (executable)
@@ -39,30 +39,25 @@ info()
 
 # Generate the SDT probe point stubs object file
 # ${1} output file
-sdtstubs()
+sdtstub()
 {
-       info MKSTUBS ${1}
-       ${NM} -u ${KBUILD_VMLINUX_INIT} ${KBUILD_VMLINUX_MAIN} | \
-               grep __dtrace_probe_ | sort | uniq | \
-               ${AWK} '{
-                         printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
-                                $2, $2, $2);
-                       }' > .tmp_sdtstubs.S
-       echo "  ret" >> .tmp_sdtstubs.S
+       info SDTSTB ${1}
+       ${srctree}/scripts/dtrace_sdt.sh sdtstub .tmp_sdtstub.S \
+               ${KBUILD_VMLINUX_INIT} ${KBUILD_VMLINUX_MAIN}
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 
-       ${CC} ${aflags} -c -o ${1} .tmp_sdtstubs.S
+       ${CC} ${aflags} -c -o ${1} .tmp_sdtstub.S
 }
 
 # Generate the SDT probe info for object file ${1} and kernel image ${2}
 # ${3} output file
 sdtinfo()
 {
-       info DT-SDT ${3}
+       info SDTINF ${3}
 
-       ${srctree}/scripts/dtrace_sdt.sh ${1} ${2} > .tmp_sdtinfo.S
+       ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1} ${2}
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
@@ -150,7 +145,7 @@ cleanup()
        rm -f .old_version
        rm -f .tmp_System.map
        rm -f .tmp_kallsyms*
-       rm -f .tmp_sdtstubs.*
+       rm -f .tmp_sdtstub.*
        rm -f .tmp_sdtinfo.*
        rm -f .tmp_version
        rm -f .tmp_vmlinux*
@@ -183,12 +178,12 @@ case "${KCONFIG_CONFIG}" in
        . "./${KCONFIG_CONFIG}"
 esac
 
-sdtstubso=""
+sdtstubo=""
 sdtinfoo=""
 if [ -n "${CONFIG_DTRACE}" ]; then
-       sdtstubso=.tmp_sdtstubs.o
+       sdtstubo=.tmp_sdtstub.o
        sdtinfoo=.tmp_sdtinfo.o
-       sdtstubs ${sdtstubso}
+       sdtstub ${sdtstubo}
 fi
 
 #link vmlinux.o
@@ -242,7 +237,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
        fi
 
        # step 1
-       vmlinux_link "${sdtstubso} ${sdtinfoo}" .tmp_vmlinux1
+       vmlinux_link "${sdtstubo} ${sdtinfoo}" .tmp_vmlinux1
        kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
 
        if [ -n "${CONFIG_DTRACE}" ]; then
@@ -250,7 +245,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
        fi
 
        # step 2
-       vmlinux_link "${sdtstubso} .tmp_kallsyms1.o ${sdtinfoo}" .tmp_vmlinux2
+       vmlinux_link "${sdtstubo} .tmp_kallsyms1.o ${sdtinfoo}" .tmp_vmlinux2
        kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
 
        # step 2a
@@ -258,14 +253,14 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
                kallsymso=.tmp_kallsyms3.o
                kallsyms_vmlinux=.tmp_vmlinux3
 
-               vmlinux_link "${sdtstubso} .tmp_kallsyms2.o ${sdtinfoo}" .tmp_vmlinux3
+               vmlinux_link "${sdtstubo} .tmp_kallsyms2.o ${sdtinfoo}" .tmp_vmlinux3
 
                kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
        fi
 fi
 
 info LD vmlinux
-vmlinux_link "${sdtstubso} ${kallsymso} ${sdtinfoo}" vmlinux
+vmlinux_link "${sdtstubo} ${kallsymso} ${sdtinfoo}" vmlinux
 
 if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
        info SORTEX vmlinux
index 91ee1b2e0f9aa65fbdcb471d8f6695489453029f..b5bd379634ded26553a31cdc563b3fa6bd2c2281 100644 (file)
@@ -2099,10 +2099,21 @@ static void check_exports(struct module *mod)
  **/
 static void add_header(struct buffer *b, struct module *mod)
 {
+       const char *modname;
+
+       if ((modname = strrchr(mod->name, '/')) != NULL)
+               modname++;
+       else
+               modname = mod->name;
+
        buf_printf(b, "#include <linux/module.h>\n");
        buf_printf(b, "#include <linux/vermagic.h>\n");
        buf_printf(b, "#include <linux/compiler.h>\n");
        buf_printf(b, "\n");
+       buf_printf(b, "#ifdef CONFIG_DTRACE\n");
+       buf_printf(b, "# include \"%s.sdtinfo.c\"\n", modname);
+       buf_printf(b, "#endif\n");
+       buf_printf(b, "\n");
        buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
        buf_printf(b, "\n");
        buf_printf(b, "__visible struct module __this_module\n");
@@ -2115,6 +2126,10 @@ static void add_header(struct buffer *b, struct module *mod)
                              "\t.exit = cleanup_module,\n"
                              "#endif\n");
        buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
+       buf_printf(b, "#ifdef CONFIG_DTRACE\n");
+       buf_printf(b, "\t.sdt_probes = _sdt_probes,\n");
+       buf_printf(b, "\t.num_dtrace_probes = _sdt_probec,\n");
+       buf_printf(b, "#endif\n");
        buf_printf(b, "};\n");
 }