Attachment 'linux-kernel-markers-create-modpost-file.patch'

Download

   1 From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
   2 
   3 This adds some new magic in the MODPOST phase for CONFIG_MARKERS.  Analogous
   4 to the Module.symvers file, the build will now write a Module.markers file
   5 when CONFIG_MARKERS=y is set.  This file lists the name, defining module, and
   6 format string of each marker, separated by \t characters.  This simple text
   7 file can be used by offline build procedures for instrumentation code,
   8 analogous to how System.map and Module.symvers can be useful to have for
   9 kernels other than the one you are running right now.
  10 
  11 The strings are made easy to extract by having the __trace_mark macro define
  12 the name and format together in a single array called __mstrtab_* in the
  13 __markers_strings section.  This is straightforward and reliable as long as
  14 the marker structs are always defined by this macro.  It is an unreasonable
  15 amount of hairy work to extract the string pointers from the __markers section
  16 structs, which entails handling a relocation type for every machine under the
  17 sun.
  18 
  19 Mathieu :
  20 - Ran through checkpatch.pl
  21 
  22 Signed-off-by: Roland McGrath <roland@redhat.com>
  23 Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
  24 Cc: David Smith <dsmith@redhat.com>
  25 Cc: Sam Ravnborg <sam@ravnborg.org>
  26 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  27 ---
  28 
  29  include/linux/marker.h   |    9 --
  30  scripts/Makefile.modpost |   11 ++
  31  scripts/mod/modpost.c    |  164 ++++++++++++++++++++++++++++++++++++-
  32  scripts/mod/modpost.h    |    3 
  33  4 files changed, 180 insertions(+), 7 deletions(-)
  34 
  35 diff -puN include/linux/marker.h~linux-kernel-markers-create-modpost-file include/linux/marker.h
  36 --- a/include/linux/marker.h~linux-kernel-markers-create-modpost-file
  37 +++ a/include/linux/marker.h
  38 @@ -61,15 +61,12 @@ struct marker {
  39   */
  40  #define __trace_mark(name, call_private, format, args...)		\
  41  	do {								\
  42 -		static const char __mstrtab_name_##name[]		\
  43 +		static const char __mstrtab_##name[]			\
  44  		__attribute__((section("__markers_strings")))		\
  45 -		= #name;						\
  46 -		static const char __mstrtab_format_##name[]		\
  47 -		__attribute__((section("__markers_strings")))		\
  48 -		= format;						\
  49 +		= #name "\0" format;					\
  50  		static struct marker __mark_##name			\
  51  		__attribute__((section("__markers"), aligned(8))) =	\
  52 -		{ __mstrtab_name_##name, __mstrtab_format_##name,	\
  53 +		{ __mstrtab_##name, &__mstrtab_##name[sizeof(#name)],	\
  54  		0, 0, marker_probe_cb,					\
  55  		{ __mark_empty_function, NULL}, NULL };			\
  56  		__mark_check_format(format, ## args);			\
  57 diff -puN scripts/Makefile.modpost~linux-kernel-markers-create-modpost-file scripts/Makefile.modpost
  58 --- a/scripts/Makefile.modpost~linux-kernel-markers-create-modpost-file
  59 +++ a/scripts/Makefile.modpost
  60 @@ -13,6 +13,7 @@
  61  # 2) modpost is then used to
  62  # 3)  create one <module>.mod.c file pr. module
  63  # 4)  create one Module.symvers file with CRC for all exported symbols
  64 +# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
  65  # 5) compile all <module>.mod.c files
  66  # 6) final link of the module to a <module.ko> file
  67  
  68 @@ -45,6 +46,10 @@ include scripts/Makefile.lib
  69  
  70  kernelsymfile := $(objtree)/Module.symvers
  71  modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
  72 +kernelmarkersfile := $(objtree)/Module.markers
  73 +modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
  74 +
  75 +markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
  76  
  77  # Step 1), find all modules listed in $(MODVERDIR)/
  78  __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
  79 @@ -62,6 +67,8 @@ modpost = scripts/mod/modpost           
  80   $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)   \
  81   $(if $(KBUILD_EXTMOD),-I $(modulesymfile))      \
  82   $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
  83 + $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
  84 + $(if $(CONFIG_MARKERS),-M $(markersfile))	 \
  85   $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
  86  
  87  quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
  88 @@ -81,6 +88,10 @@ vmlinux.o: FORCE
  89  $(symverfile):         __modpost ;
  90  $(modules:.ko=.mod.c): __modpost ;
  91  
  92 +ifdef CONFIG_MARKERS
  93 +$(markersfile):	       __modpost ;
  94 +endif
  95 +
  96  
  97  # Step 5), compile all *.mod.c files
  98  
  99 diff -puN scripts/mod/modpost.c~linux-kernel-markers-create-modpost-file scripts/mod/modpost.c
 100 --- a/scripts/mod/modpost.c~linux-kernel-markers-create-modpost-file
 101 +++ a/scripts/mod/modpost.c
 102 @@ -11,6 +11,8 @@
 103   * Usage: modpost vmlinux module1.o module2.o ...
 104   */
 105  
 106 +#define _GNU_SOURCE
 107 +#include <stdio.h>
 108  #include <ctype.h>
 109  #include "modpost.h"
 110  #include "../../include/linux/license.h"
 111 @@ -424,6 +426,8 @@ static int parse_elf(struct elf_info *in
 112  			info->export_unused_gpl_sec = i;
 113  		else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
 114  			info->export_gpl_future_sec = i;
 115 +		else if (strcmp(secname, "__markers_strings") == 0)
 116 +			info->markers_strings_sec = i;
 117  
 118  		if (sechdrs[i].sh_type != SHT_SYMTAB)
 119  			continue;
 120 @@ -1249,6 +1253,62 @@ static int exit_section_ref_ok(const cha
 121  	return 0;
 122  }
 123  
 124 +static void get_markers(struct elf_info *info, struct module *mod)
 125 +{
 126 +	const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
 127 +	const char *strings = (const char *) info->hdr + sh->sh_offset;
 128 +	const Elf_Sym *sym, *first_sym, *last_sym;
 129 +	size_t n;
 130 +
 131 +	if (!info->markers_strings_sec)
 132 +		return;
 133 +
 134 +	/*
 135 +	 * First count the strings.  We look for all the symbols defined
 136 +	 * in the __markers_strings section named __mstrtab_*.  For
 137 +	 * these local names, the compiler puts a random .NNN suffix on,
 138 +	 * so the names don't correspond exactly.
 139 +	 */
 140 +	first_sym = last_sym = NULL;
 141 +	n = 0;
 142 +	for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
 143 +		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
 144 +		    sym->st_shndx == info->markers_strings_sec &&
 145 +		    !strncmp(info->strtab + sym->st_name,
 146 +			     "__mstrtab_", sizeof "__mstrtab_" - 1)) {
 147 +			if (first_sym == NULL)
 148 +				first_sym = sym;
 149 +			last_sym = sym;
 150 +			++n;
 151 +		}
 152 +
 153 +	if (n == 0)
 154 +		return;
 155 +
 156 +	/*
 157 +	 * Now collect each name and format into a line for the output.
 158 +	 * Lines look like:
 159 +	 *	marker_name	vmlinux	marker %s format %d
 160 +	 * The format string after the second \t can use whitespace.
 161 +	 */
 162 +	mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
 163 +	mod->nmarkers = n;
 164 +
 165 +	n = 0;
 166 +	for (sym = first_sym; sym <= last_sym; sym++)
 167 +		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
 168 +		    sym->st_shndx == info->markers_strings_sec &&
 169 +		    !strncmp(info->strtab + sym->st_name,
 170 +			     "__mstrtab_", sizeof "__mstrtab_" - 1)) {
 171 +			const char *name = strings + sym->st_value;
 172 +			const char *fmt = strchr(name, '\0') + 1;
 173 +			char *line = NULL;
 174 +			asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
 175 +			NOFAIL(line);
 176 +			mod->markers[n++] = line;
 177 +		}
 178 +}
 179 +
 180  static void read_symbols(char *modname)
 181  {
 182  	const char *symname;
 183 @@ -1301,6 +1361,8 @@ static void read_symbols(char *modname)
 184  		get_src_version(modname, mod->srcversion,
 185  				sizeof(mod->srcversion)-1);
 186  
 187 +	get_markers(&info, mod);
 188 +
 189  	parse_elf_finish(&info);
 190  
 191  	/* Our trick to get versioning for struct_module - it's
 192 @@ -1649,6 +1711,92 @@ static void write_dump(const char *fname
 193  	write_if_changed(&buf, fname);
 194  }
 195  
 196 +static void add_marker(struct module *mod, const char *name, const char *fmt)
 197 +{
 198 +	char *line = NULL;
 199 +	asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
 200 +	NOFAIL(line);
 201 +
 202 +	mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
 203 +						     sizeof mod->markers[0])));
 204 +	mod->markers[mod->nmarkers++] = line;
 205 +}
 206 +
 207 +static void read_markers(const char *fname)
 208 +{
 209 +	unsigned long size, pos = 0;
 210 +	void *file = grab_file(fname, &size);
 211 +	char *line;
 212 +
 213 +	if (!file)		/* No old markers, silently ignore */
 214 +		return;
 215 +
 216 +	while ((line = get_next_line(&pos, file, size))) {
 217 +		char *marker, *modname, *fmt;
 218 +		struct module *mod;
 219 +
 220 +		marker = line;
 221 +		modname = strchr(marker, '\t');
 222 +		if (!modname)
 223 +			goto fail;
 224 +		*modname++ = '\0';
 225 +		fmt = strchr(modname, '\t');
 226 +		if (!fmt)
 227 +			goto fail;
 228 +		*fmt++ = '\0';
 229 +		if (*marker == '\0' || *modname == '\0')
 230 +			goto fail;
 231 +
 232 +		mod = find_module(modname);
 233 +		if (!mod) {
 234 +			if (is_vmlinux(modname))
 235 +				have_vmlinux = 1;
 236 +			mod = new_module(NOFAIL(strdup(modname)));
 237 +			mod->skip = 1;
 238 +		}
 239 +
 240 +		add_marker(mod, marker, fmt);
 241 +	}
 242 +	return;
 243 +fail:
 244 +	fatal("parse error in markers list file\n");
 245 +}
 246 +
 247 +static int compare_strings(const void *a, const void *b)
 248 +{
 249 +	return strcmp(*(const char **) a, *(const char **) b);
 250 +}
 251 +
 252 +static void write_markers(const char *fname)
 253 +{
 254 +	struct buffer buf = { };
 255 +	struct module *mod;
 256 +	size_t i;
 257 +
 258 +	for (mod = modules; mod; mod = mod->next)
 259 +		if ((!external_module || !mod->skip) && mod->markers != NULL) {
 260 +			/*
 261 +			 * Sort the strings so we can skip duplicates when
 262 +			 * we write them out.
 263 +			 */
 264 +			qsort(mod->markers, mod->nmarkers,
 265 +			      sizeof mod->markers[0], &compare_strings);
 266 +			for (i = 0; i < mod->nmarkers; ++i) {
 267 +				char *line = mod->markers[i];
 268 +				buf_write(&buf, line, strlen(line));
 269 +				while (i + 1 < mod->nmarkers &&
 270 +				       !strcmp(mod->markers[i],
 271 +					       mod->markers[i + 1]))
 272 +					free(mod->markers[i++]);
 273 +				free(mod->markers[i]);
 274 +			}
 275 +			free(mod->markers);
 276 +			mod->markers = NULL;
 277 +		}
 278 +
 279 +	write_if_changed(&buf, fname);
 280 +}
 281 +
 282  int main(int argc, char **argv)
 283  {
 284  	struct module *mod;
 285 @@ -1656,10 +1804,12 @@ int main(int argc, char **argv)
 286  	char fname[SZ];
 287  	char *kernel_read = NULL, *module_read = NULL;
 288  	char *dump_write = NULL;
 289 +	char *markers_read = NULL;
 290 +	char *markers_write = NULL;
 291  	int opt;
 292  	int err;
 293  
 294 -	while ((opt = getopt(argc, argv, "i:I:mso:aw")) != -1) {
 295 +	while ((opt = getopt(argc, argv, "i:I:mso:awM:K:")) != -1) {
 296  		switch(opt) {
 297  			case 'i':
 298  				kernel_read = optarg;
 299 @@ -1683,6 +1833,12 @@ int main(int argc, char **argv)
 300  			case 'w':
 301  				warn_unresolved = 1;
 302  				break;
 303 +			case 'M':
 304 +				markers_write = optarg;
 305 +				break;
 306 +			case 'K':
 307 +				markers_read = optarg;
 308 +				break;
 309  			default:
 310  				exit(1);
 311  		}
 312 @@ -1724,5 +1880,11 @@ int main(int argc, char **argv)
 313  	if (dump_write)
 314  		write_dump(dump_write);
 315  
 316 +	if (markers_read)
 317 +		read_markers(markers_read);
 318 +
 319 +	if (markers_write)
 320 +		write_markers(markers_write);
 321 +
 322  	return err;
 323  }
 324 diff -puN scripts/mod/modpost.h~linux-kernel-markers-create-modpost-file scripts/mod/modpost.h
 325 --- a/scripts/mod/modpost.h~linux-kernel-markers-create-modpost-file
 326 +++ a/scripts/mod/modpost.h
 327 @@ -110,6 +110,8 @@ struct module {
 328  	int has_init;
 329  	int has_cleanup;
 330  	struct buffer dev_table_buf;
 331 +	char **markers;
 332 +	size_t nmarkers;
 333  	char	     srcversion[25];
 334  };
 335  
 336 @@ -124,6 +126,7 @@ struct elf_info {
 337  	Elf_Section  export_gpl_sec;
 338  	Elf_Section  export_unused_gpl_sec;
 339  	Elf_Section  export_gpl_future_sec;
 340 +	Elf_Section  markers_strings_sec;
 341  	const char   *strtab;
 342  	char	     *modinfo;
 343  	unsigned int modinfo_len;
 344 _

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.