]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ctf: decouple CTF building from the kernel build
authorNick Alcock <nick.alcock@oracle.com>
Wed, 19 Jul 2017 14:34:14 +0000 (15:34 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 19 Sep 2017 08:33:31 +0000 (09:33 +0100)
This change causes CTF types for the core kernel and modules to be
generated only when the new 'ctf' make target is invoked.  The CTF content
is emitted into a CTF archive with the default name of vmlinux.ctfa (the
name read by DTrace userspace): this can be changed via the CTF_FILENAME
makefile variable.  If 'make ctf' has been run, 'make modules_install'
will install the generated CTF archive into the appropriate place. (If
CTF_FILENAME was specified on the 'make ctf' line, it needs to be passed
to 'make modules_install' as well for this to work.)

The existing link-into-modules machinery is still used for out-of-tree
modules, since these obviously cannot be visible when the vmlinux.ctfa
is built.

Usually the ctf target is invoked by kernel-uek.spec, but it can also
be invoked by developers if they know they have changed type or global
variable info while developing and would like DTrace to be able to
introspect the new data, or if they are building a kernel for the
first time and would like DTrace to be able to see its types at all.
(The archive format is fairly robust: you can often just copy
vmlinux.ctfa from one kernel to another, and types that have not
changed will continue to work with the new kernel.)

This depends on new machinery in libdtrace-ctf 0.7 or higher.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
Reviewed-by: Victor Erminpour <victor.erminpour@oracle.com>
Orabug: 25815362

Documentation/Changes
Makefile
scripts/Makefile.modpost
scripts/dwarf2ctf/dedup.blacklist
scripts/dwarf2ctf/dwarf2ctf.c
scripts/kallsyms.c

index a567f68b82ad72852c63a5065094ea383af0d91f..9a5a571eb2a48e5338b19748ffe97cf171fde52e 100644 (file)
@@ -49,7 +49,7 @@ Build-time requirements only, for DTrace:
 o  elfutils               0.152                   # eu-readelf --version
 o  pkg-config             0.16                    # pkg-config --version
 o  glib                   2.x                     # pkg-config --exists glib-2.0 && echo present
-o  libdtrace-ctf          0.3
+o  libdtrace-ctf          0.7
 
 Kernel compilation
 ==================
index ba6da1cd85c959096851e4dd8f55be2660a9209f..4971f939d870177a81b73b602cf06e02fa2e25b5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1112,6 +1112,9 @@ ifdef CONFIG_CTF
 # We need to force everything to be built, since we need the .o files below.
 KBUILD_BUILTIN := 1
 
+# Set a default CTF filename.
+CTF_FILENAME := vmlinux.ctfa
+
 # This contains all the object files that are unconditionally built into the
 # kernel, for consumption by dwarf2ctf in Makefile.modpost.
 # This is made doubly annoying by the presence of '.o' files which are actually
@@ -1129,6 +1132,14 @@ endif
                ar t "$$archive" | grep '\.o$$' | \
                        sed "s,^,$${archive%/*}/," >> objects.builtin; \
        done
+
+CTF_DEBUGDIR := .
+
+ctf: $(CTF_FILENAME)
+PHONY += ctf
+$(CTF_FILENAME):
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost CTF_FILENAME=$(CTF_FILENAME) CTF_DEBUGDIR=$(CTF_DEBUGDIR) $(CTF_FILENAME)
+
 else
 PHONY += objects.builtin
 objects.builtin:
@@ -1154,6 +1165,9 @@ _modinst_:
        fi
        @cp -f $(objtree)/modules.order $(MODLIB)/
        @cp -f $(objtree)/modules.builtin $(MODLIB)/
+       @if [ -f $(objtree)/$(CTF_FILENAME) ] ; then \
+               cp -f $(objtree)/$(CTF_FILENAME) $(MODLIB)/kernel ; \
+       fi
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
 
 # This depmod is only for convenience to give the initial
@@ -1202,6 +1216,7 @@ modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
 
 # Directories & files removed with 'make clean'
 CLEAN_DIRS  += $(MODVERDIR) .ctf
+CLEAN_FILES += .ctf.filelist
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_DIRS  += include/config usr/include include/generated          \
@@ -1297,6 +1312,8 @@ help:
        @echo  '                    (requires a recent binutils and recent build (System.map))'
        @echo  '  dir/file.ko     - Build module including final link'
        @echo  '  modules_prepare - Set up for building external modules'
+       @echo  '  ctf             - Generate CTF type information for DTrace, installed by '
+       @echo  '                    make modules_install'
        @echo  '  tags/TAGS       - Generate tags file for editors'
        @echo  '  cscope          - Generate cscope index'
        @echo  '  gtags           - Generate GNU GLOBAL index'
@@ -1466,7 +1483,7 @@ clean: $(clean-dirs)
                -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' \
-               -o -name '.tmp_*.o.*' \
+               -o -name '.tmp_*.o.*' -o -name '*.ctfa' \
                -o -name '*.gcno' \) -type f -print | xargs rm -f
 
 # Generate tags for editors
index 6b522fac214455cc4e7f9e6df21106c8ebea4279..0c3c924fbb11028f3bc2e0b991b4a727abba298f 100644 (file)
@@ -14,8 +14,9 @@
 # 3)  create one <module>.mod.c file pr. module
 # 4)  create one Module.symvers file with CRC for all exported symbols
 # 5) compute SDT offsets, generate SDT stubs, and compile all .mod.c files
-# 6) generate CTF for the entire kernel, or for the module alone if this is
-#    a build of an external module
+# 6) for external modules, generate CTF for the module (there is an extra,
+#    externally-invoked target that does this for the entire kernel but does
+#    not invoke the rst of the module-building process)
 # 7) final link of the module to a <module.ko> file
 
 # Step 3 is used to place certain information in the module's ELF
@@ -158,56 +159,54 @@ endif
 
 targets += $(modules:.ko=.mod.o)
 
-# Step 6), generate CTF for the entire kernel, or for the module alone if this
-# is a build of an external module.
+# Step 6), generate CTF for the entire kernel (in a separate $(CTF_FILENAME)),
+# or for the module alone if this is a build of an external module.
 
 ifdef CONFIG_CTF
 
+# These are overridden below for standalone modules only.
+module-ctfs-modular-prereq =
+module-ctfs-modular =
+module-ctf-flags =
+cmd_touch_ctf =
+ctf-dir = ///.nonexistent
+cmd-touch-ctf = @:
+
 # This is quite tricky.  If called for non-external-modules, dwarf2ctf needs to
 # be told about all the built-in objects as well as all the external modules --
 # but Makefile.modpost only knows about the latter.  So the toplevel makefile
 # emits the names of the built-in objects into a temporary file, which is
 # then catted and its contents used as prerequisites by this rule.
 #
-# Because we only run dwarf2ctf once (in non-standalone-module mode), and it
-# depends on a stamp file (because its real targets cannot change unless the
-# object files change, in which case a relink of the appropriate modules is
-# triggered anyway), we don't emit a filename in this output.
-#
-# Out-of-tree module CTF gets its own per-module set of stamp files, since its
-# CTF is rebuilt independently.
-#
 # We write the names of the object files to be scanned for CTF content into a
 # file, then use that, to avoid hitting command-line length limits.
 
 ifeq ($(KBUILD_EXTMOD),)
-ctf-dir := .ctf
-quiet_cmd_ctf = CTF
-      cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) $(srctree) objects.builtin modules.builtin $(srctree)/scripts/dwarf2ctf/dedup.blacklist $(srctree)/scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
-builtins := $(shell cat objects.builtin 2>/dev/null)
-ctf-stamp := .ctf/ctf.stamp
-ctf-filelist := .ctf/ctf.filelist
-
-# The CTF module depends on the CTF stamp file, in lieu of the builtin
-# CTF files whose names we cannot determine until it is too late.
-
-kernel/ctf/ctf.ko: .ctf/ctf.stamp
+ctf-dir-mk :=
+quiet_cmd_ctf = CTFA
+      cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(CTF_FILENAME) $(srctree) objects.builtin modules.builtin $(srctree)/scripts/dwarf2ctf/dedup.blacklist $(srctree)/scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
+ctf-builtins := $(CTF_DEBUGDIR)/vmlinux
+ ctf-modules := $(shell find $(CTF_DEBUGDIR) \( -name '*.ko' -o -name '*.ko.debug' \) -print)
+ctf-filelist := .ctf.filelist
+ctf-stamp :=
 
 else
 ctf-dir := $(KBUILD_EXTMOD)/.ctf
