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.- [get | view] (2008-01-11 17:20:45, 10.6 KB) [[attachment:linux-kernel-markers-create-modpost-file.patch]]
- [get | view] (2008-01-11 17:20:31, 1.4 KB) [[attachment:linux-kernel-markers-support-multiple-probes-update.patch]]
- [get | view] (2008-01-11 17:20:09, 37.6 KB) [[attachment:linux-kernel-markers-support-multiple-probes.patch]]
You are not allowed to attach a file to this page.
