# 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
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:
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
# 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 \
@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'
-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
# 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
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.
#
$(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.
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
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] $@
/*
* 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
#include <fcntl.h>
#include <limits.h>
#include <endian.h>
+#include <unistd.h>
#include <libelf.h>
#include <dwarf.h>
/*
* 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.
* 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
/*
* 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.
*/
/*
* 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.
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);
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;
for (i = 0; i < all_object_names_cnt; i++) {
single_object_name = all_object_names[i];
- run(output_dir);
+ run(output, 1);
}
}
/*
* 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;
* 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);
* 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;
dw_ctf_trace("Created CTF file for module %s: %p\n",
module_name, ctf_file);
- return ctf_file;
+ return;
}
/* DWARF walkers. */
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);
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
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_")) ||
/* 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);
}
}
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);
if ((chop = strrchr(module_name, '.')) != NULL)
*chop = '\0';
+ dash = module_name;
+ while (dash != NULL) {
+ dash = strchr(dash, '-');
+ if (dash != NULL)
+ *dash = '_';
+ }
+
return module_name;
}