+ctf-dir-mk := $(ctf-dir)
 quiet_cmd_ctf = CTF
       cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) -e $(ctf-filelist)
-builtins :=
-ctf-stamp := $(ctf-dir)/$(notdir $(M)-extmod).stamp
+ctf-builtins :=
+ctf-modules := $(modules:.ko=.o)
 ctf-filelist := $(ctf-dir)/$(notdir $(M)-extmod).ctf.filelist
+ctf-stamp = $(ctf-dir)/$(notdir $(M)-extmod).stamp
 
-endif
-
-# All the modules' CTF likewise depends on the stamp file.
+# All the modules' CTF depends on the stamp file.
 
 all-module-ctfs = $(addprefix $(ctf-dir)/,$(notdir $(modules:.ko=.mod.ctf)))
 $(all-module-ctfs): $(ctf-stamp)
 
+endif
+
 # This ensures that the (possibly very long) prerequisite list is written out
 # using one shell invocation per prerequisite.
 #
@@ -220,26 +219,30 @@ define add-ctf-filelists-cmd
        $(foreach file,$(1),$(call add-ctf-filelist-cmd,$(file)))
 endef
 
-$(ctf-filelist): $(builtins) $(modules:.ko=.o) | $(sdtinfo-prereq)
+$(ctf-filelist): $(ctf-builtins) $(ctf-modules) | $(sdtinfo-prereq)
        @rm -f $(ctf-filelist);
