aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2008-02-13 18:03:39 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-13 19:21:20 -0500
commitb2e3e658b344c6bcfb8fb694100ab2f2b5b2edb0 (patch)
treea2999226edcb6b293c2044716a0146c7f2f82a22
parentfb40bd78b0f91b274879cf5db8facd1e04b6052e (diff)
Linux Kernel Markers: create modpost file
This adds some new magic in the MODPOST phase for CONFIG_MARKERS. Analogous to the Module.symvers file, the build will now write a Module.markers file when CONFIG_MARKERS=y is set. This file lists the name, defining module, and format string of each marker, separated by \t characters. This simple text file can be used by offline build procedures for instrumentation code, analogous to how System.map and Module.symvers can be useful to have for kernels other than the one you are running right now. The strings are made easy to extract by having the __trace_mark macro define the name and format together in a single array called __mstrtab_* in the __markers_strings section. This is straightforward and reliable as long as the marker structs are always defined by this macro. It is an unreasonable amount of hairy work to extract the string pointers from the __markers section structs, which entails handling a relocation type for every machine under the sun. Mathieu : - Ran through checkpatch.pl Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: David Smith <dsmith@redhat.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/marker.h9
-rw-r--r--scripts/Makefile.modpost11
-rw-r--r--scripts/mod/modpost.c164
-rw-r--r--scripts/mod/modpost.h3
4 files changed, 180 insertions, 7 deletions
diff --git a/include/linux/marker.h b/include/linux/marker.h
index b5f95637f289..5df879dc3776 100644
--- a/include/linux/marker.h
+++ b/include/linux/marker.h
@@ -61,15 +61,12 @@ struct marker {
61 */ 61 */
62#define __trace_mark(name, call_private, format, args...) \ 62#define __trace_mark(name, call_private, format, args...) \
63 do { \ 63 do { \
64 static const char __mstrtab_name_##name[] \ 64 static const char __mstrtab_##name[] \
65 __attribute__((section("__markers_strings"))) \ 65 __attribute__((section("__markers_strings"))) \
66 = #name; \ 66 = #name "\0" format; \
67 static const char __mstrtab_format_##name[] \
68 __attribute__((section("__markers_strings"))) \
69 = format; \
70 static struct marker __mark_##name \ 67 static struct marker __mark_##name \
71 __attribute__((section("__markers"), aligned(8))) = \ 68 __attribute__((section("__markers"), aligned(8))) = \
72 { __mstrtab_name_##name, __mstrtab_format_##name, \ 69 { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
73 0, 0, marker_probe_cb, \ 70 0, 0, marker_probe_cb, \
74 { __mark_empty_function, NULL}, NULL }; \ 71 { __mark_empty_function, NULL}, NULL }; \
75 __mark_check_format(format, ## args); \ 72 __mark_check_format(format, ## args); \
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 65e707e1ffc3..cfc004e04417 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -13,6 +13,7 @@
13# 2) modpost is then used to 13# 2) modpost is then used to
14# 3) create one <module>.mod.c file pr. module 14# 3) create one <module>.mod.c file pr. module
15# 4) create one Module.symvers file with CRC for all exported symbols 15# 4) create one Module.symvers file with CRC for all exported symbols
16# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
16# 5) compile all <module>.mod.c files 17# 5) compile all <module>.mod.c files
17# 6) final link of the module to a <module.ko> file 18# 6) final link of the module to a <module.ko> file
18 19
@@ -45,6 +46,10 @@ include scripts/Makefile.lib
45 46
46kernelsymfile := $(objtree)/Module.symvers 47kernelsymfile := $(objtree)/Module.symvers
47modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers 48modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
49kernelmarkersfile := $(objtree)/Module.markers
50modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
51
52markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
48 53
49# Step 1), find all modules listed in $(MODVERDIR)/ 54# Step 1), find all modules listed in $(MODVERDIR)/
50__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) 55__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
@@ -63,6 +68,8 @@ modpost = scripts/mod/modpost \
63 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ 68 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
64 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ 69 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
65 $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ 70 $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
71 $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
72 $(if $(CONFIG_MARKERS),-M $(markersfile)) \
66 $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) 73 $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
67 74
68quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules 75quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
@@ -82,6 +89,10 @@ vmlinux.o: FORCE
82$(symverfile): __modpost ; 89$(symverfile): __modpost ;
83$(modules:.ko=.mod.c): __modpost ; 90$(modules:.ko=.mod.c): __modpost ;
84 91
92ifdef CONFIG_MARKERS
93$(markersfile): __modpost ;
94endif
95
85 96
86# Step 5), compile all *.mod.c files 97# Step 5), compile all *.mod.c files
87 98
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index dbe1fb5e8cc0..61742771c65d 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -11,6 +11,8 @@
11 * Usage: modpost vmlinux module1.o module2.o ... 11 * Usage: modpost vmlinux module1.o module2.o ...
12 */ 12 */
13 13
14#define _GNU_SOURCE
15#include <stdio.h>
14#include <ctype.h> 16#include <ctype.h>
15#include "modpost.h" 17#include "modpost.h"
16#include "../../include/linux/license.h" 18#include "../../include/linux/license.h"
@@ -435,6 +437,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
435 info->export_unused_gpl_sec = i; 437 info->export_unused_gpl_sec = i;
436 else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 438 else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
437 info->export_gpl_future_sec = i; 439 info->export_gpl_future_sec = i;
440 else if (strcmp(secname, "__markers_strings") == 0)
441 info->markers_strings_sec = i;
438 442
439 if (sechdrs[i].sh_type != SHT_SYMTAB) 443 if (sechdrs[i].sh_type != SHT_SYMTAB)
440 continue; 444 continue;
@@ -1470,6 +1474,62 @@ static void check_sec_ref(struct module *mod, const char *modname,
1470 } 1474 }
1471} 1475}
1472 1476
1477static void get_markers(struct elf_info *info, struct module *mod)
1478{
1479 const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
1480 const char *strings = (const char *) info->hdr + sh->sh_offset;
1481 const Elf_Sym *sym, *first_sym, *last_sym;
1482 size_t n;
1483
1484 if (!info->markers_strings_sec)
1485 return;
1486
1487 /*
1488 * First count the strings. We look for all the symbols defined
1489 * in the __markers_strings section named __mstrtab_*. For
1490 * these local names, the compiler puts a random .NNN suffix on,
1491 * so the names don't correspond exactly.
1492 */
1493 first_sym = last_sym = NULL;
1494 n = 0;
1495 for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
1496 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
1497 sym->st_shndx == info->markers_strings_sec &&
1498 !strncmp(info->strtab + sym->st_name,
1499 "__mstrtab_", sizeof "__mstrtab_" - 1)) {
1500 if (first_sym == NULL)
1501 first_sym = sym;
1502 last_sym = sym;
1503 ++n;
1504 }
1505
1506 if (n == 0)
1507 return;
1508
1509 /*
1510 * Now collect each name and format into a line for the output.
1511 * Lines look like:
1512 * marker_name vmlinux marker %s format %d
1513 * The format string after the second \t can use whitespace.
1514 */
1515 mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
1516 mod->nmarkers = n;
1517
1518 n = 0;
1519 for (sym = first_sym; sym <= last_sym; sym++)
1520 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
1521 sym->st_shndx == info->markers_strings_sec &&
1522 !strncmp(info->strtab + sym->st_name,
1523 "__mstrtab_", sizeof "__mstrtab_" - 1)) {
1524 const char *name = strings + sym->st_value;
1525 const char *fmt = strchr(name, '\0') + 1;
1526 char *line = NULL;
1527 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
1528 NOFAIL(line);
1529 mod->markers[n++] = line;
1530 }
1531}
1532
1473static void read_symbols(char *modname) 1533static void read_symbols(char *modname)
1474{ 1534{
1475 const char *symname; 1535 const char *symname;
@@ -1521,6 +1581,8 @@ static void read_symbols(char *modname)
1521 get_src_version(modname, mod->srcversion, 1581 get_src_version(modname, mod->srcversion,
1522 sizeof(mod->srcversion)-1); 1582 sizeof(mod->srcversion)-1);
1523 1583
1584 get_markers(&info, mod);
1585
1524 parse_elf_finish(&info); 1586 parse_elf_finish(&info);
1525 1587
1526 /* Our trick to get versioning for struct_module - it's 1588 /* Our trick to get versioning for struct_module - it's
@@ -1867,16 +1929,104 @@ static void write_dump(const char *fname)
1867 write_if_changed(&buf, fname); 1929 write_if_changed(&buf, fname);
1868} 1930}
1869 1931
1932static void add_marker(struct module *mod, const char *name, const char *fmt)
1933{
1934 char *line = NULL;
1935 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
1936 NOFAIL(line);
1937
1938 mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
1939 sizeof mod->markers[0])));
1940 mod->markers[mod->nmarkers++] = line;
1941}
1942
1943static void read_markers(const char *fname)
1944{
1945 unsigned long size, pos = 0;
1946 void *file = grab_file(fname, &size);
1947 char *line;
1948
1949 if (!file) /* No old markers, silently ignore */
1950 return;
1951
1952 while ((line = get_next_line(&pos, file, size))) {
1953 char *marker, *modname, *fmt;
1954 struct module *mod;
1955
1956 marker = line;
1957 modname = strchr(marker, '\t');
1958 if (!modname)
1959 goto fail;
1960 *modname++ = '\0';
1961 fmt = strchr(modname, '\t');
1962 if (!fmt)
1963 goto fail;
1964 *fmt++ = '\0';
1965 if (*marker == '\0' || *modname == '\0')
1966 goto fail;
1967
1968 mod = find_module(modname);
1969 if (!mod) {
1970 if (is_vmlinux(modname))
1971 have_vmlinux = 1;
1972 mod = new_module(NOFAIL(strdup(modname)));
1973 mod->skip = 1;
1974 }
1975
1976 add_marker(mod, marker, fmt);
1977 }
1978 return;
1979fail:
1980 fatal("parse error in markers list file\n");
1981}
1982
1983static int compare_strings(const void *a, const void *b)
1984{
1985 return strcmp(*(const char **) a, *(const char **) b);
1986}
1987
1988static void write_markers(const char *fname)
1989{
1990 struct buffer buf = { };
1991 struct module *mod;
1992 size_t i;
1993
1994 for (mod = modules; mod; mod = mod->next)
1995 if ((!external_module || !mod->skip) && mod->markers != NULL) {
1996 /*
1997 * Sort the strings so we can skip duplicates when
1998 * we write them out.
1999 */
2000 qsort(mod->markers, mod->nmarkers,
2001 sizeof mod->markers[0], &compare_strings);
2002 for (i = 0; i < mod->nmarkers; ++i) {
2003 char *line = mod->markers[i];
2004 buf_write(&buf, line, strlen(line));
2005 while (i + 1 < mod->nmarkers &&
2006 !strcmp(mod->markers[i],
2007 mod->markers[i + 1]))
2008 free(mod->markers[i++]);
2009 free(mod->markers[i]);
2010 }
2011 free(mod->markers);
2012 mod->markers = NULL;
2013 }
2014
2015 write_if_changed(&buf, fname);
2016}
2017
1870int main(int argc, char **argv) 2018int main(int argc, char **argv)
1871{ 2019{
1872 struct module *mod; 2020 struct module *mod;
1873 struct buffer buf = { }; 2021 struct buffer buf = { };
1874 char *kernel_read = NULL, *module_read = NULL; 2022 char *kernel_read = NULL, *module_read = NULL;
1875 char *dump_write = NULL; 2023 char *dump_write = NULL;
2024 char *markers_read = NULL;
2025 char *markers_write = NULL;
1876 int opt; 2026 int opt;
1877 int err; 2027 int err;
1878 2028
1879 while ((opt = getopt(argc, argv, "i:I:msSo:aw")) != -1) { 2029 while ((opt = getopt(argc, argv, "i:I:msSo:awM:K:")) != -1) {
1880 switch (opt) { 2030 switch (opt) {
1881 case 'i': 2031 case 'i':
1882 kernel_read = optarg; 2032 kernel_read = optarg;
@@ -1903,6 +2053,12 @@ int main(int argc, char **argv)
1903 case 'w': 2053 case 'w':
1904 warn_unresolved = 1; 2054 warn_unresolved = 1;
1905 break; 2055 break;
2056 case 'M':
2057 markers_write = optarg;
2058 break;
2059 case 'K':
2060 markers_read = optarg;
2061 break;
1906 default: 2062 default:
1907 exit(1); 2063 exit(1);
1908 } 2064 }
@@ -1950,5 +2106,11 @@ int main(int argc, char **argv)
1950 "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n", 2106 "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
1951 sec_mismatch_count); 2107 sec_mismatch_count);
1952 2108
2109 if (markers_read)
2110 read_markers(markers_read);
2111
2112 if (markers_write)
2113 write_markers(markers_write);
2114
1953 return err; 2115 return err;
1954} 2116}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 999f15e0e008..565c5872407e 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -112,6 +112,8 @@ struct module {
112 int has_init; 112 int has_init;
113 int has_cleanup; 113 int has_cleanup;
114 struct buffer dev_table_buf; 114 struct buffer dev_table_buf;
115 char **markers;
116 size_t nmarkers;
115 char srcversion[25]; 117 char srcversion[25];
116}; 118};
117 119
@@ -126,6 +128,7 @@ struct elf_info {
126 Elf_Section export_gpl_sec; 128 Elf_Section export_gpl_sec;
127 Elf_Section export_unused_gpl_sec; 129 Elf_Section export_unused_gpl_sec;
128 Elf_Section export_gpl_future_sec; 130 Elf_Section export_gpl_future_sec;
131 Elf_Section markers_strings_sec;
129 const char *strtab; 132 const char *strtab;
130 char *modinfo; 133 char *modinfo;
131 unsigned int modinfo_len; 134 unsigned int modinfo_len;