aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-04-12 18:53:25 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-05-16 14:44:20 -0400
commitdfad3d598c4bbbaf137588e22bac1ce624529f7e (patch)
tree7df293e467f93913d1979a0e7131bb6e1977acd7 /scripts
parentffd618fa39284f8cc343894b566dd42ec6e74e77 (diff)
ftrace/recordmcount: Add warning logic to warn on mcount not recorded
There's some sections that should not have mcount recorded and should not have modifications to the that code. But currently they waste some time by calling mcount anyway (which simply returns). As the real answer should be to either whitelist the section or have gcc ignore it fully. This change adds a option to recordmcount to warn when it finds a section that is ignored by ftrace but still contains mcount callers. This is not on by default as developers may not know if the section should be completely ignored or added to the whitelist. Cc: John Reiser <jreiser@bitwagon.com> Link: http://lkml.kernel.org/r/20110421023738.476989377@goodmis.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/recordmcount.c32
-rw-r--r--scripts/recordmcount.h22
2 files changed, 41 insertions, 13 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 78054a41d134..0e18975824f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -24,6 +24,7 @@
24#include <sys/types.h> 24#include <sys/types.h>
25#include <sys/mman.h> 25#include <sys/mman.h>
26#include <sys/stat.h> 26#include <sys/stat.h>
27#include <getopt.h>
27#include <elf.h> 28#include <elf.h>
28#include <fcntl.h> 29#include <fcntl.h>
29#include <setjmp.h> 30#include <setjmp.h>
@@ -39,6 +40,7 @@ static char gpfx; /* prefix for global symbol name (sometimes '_') */
39static struct stat sb; /* Remember .st_size, etc. */ 40static struct stat sb; /* Remember .st_size, etc. */
40static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ 41static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
41static const char *altmcount; /* alternate mcount symbol name */ 42static const char *altmcount; /* alternate mcount symbol name */
43static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
42 44
43/* setjmp() return values */ 45/* setjmp() return values */
44enum { 46enum {
@@ -397,19 +399,33 @@ do_file(char const *const fname)
397} 399}
398 400
399int 401int
400main(int argc, char const *argv[]) 402main(int argc, char *argv[])
401{ 403{
402 const char ftrace[] = "/ftrace.o"; 404 const char ftrace[] = "/ftrace.o";
403 int ftrace_size = sizeof(ftrace) - 1; 405 int ftrace_size = sizeof(ftrace) - 1;
404 int n_error = 0; /* gcc-4.3.0 false positive complaint */ 406 int n_error = 0; /* gcc-4.3.0 false positive complaint */
407 int c;
408 int i;
405 409
406 if (argc <= 1) { 410 while ((c = getopt(argc, argv, "w")) >= 0) {
407 fprintf(stderr, "usage: recordmcount file.o...\n"); 411 switch (c) {
412 case 'w':
413 warn_on_notrace_sect = 1;
414 break;
415 default:
416 fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
417 return 0;
418 }
419 }
420
421 if ((argc - optind) < 1) {
422 fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
408 return 0; 423 return 0;
409 } 424 }
410 425
411 /* Process each file in turn, allowing deep failure. */ 426 /* Process each file in turn, allowing deep failure. */
412 for (--argc, ++argv; argc > 0; --argc, ++argv) { 427 for (i = optind; i < argc; i++) {
428 char *file = argv[i];
413 int const sjval = setjmp(jmpenv); 429 int const sjval = setjmp(jmpenv);
414 int len; 430 int len;
415 431
@@ -418,14 +434,14 @@ main(int argc, char const *argv[])
418 * function but does not call it. Since ftrace.o should 434 * function but does not call it. Since ftrace.o should
419 * not be traced anyway, we just skip it. 435 * not be traced anyway, we just skip it.
420 */ 436 */
421 len = strlen(argv[0]); 437 len = strlen(file);
422 if (len >= ftrace_size && 438 if (len >= ftrace_size &&
423 strcmp(argv[0] + (len - ftrace_size), ftrace) == 0) 439 strcmp(file + (len - ftrace_size), ftrace) == 0)
424 continue; 440 continue;
425 441
426 switch (sjval) { 442 switch (sjval) {
427 default: 443 default:
428 fprintf(stderr, "internal error: %s\n", argv[0]); 444 fprintf(stderr, "internal error: %s\n", file);
429 exit(1); 445 exit(1);
430 break; 446 break;
431 case SJ_SETJMP: /* normal sequence */ 447 case SJ_SETJMP: /* normal sequence */
@@ -433,7 +449,7 @@ main(int argc, char const *argv[])
433 fd_map = -1; 449 fd_map = -1;
434 ehdr_curr = NULL; 450 ehdr_curr = NULL;
435 mmap_failed = 1; 451 mmap_failed = 1;
436 do_file(argv[0]); 452 do_file(file);
437 break; 453 break;
438 case SJ_FAIL: /* error in do_file or below */ 454 case SJ_FAIL: /* error in do_file or below */
439 ++n_error; 455 ++n_error;
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 657dbedd1c7f..22033d563bcd 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -313,7 +313,8 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
313 * into nops. 313 * into nops.
314 */ 314 */
315static void nop_mcount(Elf_Shdr const *const relhdr, 315static void nop_mcount(Elf_Shdr const *const relhdr,
316 Elf_Ehdr const *const ehdr) 316 Elf_Ehdr const *const ehdr,
317 const char *const txtname)
317{ 318{
318 Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 319 Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
319 + (void *)ehdr); 320 + (void *)ehdr);
@@ -336,6 +337,7 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
336 337
337 unsigned mcountsym = 0; 338 unsigned mcountsym = 0;
338 unsigned t; 339 unsigned t;
340 int once = 0;
339 341
340 for (t = nrel; t; --t) { 342 for (t = nrel; t; --t) {
341 int ret = -1; 343 int ret = -1;
@@ -353,8 +355,18 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
353 mcountsym = Elf_r_sym(relp); 355 mcountsym = Elf_r_sym(relp);
354 } 356 }
355 357
356 if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) 358 if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
357 ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset); 359 if (make_nop)
360 ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
361 if (warn_on_notrace_sect && !once) {
362 printf("Section %s has mcount callers being ignored\n",
363 txtname);
364 once = 1;
365 /* just warn? */
366 if (!make_nop)
367 return;
368 }
369 }
358 370
359 /* 371 /*
360 * If we successfully removed the mcount, mark the relocation 372 * If we successfully removed the mcount, mark the relocation
@@ -501,12 +513,12 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
501 mlocp = sift_rel_mcount(mlocp, 513 mlocp = sift_rel_mcount(mlocp,
502 (void *)mlocp - (void *)mloc0, &mrelp, 514 (void *)mlocp - (void *)mloc0, &mrelp,
503 relhdr, ehdr, recsym, recval, reltype); 515 relhdr, ehdr, recsym, recval, reltype);
504 } else if (make_nop && txtname) { 516 } else if (txtname && (warn_on_notrace_sect || make_nop)) {
505 /* 517 /*
506 * This section is ignored by ftrace, but still 518 * This section is ignored by ftrace, but still
507 * has mcount calls. Convert them to nops now. 519 * has mcount calls. Convert them to nops now.
508 */ 520 */
509 nop_mcount(relhdr, ehdr); 521 nop_mcount(relhdr, ehdr, txtname);
510 } 522 }
511 } 523 }
512 if (mloc0 != mlocp) { 524 if (mloc0 != mlocp) {