aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.modpost11
-rw-r--r--scripts/mod/modpost.c164
-rw-r--r--scripts/mod/modpost.h3
3 files changed, 177 insertions, 1 deletions
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;