#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <getopt.h>
#include <elf.h>
#include <fcntl.h>
#include <setjmp.h>
static struct stat sb; /* Remember .st_size, etc. */
static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
static const char *altmcount; /* alternate mcount symbol name */
+static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
/* setjmp() return values */
enum {
}
int
-main(int argc, char const *argv[])
+main(int argc, char *argv[])
{
const char ftrace[] = "/ftrace.o";
int ftrace_size = sizeof(ftrace) - 1;
int n_error = 0; /* gcc-4.3.0 false positive complaint */
+ int c;
+ int i;
- if (argc <= 1) {
- fprintf(stderr, "usage: recordmcount file.o...\n");
+ while ((c = getopt(argc, argv, "w")) >= 0) {
+ switch (c) {
+ case 'w':
+ warn_on_notrace_sect = 1;
+ break;
+ default:
+ fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
+ return 0;
+ }
+ }
+
+ if ((argc - optind) < 1) {
+ fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
return 0;
}
/* Process each file in turn, allowing deep failure. */
- for (--argc, ++argv; argc > 0; --argc, ++argv) {
+ for (i = optind; i < argc; i++) {
+ char *file = argv[i];
int const sjval = setjmp(jmpenv);
int len;
* function but does not call it. Since ftrace.o should
* not be traced anyway, we just skip it.
*/
- len = strlen(argv[0]);
+ len = strlen(file);
if (len >= ftrace_size &&
- strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
+ strcmp(file + (len - ftrace_size), ftrace) == 0)
continue;
switch (sjval) {
default:
- fprintf(stderr, "internal error: %s\n", argv[0]);
+ fprintf(stderr, "internal error: %s\n", file);
exit(1);
break;
case SJ_SETJMP: /* normal sequence */
fd_map = -1;
ehdr_curr = NULL;
mmap_failed = 1;
- do_file(argv[0]);
+ do_file(file);
break;
case SJ_FAIL: /* error in do_file or below */
++n_error;
* into nops.
*/
static void nop_mcount(Elf_Shdr const *const relhdr,
- Elf_Ehdr const *const ehdr)
+ Elf_Ehdr const *const ehdr,
+ const char *const txtname)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
unsigned mcountsym = 0;
unsigned t;
+ int once = 0;
for (t = nrel; t; --t) {
int ret = -1;
mcountsym = Elf_r_sym(relp);
}
- if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp))
- ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
+ if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
+ if (make_nop)
+ ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
+ if (warn_on_notrace_sect && !once) {
+ printf("Section %s has mcount callers being ignored\n",
+ txtname);
+ once = 1;
+ /* just warn? */
+ if (!make_nop)
+ return;
+ }
+ }
/*
* If we successfully removed the mcount, mark the relocation
mlocp = sift_rel_mcount(mlocp,
(void *)mlocp - (void *)mloc0, &mrelp,
relhdr, ehdr, recsym, recval, reltype);
- } else if (make_nop && txtname) {
+ } else if (txtname && (warn_on_notrace_sect || make_nop)) {
/*
* This section is ignored by ftrace, but still
* has mcount calls. Convert them to nops now.
*/
- nop_mcount(relhdr, ehdr);
+ nop_mcount(relhdr, ehdr, txtname);
}
}
if (mloc0 != mlocp) {