-       @mkdir -p $(ctf-dir);
+       @if [[ -n "$(ctf-dir-mk)" ]]; then \
+               mkdir -p "$(ctf-dir-mk)"; \
+       fi
        $(call add-ctf-filelists-cmd,$^)
 
-# We depend upon a stamp file in lieu of the builtin modules' CTF files, because
-# the names of the generated CTF files for the builtins are so variable.
-# (Standalone modules get their own per-module stamp files.)
-# The stamp file then depends on the .o files for the modules, and on the
-# sdtinfo files, if any (for the same reason that the sdtstub does).
+ifeq ($(KBUILD_EXTMOD),)
+# The CTF depends on the output CTF file list, and that depends
+# on the .ko files for the modules.
+$(CTF_FILENAME): $(ctf-filelist)
+       $(call if_changed,ctf)
+else
+
+# The CTF depends on the output CTF file list, and that depends
+# on the .o files for the modules, and on the sdtinfo files, if any
+# (for the same reason that the sdtstub does).
 $(ctf-stamp): $(ctf-filelist)
        $(call if_changed,ctf)
        @shopt -s nullglob; \
-       for name in $(ctf-dir)/*.builtin.ctf; do \
-               [[ -f $${name}.new ]] || rm -f $$name; \
-       done; \
        for name in $(ctf-dir)/*.ctf.new; do \
                $(srctree)/scripts/move-if-change $$name $${name%.new}; \
-       done
-       @touch $(ctf-stamp)
+       done; \
+       touch $(ctf-stamp)
 
 # Expands to the names of the CTF files to be incorporated into this module.
 # The former is used in prerequisite lists, thanks to secondary expansion.
@@ -259,9 +262,6 @@ ctf-module-name = $(addprefix $(ctf-dir)/,$(notdir $(basename $@)).mod.ctf)
 
 module-ctf-flags = $(if $(filter ctf.ko,$(notdir $@)), \
                   --strip-debug \
-                  $(shell for builtin in $(ctf-dir)/*.builtin.ctf; do \
-                              printf "%s" "--add-section .ctf.$$(basename $$builtin .builtin.ctf)=$$builtin "; \
-                          done), \
                   --add-section .ctf=$(ctf-module-name))
 
 # We have to put content in our dummy no-CTF files because --add-section
@@ -271,15 +271,9 @@ cmd_touch_ctf = @for name in $(filter $(ctf-dir)/%,$(module-ctfs-modular)); do \
                    test -f $$name || dd if=/dev/zero of=$$name bs=1 count=1 2>/dev/null; \
                done
 
-else           # !CONFIG_CTF
+endif          # KBUILD_EXTMOD
 
-module-ctfs-modular-prereq =
-module-ctfs-builtin =
-module-ctf-flags =
-ctf-dir = ///.nonexistent
-cmd-touch-ctf = @:
-
-endif
+endif          # !CONFIG_CTF
 
 # Step 7), final link of the modules
 quiet_cmd_ld_ko_o = LD [M]  $@
index 5d588367556cf4f01f8cc0d7489a1e982369f74c..4898611d45b11e16d9ecfffba47afec9819c0139 100644 (file)
@@ -1,4 +1,4 @@
-snd-ens1371
-snd-opti93x
-snd-opti92x-cs4231
-snd-interwave-stb
+snd_ens1371
+snd_opti93x
+snd_opti92x_cs4231
+snd_interwave_stb
index 59f3ad02c88faeab797c24e6d6d12dc6abc3934d..639198c70363a62da0a19a3c2c1399c32e11b1cd 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * dwarf2ctf.c: Read in DWARF[23] debugging information from some set of ELF
- * files, and generate CTF in correspondingly-named files.
+ * files, and generate CTF in correspondingly-named files, or in a single
+ * representation meant for mmapping.
  *
- * (C) 2011 -- 2017 Oracle, Inc.  All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +22,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <endian.h>
+#include <unistd.h>
 
 #include <libelf.h>
 #include <dwarf.h>
@@ -59,9 +61,10 @@ static const char *trace;
 /*
  * Run dwarf2ctf over a single object file or set thereof.
  *
- * output_dir is the directory into which the CTF goes.
+ * output_dir is the directory into which the CTF goes, if 'standalone', or the
+ * CTF archive file name otherwise.
  */
