~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to scripts/recordmcount.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include <sys/types.h>
25
25
#include <sys/mman.h>
26
26
#include <sys/stat.h>
 
27
#include <getopt.h>
27
28
#include <elf.h>
28
29
#include <fcntl.h>
29
30
#include <setjmp.h>
39
40
static struct stat sb;  /* Remember .st_size, etc. */
40
41
static jmp_buf jmpenv;  /* setjmp/longjmp per-file error escape */
41
42
static const char *altmcount;   /* alternate mcount symbol name */
 
43
static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
42
44
 
43
45
/* setjmp() return values */
44
46
enum {
78
80
ulseek(int const fd, off_t const offset, int const whence)
79
81
{
80
82
        off_t const w = lseek(fd, offset, whence);
81
 
        if ((off_t)-1 == w) {
 
83
        if (w == (off_t)-1) {
82
84
                perror("lseek");
83
85
                fail_file();
84
86
        }
111
113
umalloc(size_t size)
112
114
{
113
115
        void *const addr = malloc(size);
114
 
        if (0 == addr) {
 
116
        if (addr == 0) {
115
117
                fprintf(stderr, "malloc failed: %zu bytes\n", size);
116
118
                fail_file();
117
119
        }
118
120
        return addr;
119
121
}
120
122
 
 
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;
 
126
 
 
127
static char rel_type_nop;
 
128
 
 
129
static int (*make_nop)(void *map, size_t const offset);
 
130
 
 
131
static int make_nop_x86(void *map, size_t const offset)
 
132
{
 
133
        uint32_t *ptr;
 
134
        unsigned char *op;
 
135
 
 
136
        /* Confirm we have 0xe8 0x0 0x0 0x0 0x0 */
 
137
        ptr = map + offset;
 
138
        if (*ptr != 0)
 
139
                return -1;
 
140
 
 
141
        op = map + offset - 1;
 
142
        if (*op != 0xe8)
 
143
                return -1;
 
144
 
 
145
        /* convert to nop */
 
146
        ulseek(fd_map, offset - 1, SEEK_SET);
 
147
        uwrite(fd_map, ideal_nop, 5);
 
148
        return 0;
 
149
}
 
150
 
121
151
/*
122
152
 * Get the whole file as a programming convenience in order to avoid
123
153
 * malloc+lseek+read+free of many pieces.  If successful, then mmap
136
166
        void *addr;
137
167
 
138
168
        fd_map = open(fname, O_RDWR);
139
 
        if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
 
169
        if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
140
170
                perror(fname);
141
171
                fail_file();
142
172
        }
147
177
        addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
148
178
                    fd_map, 0);
149
179
        mmap_failed = 0;
150
 
        if (MAP_FAILED == addr) {
 
180
        if (addr == MAP_FAILED) {
151
181
                mmap_failed = 1;
152
182
                addr = umalloc(sb.st_size);
153
183
                uread(fd_map, addr, sb.st_size);
206
236
static int
207
237
is_mcounted_section_name(char const *const txtname)
208
238
{
209
 
        return 0 == strcmp(".text",           txtname) ||
210
 
                0 == strcmp(".ref.text",      txtname) ||
211
 
                0 == strcmp(".sched.text",    txtname) ||
212
 
                0 == strcmp(".spinlock.text", txtname) ||
213
 
                0 == strcmp(".irqentry.text", txtname) ||
214
 
                0 == strcmp(".text.unlikely", 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;
215
246
}
216
247
 
217
248
/* 32 bit and 64 bit are very similar */
264
295
        w8 = w8nat;
265
296
        switch (ehdr->e_ident[EI_DATA]) {
266
297
                static unsigned int const endian = 1;
267
 
        default: {
 
298
        default:
268
299
                fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
269
300
                        ehdr->e_ident[EI_DATA], fname);
270
301
                fail_file();
271
 
        } break;
272
 
        case ELFDATA2LSB: {
273
 
                if (1 != *(unsigned char const *)&endian) {
 
302
                break;
 
303
        case ELFDATA2LSB:
 
304
                if (*(unsigned char const *)&endian != 1) {
274
305
                        /* main() is big endian, file.o is little endian. */
275
306
                        w = w4rev;
276
307
                        w2 = w2rev;
277
308
                        w8 = w8rev;
278
309
                }
279
 
        } break;
280
 
        case ELFDATA2MSB: {
281
 
                if (0 != *(unsigned char const *)&endian) {
 
310
                break;
 
311
        case ELFDATA2MSB:
 
312
                if (*(unsigned char const *)&endian != 0) {
282
313
                        /* main() is little endian, file.o is big endian. */
283
314
                        w = w4rev;
284
315
                        w2 = w2rev;
285
316
                        w8 = w8rev;
286
317
                }
287
 
        } break;
 
318
                break;
288
319
        }  /* end switch */
289
 
        if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
290
 
        ||  ET_REL != w2(ehdr->e_type)
291
 
        ||  EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
 
320
        if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
 
321
        ||  w2(ehdr->e_type) != ET_REL
 
322
        ||  ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
292
323
                fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
293
324
                fail_file();
294
325
        }
295
326
 
296
327
        gpfx = 0;
297
328
        switch (w2(ehdr->e_machine)) {
298
 
        default: {
 
329
        default:
299
330
                fprintf(stderr, "unrecognized e_machine %d %s\n",
300
331
                        w2(ehdr->e_machine), fname);
301
332
                fail_file();
302
 
        } break;
303
 
        case EM_386:     reltype = R_386_32;                   break;
 
333
                break;
 
334
        case EM_386:
 
335
                reltype = R_386_32;
 
336
                make_nop = make_nop_x86;
 
337
                ideal_nop = ideal_nop5_x86_32;
 
338
                mcount_adjust_32 = -1;
 
339
                break;
304
340
        case EM_ARM:     reltype = R_ARM_ABS32;
305
341
                         altmcount = "__gnu_mcount_nc";
306
342
                         break;
311
347
        case EM_S390:    /* reltype: e_class    */ gpfx = '_'; break;
312
348
        case EM_SH:      reltype = R_SH_DIR32;                 break;
313
349
        case EM_SPARCV9: reltype = R_SPARC_64;     gpfx = '_'; break;
314
 
        case EM_X86_64:  reltype = R_X86_64_64;                break;
 
350
        case EM_X86_64:
 
351
                make_nop = make_nop_x86;
 
352
                ideal_nop = ideal_nop5_x86_64;
 
353
                reltype = R_X86_64_64;
 
354
                mcount_adjust_64 = -1;
 
355
                break;
315
356
        }  /* end switch */
316
357
 
317
358
        switch (ehdr->e_ident[EI_CLASS]) {
318
 
        default: {
 
359
        default:
319
360
                fprintf(stderr, "unrecognized ELF class %d %s\n",
320
361
                        ehdr->e_ident[EI_CLASS], fname);
321
362
                fail_file();
322
 
        } break;
323
 
        case ELFCLASS32: {
324
 
                if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
325
 
                ||  sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
 
363
                break;
 
364
        case ELFCLASS32:
 
365
                if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
 
366
                ||  w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
326
367
                        fprintf(stderr,
327
368
                                "unrecognized ET_REL file: %s\n", fname);
328
369
                        fail_file();
329
370
                }
330
 
                if (EM_S390 == w2(ehdr->e_machine))
 
371
                if (w2(ehdr->e_machine) == EM_S390) {
331
372
                        reltype = R_390_32;
332
 
                if (EM_MIPS == w2(ehdr->e_machine)) {
 
373
                        mcount_adjust_32 = -4;
 
374
                }
 
375
                if (w2(ehdr->e_machine) == EM_MIPS) {
333
376
                        reltype = R_MIPS_32;
334
377
                        is_fake_mcount32 = MIPS32_is_fake_mcount;
335
378
                }
336
379
                do32(ehdr, fname, reltype);
337
 
        } break;
 
380
                break;
338
381
        case ELFCLASS64: {
339
382
                Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
340
 
                if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
341
 
                ||  sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
 
383
                if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
 
384
                ||  w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
342
385
                        fprintf(stderr,
343
386
                                "unrecognized ET_REL file: %s\n", fname);
344
387
                        fail_file();
345
388
                }
346
 
                if (EM_S390 == w2(ghdr->e_machine))
 
389
                if (w2(ghdr->e_machine) == EM_S390) {
347
390
                        reltype = R_390_64;
348
 
                if (EM_MIPS == w2(ghdr->e_machine)) {
 
391
                        mcount_adjust_64 = -8;
 
392
                }
 
393
                if (w2(ghdr->e_machine) == EM_MIPS) {
349
394
                        reltype = R_MIPS_64;
350
395
                        Elf64_r_sym = MIPS64_r_sym;
351
396
                        Elf64_r_info = MIPS64_r_info;
352
397
                        is_fake_mcount64 = MIPS64_is_fake_mcount;
353
398
                }
354
399
                do64(ghdr, fname, reltype);
355
 
        } break;
 
400
                break;
 
401
        }
356
402
        }  /* end switch */
357
403
 
358
404
        cleanup();
359
405
}
360
406
 
361
407
int
362
 
main(int argc, char const *argv[])
 
408
main(int argc, char *argv[])
363
409
{
364
410
        const char ftrace[] = "/ftrace.o";
365
411
        int ftrace_size = sizeof(ftrace) - 1;
366
412
        int n_error = 0;  /* gcc-4.3.0 false positive complaint */
367
 
 
368
 
        if (argc <= 1) {
369
 
                fprintf(stderr, "usage: recordmcount file.o...\n");
 
413
        int c;
 
414
        int i;
 
415
 
 
416
        while ((c = getopt(argc, argv, "w")) >= 0) {
 
417
                switch (c) {
 
418
                case 'w':
 
419
                        warn_on_notrace_sect = 1;
 
420
                        break;
 
421
                default:
 
422
                        fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
 
423
                        return 0;
 
424
                }
 
425
        }
 
426
 
 
427
        if ((argc - optind) < 1) {
 
428
                fprintf(stderr, "usage: recordmcount [-w] file.o...\n");
370
429
                return 0;
371
430
        }
372
431
 
373
432
        /* Process each file in turn, allowing deep failure. */
374
 
        for (--argc, ++argv; 0 < argc; --argc, ++argv) {
 
433
        for (i = optind; i < argc; i++) {
 
434
                char *file = argv[i];
375
435
                int const sjval = setjmp(jmpenv);
376
436
                int len;
377
437
 
380
440
                 * function but does not call it. Since ftrace.o should
381
441
                 * not be traced anyway, we just skip it.
382
442
                 */
383
 
                len = strlen(argv[0]);
 
443
                len = strlen(file);
384
444
                if (len >= ftrace_size &&
385
 
                    strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
 
445
                    strcmp(file + (len - ftrace_size), ftrace) == 0)
386
446
                        continue;
387
447
 
388
448
                switch (sjval) {
389
 
                default: {
390
 
                        fprintf(stderr, "internal error: %s\n", argv[0]);
 
449
                default:
 
450
                        fprintf(stderr, "internal error: %s\n", file);
391
451
                        exit(1);
392
 
                } break;
393
 
                case SJ_SETJMP: {  /* normal sequence */
 
452
                        break;
 
453
                case SJ_SETJMP:    /* normal sequence */
394
454
                        /* Avoid problems if early cleanup() */
395
455
                        fd_map = -1;
396
456
                        ehdr_curr = NULL;
397
457
                        mmap_failed = 1;
398
 
                        do_file(argv[0]);
399
 
                } break;
400
 
                case SJ_FAIL: {  /* error in do_file or below */
 
458
                        do_file(file);
 
459
                        break;
 
460
                case SJ_FAIL:    /* error in do_file or below */
401
461
                        ++n_error;
402
 
                } break;
403
 
                case SJ_SUCCEED: {  /* premature success */
 
462
                        break;
 
463
                case SJ_SUCCEED:    /* premature success */
404
464
                        /* do nothing */
405
 
                } break;
 
465
                        break;
406
466
                }  /* end switch */
407
467
        }
408
468
        return !!n_error;