Commit b43f70933e7753a284733d5ae355f6778bd118ce

Authored by Steven Rostedt
Committed by Ingo Molnar
1 parent 4092762aeb

ftrace: test for running of recordmcount.pl twice on an object

Impact: fix failure of dynamic function tracer selftest

In a course of development, a developer does several makes on their
kernel. Sometimes, the make might do something abnormal. In the
case of running the recordmcount.pl script on an object twice,
the script will duplicate all the calls to mcount in the __mcount_loc
section.

On boot up, the dynamic function tracer is careful when it modifies
code, and performs several consistency checks. One is to not modify
the call site if it is not what it expects it to be. If a function
call site is listed twice, the first entry will convert the site
to a nop, and the second will fail because it expected to see a
call to mcount, but instead it sees a nop. Thus, the function tracer
is disabled.

Eric Sesterhenn reported seeing:

[    1.055440] ftrace: converting mcount calls to 0f 1f 44 00 00
[    1.055568] ftrace: allocating 29418 entries in 116 pages
[    1.061000] ------------[ cut here ]------------
[    1.061000] WARNING: at kernel/trace/ftrace.c:441

 [...]

[    1.060000] ---[ end trace 4eaa2a86a8e2da23 ]---
[    1.060000] ftrace failed to modify [<c0118072>] check_corruption+0x3/0x2d
[    1.060000]  actual: 0f:1f:44:00:00

This warning shows that check_corruption+0x3 already had a nop in
its place (0x0f1f440000). After compiling another kernel the problem
went away.

Later Eric Paris notice the same type of issue. Luckily, he saved
the vmlinux file that caused it. In the file we found a bunch of
duplicate mcount call site records, which lead us to the script.

Perhaps this problem only happens to people named Eric.

This patch changes the script to test if the __mcount_loc already
exists in the object file, and if it does, it will print out
an error message and kill the compile.

Reported-by: Eric Sesterhenn <snakebyte@gmx.de>
Reported-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 1 changed file with 18 additions and 3 deletions Side-by-side Diff

scripts/recordmcount.pl
... ... @@ -101,7 +101,7 @@
101 101 my $V = '0.1';
102 102  
103 103 if ($#ARGV < 7) {
104   - print "usage: $P arch objdump objcopy cc ld nm rm mv is_module inputfile\n";
  104 + print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
105 105 print "version: $V\n";
106 106 exit(1);
107 107 }
... ... @@ -275,7 +275,6 @@
275 275 "\tDisabling local function references.\n";
276 276 }
277 277  
278   -
279 278 #
280 279 # Step 1: find all the local (static functions) and weak symbols.
281 280 # 't' is local, 'w/W' is weak (we never use a weak function)
282 281  
283 282  
... ... @@ -343,13 +342,16 @@
343 342 #
344 343 # Step 2: find the sections and mcount call sites
345 344 #
346   -open(IN, "$objdump -dr $inputfile|") || die "error running $objdump";
  345 +open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump";
347 346  
348 347 my $text;
349 348  
  349 +my $read_headers = 1;
  350 +
350 351 while (<IN>) {
351 352 # is it a section?
352 353 if (/$section_regex/) {
  354 + $read_headers = 0;
353 355  
354 356 # Only record text sections that we know are safe
355 357 if (defined($text_sections{$1})) {
... ... @@ -383,6 +385,19 @@
383 385 $ref_func = $text;
384 386 }
385 387 }
  388 + } elsif ($read_headers && /$mcount_section/) {
  389 + #
  390 + # Somehow the make process can execute this script on an
  391 + # object twice. If it does, we would duplicate the mcount
  392 + # section and it will cause the function tracer self test
  393 + # to fail. Check if the mcount section exists, and if it does,
  394 + # warn and exit.
  395 + #
  396 + print STDERR "ERROR: $mcount_section already in $inputfile\n" .
  397 + "\tThis may be an indication that your build is corrupted.\n" .
  398 + "\tDelete $inputfile and try again. If the same object file\n" .
  399 + "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
  400 + exit(-1);
386 401 }
387 402  
388 403 # is this a call site to mcount? If so, record it to print later