-static void run(char *output_dir);
+static void run(char *output, int standalone);
 
 /*
  * A fully descriptive CTF type ID: both file and type ID in one place.
@@ -255,7 +258,7 @@ static void init_tu_to_modules(void);
  * If this is a local type table, and deduplication is active, make the global
  * type table its parent.
  */
-static ctf_file_t *init_ctf_table(const char *module_name);
+static void init_ctf_table(const char *module_name);
 
 /*
  * A few useful singleton CTF type IDs in the global type table: a void pointer
@@ -404,7 +407,7 @@ static void detect_duplicates(const char *module_name, const char *file_name,
 
 /*
  * Note in the detect_duplicates_id_file list that we will rescan a DIE in
- * a later duplicate detection pass
+ * a later duplicate detection pass.
  *
  * A type_id() callback.
  */
@@ -507,9 +510,9 @@ static void construct_ctf(const char *module_name, const char *file_name,
 
 /*
  * Write out the CTF files from the per_module->ctf_file into files in the
- * output_dir.
+ * output directory (if standalone), or into the output file (otherwise).
  */
-static void write_types(char *output_dir);
+static void write_types(char *output, int standalone);
 
 /*
  * Construct CTF out of each type and return that type's ID and file.
@@ -827,21 +830,21 @@ static void free_duplicates_id_file(void *id_file);
 
 int main(int argc, char *argv[])
 {
-       char *output_dir;
+       char *output;
 
        trace = getenv("DWARF2CTF_TRACE");
 
        if ((argc != 4 && argc != 8) ||
            (argc == 4 && strcmp(argv[2], "-e") != 0)) {
-               fprintf(stderr, "Syntax: dwarf2ctf outputdir srcdir "
+               fprintf(stderr, "Syntax: dwarf2ctf output-file srcdir "
                        "objects.builtin modules.builtin dedup.blacklist\n");
                fprintf(stderr, "                  member.blacklist filelist\n");
-               fprintf(stderr, "    or dwarf2ctf outputdir -e filelist\n"
+               fprintf(stderr, "    or dwarf2ctf output-dir -e filelist\n"
                        "for external module use\n");
                exit(1);
        }
 
-       output_dir = argv[1];
+       output = argv[1];
 
        elf_version(EV_CURRENT);
 
@@ -876,7 +879,7 @@ int main(int argc, char *argv[])
                init_member_blacklist(member_blacklist_file, srcdir);
                init_object_names(argv[7]);
 
-               run(output_dir);
+               run(output, 0);
        } else {
                char *single_object_name;
                char **all_object_names;
@@ -897,7 +900,7 @@ int main(int argc, char *argv[])
                for (i = 0; i < all_object_names_cnt; i++) {
                        single_object_name = all_object_names[i];
 
-                       run(output_dir);
+                       run(output, 1);
                }
        }
 
@@ -910,9 +913,10 @@ int main(int argc, char *argv[])
 /*
  * Run dwarf2ctf over a single object file or set thereof.
  *
- * output_dir is the directory into which the CTF goes.
+ * output is the directory into which the CTF goes, if 'standalone', or the
+ * CTF archive file name otherwise.
  */
-static void run(char *output_dir)
+static void run(char *output, int standalone)
 {
        size_t i;
 
@@ -952,7 +956,7 @@ static void run(char *output_dir)
         * necessary linker scripts.
         */
        dw_ctf_trace("Writeout.\n");
-       write_types(output_dir);
+       write_types(output, standalone);
 
        g_hash_table_destroy(id_to_type);
        g_hash_table_destroy(id_to_module);
@@ -1355,7 +1359,7 @@ static int member_blacklisted(Dwarf_Die *die, Dwarf_Die *parent_die)
  * If this is a local type table, and deduplication is active, make the global
  * type table its parent.
  */
-static ctf_file_t *init_ctf_table(const char *module_name)
+static void init_ctf_table(const char *module_name)
 {
        ctf_file_t *ctf_file;
        per_module_t *new_per_mod;
@@ -1433,7 +1437,7 @@ static ctf_file_t *init_ctf_table(const char *module_name)
        dw_ctf_trace("Created CTF file for module %s: %p\n",
                     module_name, ctf_file);
 
-       return ctf_file;
+       return;
 }
 
 /* DWARF walkers.  */
@@ -2034,6 +2038,20 @@ static void detect_duplicates_tu_init(const char *module_name,
                                      void *data)
 {
        struct detect_duplicates_state *state = data;
+       per_module_t *per_mod;
+
+       /*
+        * Make sure that even if this module has no types in it we still end up
+        * generating a CTF file.  (Userspace depends on this, since a CTF file
+        * with no types in means the module is known and typeless, while no CTF
+        * file at all means the module is not known.)
+        */
+
+       per_mod = g_hash_table_lookup(per_module, module_name);
+       if (per_mod == NULL) {
+               init_ctf_table(module_name);
+               dw_ctf_trace("%s: initialized CTF file.\n", module_name);
+       }
 
        state->structs_seen = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                    free, NULL);
@@ -2801,12 +2819,6 @@ static ctf_full_id_t *construct_ctf_id(const char *module_name,
 
        ctf = lookup_ctf_file(ctf_module);
 
-       if (ctf == NULL) {
-               ctf = init_ctf_table(ctf_module);
-               dw_ctf_trace("%p: %s: initialized CTF file %p\n", &id,
-                            ctf_module, ctf);
-       }
-
        /*
         * Construct the CTF, then insert the top-level CTF entity into the
         * id->type hash so that references from other types can find it, and
@@ -3290,6 +3302,7 @@ static int filter_ctf_uninteresting(Dwarf_Die *die,
        return ((dwarf_tag(parent_die) == DW_TAG_compile_unit) &&
                !((strcmp(sym_name, "__per_cpu_start") == 0) ||
                  (strcmp(sym_name, "__per_cpu_end") == 0) ||
+                 (strcmp(sym_name, "_sdt_probes") == 0) ||
                  (strstarts(sym_name, "__crc_")) ||
                  (strstarts(sym_name, "__ksymtab_")) ||
                  (strstarts(sym_name, "__kcrctab_")) ||
@@ -4211,81 +4224,96 @@ static ctf_id_t assemble_ctf_variable(const char *module_name,
 
 /* Writeout.  */
 
-static void write_types(char *output_dir)
+static void write_types(char *output, int standalone)
 {
        GHashTableIter module_iter;
        char *module;
        per_module_t *per_mod;
+       ctf_file_t **ctfs;
+       const char **names;
+       size_t i = 0;
+       size_t ctf_count = g_hash_table_size(per_module);
 
        /*
-        * Work over all the modules and write their compressed CTF data out
-        * into the output directory.  Built-in modules get names ending in
-        * .builtin.ctf.new; others get names ending in .mod.ctf.new.  The
-        * makefile moves .ctf.new over the top of .ctf iff it has changed.
+        * Work over all the modules and write their compressed CTF data out.
+        * Standalone modules get placed in files in the output directory named
+        * with names ending in .mod.ctf.new, and the makefile moves .ctf.new
+        * over the top of .ctf iff it has changed; built-in modules and the
+        * core kernel and shared type repository are placed into a CTF archive.
         */
-
-       if ((mkdir(output_dir, 0777) < 0) && errno != EEXIST) {
-               fprintf(stderr, "Cannot create .ctf directory: %s\n",
-                       strerror(errno));
-               exit(1);
+       if (standalone) {
+               if ((mkdir(output, 0777) < 0) && errno != EEXIST) {
+                       fprintf(stderr, "Cannot create .ctf directory: %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+       } else {
+               ctfs = calloc(ctf_count, sizeof (ctf_file_t *));
+               names = calloc(ctf_count, sizeof (char *));
+               if (!ctfs || !names) {
+                       fprintf (stderr, "Out of memory in CTF writeout\n");
+               }
        }
 
+       /*
+        * Write the files out (in standalone mode), or construct the arrays of
+        * module names and files to put in the archive (otherwise).
+        */
        g_hash_table_iter_init(&module_iter, per_module);
        while (g_hash_table_iter_next(&module_iter, (void **) &module,
                                      (void **)&per_mod)) {
-               char *path = NULL;
-               gzFile fd;
-               int builtin_module = 0;
+               int fd;
 
                dw_ctf_trace("Writing out %s\n", module);
 
-               if ((strcmp(module, "shared_ctf") == 0) ||
-                   (strcmp(module, "vmlinux") == 0))
-                       builtin_module = 1;
-               else {
-                       size_t module_num;
-
-                       for (module_num = 0; module_num < builtin_modules_cnt;
-                            module_num++) {
-                               char *module_name = fn_to_module(builtin_modules[module_num]);
-
-                               if (strcmp(module_name, module) == 0)
-                                       builtin_module = 1;
-
-                               free(module_name);
-                       }
-               }
-
-               path = str_appendn(path, output_dir, "/", module,
-                                  builtin_module ? ".builtin" : ".mod",
-                                  ".ctf.new", NULL);
-
-               dw_ctf_trace("Writeout path: %s\n", path);
-
                if (ctf_update(per_mod->ctf_file) < 0) {
                        fprintf(stderr, "Cannot serialize CTF file %s: %s\n",
-                               path, ctf_errmsg(ctf_errno(per_mod->ctf_file)));
+                               module, ctf_errmsg(ctf_errno(per_mod->ctf_file)));
                        exit(1);
                }
 
-               if ((fd = gzopen(path, "wb")) == NULL) {
-                       fprintf(stderr, "Cannot open CTF file %s for writing: "
-                               "%s\n", path, strerror(errno));
-                       exit(1);
-               }
-               if (ctf_gzwrite(per_mod->ctf_file, fd) < 0) {
-                       fprintf(stderr, "Cannot write to CTF file %s: "
-                               "%s\n", path,
-                               ctf_errmsg(ctf_errno(per_mod->ctf_file)));
-                       exit(1);
+               if (!standalone) {
+                       names[i] = module;
+                       ctfs[i] = per_mod->ctf_file;
+                       i++;
+               } else {
+                       char *path = NULL;
+                       path = str_appendn(path, output, "/", module,
+                                          ".mod.ctf.new", NULL);
+
+                       if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC |
+                                      O_CLOEXEC, 0666)) < 0) {
+                               fprintf(stderr, "Cannot open CTF file %s for "
+                                       "writing: %s\n", path,
+                                       strerror(errno));
+                               exit(1);
+                       }
+                       if (ctf_compress_write(per_mod->ctf_file, fd) < 0) {
+                               fprintf(stderr, "Cannot write to CTF file %s: "
+                                       "%s\n", path,
+                                       ctf_errmsg(ctf_errno(per_mod->ctf_file)));
+                               exit(1);
+                       }
+                       if (close(fd) != 0) {
+                               fprintf(stderr, "Cannot close CTF file %s: %s\n",
+                                       path, strerror(errno));
+                               exit(1);
+                       }
+                       free(path);
                }
+       }
 
-               if (gzclose(fd) != Z_OK) {
-                       fprintf(stderr, "Cannot close CTF file %s: %s\n",
-                               path, strerror(errno));
+       if (!standalone) {
+               int err;
+               if ((err = ctf_arc_write(output, ctfs, ctf_count,
+                                        names, 4096) != 0)) {
+                       fprintf(stderr, "Cannot write to CTF archive %s: %s\n",
+                               output, err < ECTF_BASE ? strerror(err) :
+                               ctf_errmsg(err));
                        exit(1);
                }
-               free(path);
+               free(names);
+               free(ctfs);
        }
 }
 
@@ -4576,7 +4604,7 @@ static GList *list_filter(GList *list, filter_pred_fun fun,
 static char *fn_to_module(const char *file_name)
 {
        char *module_name;
-       char *chop;
+       char *chop, *dash;
 
        if ((chop = strrchr(file_name, '/')) != NULL)
                module_name = xstrdup(++chop);
@@ -4586,6 +4614,13 @@ static char *fn_to_module(const char *file_name)
        if ((chop = strrchr(module_name, '.')) != NULL)
                *chop = '\0';
 
+       dash = module_name;
+       while (dash != NULL) {
+               dash = strchr(dash, '-');
+               if (dash != NULL)
+                       *dash = '_';
+       }
+
        return module_name;
 }
 
index 907959f83ae757b0831f11700e5d63f0bf1488f2..6bca66f9dc9449bbc82bf8219b183d9e9fcc37dc 100644 (file)
@@ -935,7 +935,8 @@ static void read_modules(const char *modules_builtin)
        /*
         * Read in, stripping off the leading path element, if any, transforming
         * the suffix into .o from .ko, and also computing the suffixless,
-        * pathless name of the module.  Any elements that don't have files
+        * pathless name of the module, translating - into _ to match what is
+        * done for real module names. Any elements that don't have files
         * corresponding to them elicit a warning, and do not have their names
         * recorded.
         */
@@ -960,11 +961,18 @@ static void read_modules(const char *modules_builtin)
 
                        if (access(first_slash, R_OK) == 0) {
                                char *module_name = strdup(last_slash);
+                               char *dash = module_name;
 
                                last_dot = strrchr(module_name, '.');
                                if (last_dot != NULL)
                                        *last_dot = '\0';
 
+                               while (dash != NULL) {
+                                       dash = strchr(dash, '-');
+                                       if (dash != NULL)
+                                               *dash = '_';
+                               }
+
                                read_module_symbols(builtin_module_len, first_slash,
                                        module_symbol_seen);