24 #include <sys/types.h>
37 static int mmap_failed;
38 static void *ehdr_curr;
42 static const char *altmcount;
43 static int warn_on_notrace_sect;
57 munmap(ehdr_curr,
sb.st_size);
82 off_t const w = lseek(fd, offset, whence);
91 uread(
int const fd,
void *
const buf,
size_t const count)
93 size_t const n =
read(fd, buf, count);
102 uwrite(
int const fd,
void const *
const buf,
size_t const count)
104 size_t const n =
write(fd, buf, count);
117 fprintf(stderr,
"malloc failed: %zu bytes\n", size);
123 static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
124 static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
125 static unsigned char *ideal_nop;
127 static char rel_type_nop;
131 static int make_nop_x86(
void *map,
size_t const offset)
141 op = map + offset - 1;
147 uwrite(
fd_map, ideal_nop, 5);
164 static void *mmap_file(
char const *
fname)
174 fprintf(stderr,
"not a regular file: %s\n", fname);
180 if (addr == MAP_FAILED) {
182 addr = umalloc(
sb.st_size);
192 return ((0xff & (x >> (0 * 8))) << (7 * 8))
193 | ((0xff & (x >> (1 * 8))) << (6 * 8))
194 | ((0xff & (x >> (2 * 8))) << (5 * 8))
195 | ((0xff & (x >> (3 * 8))) << (4 * 8))
196 | ((0xff & (x >> (4 * 8))) << (3 * 8))
197 | ((0xff & (x >> (5 * 8))) << (2 * 8))
198 | ((0xff & (x >> (6 * 8))) << (1 * 8))
199 | ((0xff & (x >> (7 * 8))) << (0 * 8));
204 return ((0xff & (x >> (0 * 8))) << (3 * 8))
205 | ((0xff & (x >> (1 * 8))) << (2 * 8))
206 | ((0xff & (x >> (2 * 8))) << (1 * 8))
207 | ((0xff & (x >> (3 * 8))) << (0 * 8));
212 return ((0xff & (x >> (0 * 8))) << (1 * 8))
213 | ((0xff & (x >> (1 * 8))) << (0 * 8));
237 is_mcounted_section_name(
char const *
const txtname)
239 return strcmp(
".text", txtname) == 0 ||
240 strcmp(
".ref.text", txtname) == 0 ||
241 strcmp(
".sched.text", txtname) == 0 ||
242 strcmp(
".spinlock.text", txtname) == 0 ||
243 strcmp(
".irqentry.text", txtname) == 0 ||
244 strcmp(
".kprobes.text", txtname) == 0 ||
245 strcmp(
".text.unlikely", txtname) == 0;
250 #define RECORD_MCOUNT_64
279 static void MIPS64_r_info(
Elf64_Rel *
const rp,
unsigned sym,
unsigned type)
282 .r_mips = { .r_sym =
w(sym), .r_type = type }
287 do_file(
char const *
const fname)
290 unsigned int reltype = 0;
297 static unsigned int const endian = 1;
299 fprintf(stderr,
"unrecognized ELF data encoding %d: %s\n",
304 if (*(
unsigned char const *)&endian != 1) {
312 if (*(
unsigned char const *)&endian != 0) {
323 fprintf(stderr,
"unrecognized ET_REL file %s\n", fname);
330 fprintf(stderr,
"unrecognized e_machine %d %s\n",
336 make_nop = make_nop_x86;
337 ideal_nop = ideal_nop5_x86_32;
338 mcount_adjust_32 = -1;
341 altmcount =
"__gnu_mcount_nc";
344 case EM_MIPS: gpfx =
'_';
break;
347 case EM_S390: gpfx =
'_';
break;
351 make_nop = make_nop_x86;
352 ideal_nop = ideal_nop5_x86_64;
354 mcount_adjust_64 = -1;
360 fprintf(stderr,
"unrecognized ELF class %d %s\n",
368 "unrecognized ET_REL file: %s\n", fname);
373 mcount_adjust_32 = -4;
377 is_fake_mcount32 = MIPS32_is_fake_mcount;
379 do32(ehdr, fname, reltype);
386 "unrecognized ET_REL file: %s\n", fname);
391 mcount_adjust_64 = -8;
395 Elf64_r_sym = MIPS64_r_sym;
396 Elf64_r_info = MIPS64_r_info;
397 is_fake_mcount64 = MIPS64_is_fake_mcount;
399 do64(ghdr, fname, reltype);
410 const char ftrace[] =
"/ftrace.o";
411 int ftrace_size =
sizeof(
ftrace) - 1;
416 while ((c = getopt(argc, argv,
"w")) >= 0) {
419 warn_on_notrace_sect = 1;
422 fprintf(stderr,
"usage: recordmcount [-w] file.o...\n");
427 if ((argc - optind) < 1) {
428 fprintf(stderr,
"usage: recordmcount [-w] file.o...\n");
433 for (i = optind; i <
argc; i++) {
434 char *
file = argv[
i];
435 int const sjval =
setjmp(jmpenv);
444 if (len >= ftrace_size &&
445 strcmp(file + (len - ftrace_size), ftrace) == 0)
450 fprintf(stderr,
"internal error: %s\n", file);