aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/recordmcount.h
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-04-08 03:58:48 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-05-16 14:43:32 -0400
commitffd618fa39284f8cc343894b566dd42ec6e74e77 (patch)
tree6086848f18cb971de2e1cd760f6d8771aaff2c45 /scripts/recordmcount.h
parent8abd5724a7f1631ab2276954156c629d4d17149a (diff)
ftrace/recordmcount: Make ignored mcount calls into nops at compile time
There are sections that are ignored by ftrace for the function tracing because the text is in a section that can be removed without notice. The mcount calls in these sections are ignored and ftrace never sees them. The downside of this is that the functions in these sections still call mcount. Although the mcount function is defined in assembly simply as a return, this added overhead is unnecessary. The solution is to convert these callers into nops at compile time. A better solution is to add 'notrace' to the section markers, but as new sections come up all the time, it would be nice that they are delt with when they are created. Later patches will deal with finding these sections and doing the proper solution. Thanks to H. Peter Anvin for giving me the right nops to use for x86. Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: John Reiser <jreiser@bitwagon.com> Link: http://lkml.kernel.org/r/20110421023738.237101176@goodmis.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'scripts/recordmcount.h')
-rw-r--r--scripts/recordmcount.h82
1 files changed, 78 insertions, 4 deletions
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 7f8d5c4c780f..657dbedd1c7f 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -23,6 +23,7 @@
23#undef fn_is_fake_mcount 23#undef fn_is_fake_mcount
24#undef MIPS_is_fake_mcount 24#undef MIPS_is_fake_mcount
25#undef sift_rel_mcount 25#undef sift_rel_mcount
26#undef nop_mcount
26#undef find_secsym_ndx 27#undef find_secsym_ndx
27#undef __has_rel_mcount 28#undef __has_rel_mcount
28#undef has_rel_mcount 29#undef has_rel_mcount
@@ -49,6 +50,7 @@
49#ifdef RECORD_MCOUNT_64 50#ifdef RECORD_MCOUNT_64
50# define append_func append64 51# define append_func append64
51# define sift_rel_mcount sift64_rel_mcount 52# define sift_rel_mcount sift64_rel_mcount
53# define nop_mcount nop_mcount_64
52# define find_secsym_ndx find64_secsym_ndx 54# define find_secsym_ndx find64_secsym_ndx
53# define __has_rel_mcount __has64_rel_mcount 55# define __has_rel_mcount __has64_rel_mcount
54# define has_rel_mcount has64_rel_mcount 56# define has_rel_mcount has64_rel_mcount
@@ -77,6 +79,7 @@
77#else 79#else
78# define append_func append32 80# define append_func append32
79# define sift_rel_mcount sift32_rel_mcount 81# define sift_rel_mcount sift32_rel_mcount
82# define nop_mcount nop_mcount_32
80# define find_secsym_ndx find32_secsym_ndx 83# define find_secsym_ndx find32_secsym_ndx
81# define __has_rel_mcount __has32_rel_mcount 84# define __has_rel_mcount __has32_rel_mcount
82# define has_rel_mcount has32_rel_mcount 85# define has_rel_mcount has32_rel_mcount
@@ -304,6 +307,70 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
304 return mlocp; 307 return mlocp;
305} 308}
306 309
310/*
311 * Read the relocation table again, but this time its called on sections
312 * that are not going to be traced. The mcount calls here will be converted
313 * into nops.
314 */
315static void nop_mcount(Elf_Shdr const *const relhdr,
316 Elf_Ehdr const *const ehdr)
317{
318 Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
319 + (void *)ehdr);
320 unsigned const symsec_sh_link = w(relhdr->sh_link);
321 Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
322 Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
323 + (void *)ehdr);
324
325 Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
326 char const *const str0 = (char const *)(_w(strsec->sh_offset)
327 + (void *)ehdr);
328
329 Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
330 + (void *)ehdr);
331 unsigned rel_entsize = _w(relhdr->sh_entsize);
332 unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
333 Elf_Rel const *relp = rel0;
334
335 Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)];
336
337 unsigned mcountsym = 0;
338 unsigned t;
339
340 for (t = nrel; t; --t) {
341 int ret = -1;
342
343 if (!mcountsym) {
344 Elf_Sym const *const symp =
345 &sym0[Elf_r_sym(relp)];
346 char const *symname = &str0[w(symp->st_name)];
347 char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
348
349 if (symname[0] == '.')
350 ++symname; /* ppc64 hack */
351 if (strcmp(mcount, symname) == 0 ||
352 (altmcount && strcmp(altmcount, symname) == 0))
353 mcountsym = Elf_r_sym(relp);
354 }
355
356 if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp))
357 ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
358
359 /*
360 * If we successfully removed the mcount, mark the relocation
361 * as a nop (don't do anything with it).
362 */
363 if (!ret) {
364 Elf_Rel rel;
365 rel = *(Elf_Rel *)relp;
366 Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
367 ulseek(fd_map, (void *)relp - (void *)ehdr, SEEK_SET);
368 uwrite(fd_map, &rel, sizeof(rel));
369 }
370 relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
371 }
372}
373
307 374
308/* 375/*
309 * Find a symbol in the given section, to be used as the base for relocating 376 * Find a symbol in the given section, to be used as the base for relocating
@@ -360,8 +427,7 @@ __has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
360 succeed_file(); 427 succeed_file();
361 } 428 }
362 if (w(txthdr->sh_type) != SHT_PROGBITS || 429 if (w(txthdr->sh_type) != SHT_PROGBITS ||
363 !(w(txthdr->sh_flags) & SHF_EXECINSTR) || 430 !(w(txthdr->sh_flags) & SHF_EXECINSTR))
364 !is_mcounted_section_name(txtname))
365 return NULL; 431 return NULL;
366 return txtname; 432 return txtname;
367} 433}
@@ -384,9 +450,11 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
384{ 450{
385 unsigned totrelsz = 0; 451 unsigned totrelsz = 0;
386 Elf_Shdr const *shdrp = shdr0; 452 Elf_Shdr const *shdrp = shdr0;
453 char const *txtname;
387 454
388 for (; nhdr; --nhdr, ++shdrp) { 455 for (; nhdr; --nhdr, ++shdrp) {
389 if (has_rel_mcount(shdrp, shdr0, shstrtab, fname)) 456 txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
457 if (txtname && is_mcounted_section_name(txtname))
390 totrelsz += _w(shdrp->sh_size); 458 totrelsz += _w(shdrp->sh_size);
391 } 459 }
392 return totrelsz; 460 return totrelsz;
@@ -422,7 +490,7 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
422 for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 490 for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
423 char const *const txtname = has_rel_mcount(relhdr, shdr0, 491 char const *const txtname = has_rel_mcount(relhdr, shdr0,
424 shstrtab, fname); 492 shstrtab, fname);
425 if (txtname) { 493 if (txtname && is_mcounted_section_name(txtname)) {
426 uint_t recval = 0; 494 uint_t recval = 0;
427 unsigned const recsym = find_secsym_ndx( 495 unsigned const recsym = find_secsym_ndx(
428 w(relhdr->sh_info), txtname, &recval, 496 w(relhdr->sh_info), txtname, &recval,
@@ -433,6 +501,12 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
433 mlocp = sift_rel_mcount(mlocp, 501 mlocp = sift_rel_mcount(mlocp,
434 (void *)mlocp - (void *)mloc0, &mrelp, 502 (void *)mlocp - (void *)mloc0, &mrelp,
435 relhdr, ehdr, recsym, recval, reltype); 503 relhdr, ehdr, recsym, recval, reltype);
504 } else if (make_nop && txtname) {
505 /*
506 * This section is ignored by ftrace, but still
507 * has mcount calls. Convert them to nops now.
508 */
509 nop_mcount(relhdr, ehdr);
436 } 510 }
437 } 511 }
438 if (mloc0 != mlocp) { 512 if (mloc0 != mlocp) {