diff options
-rw-r--r-- | arch/i386/boot/compressed/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/boot/compressed/relocs.c | 82 |
2 files changed, 73 insertions, 11 deletions
diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile index cc28da3a881e..a661217f33ec 100644 --- a/arch/i386/boot/compressed/Makefile +++ b/arch/i386/boot/compressed/Makefile | |||
@@ -20,7 +20,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE | |||
20 | $(call if_changed,objcopy) | 20 | $(call if_changed,objcopy) |
21 | 21 | ||
22 | quiet_cmd_relocs = RELOCS $@ | 22 | quiet_cmd_relocs = RELOCS $@ |
23 | cmd_relocs = $(obj)/relocs $< > $@ | 23 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< |
24 | $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE | 24 | $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE |
25 | $(call if_changed,relocs) | 25 | $(call if_changed,relocs) |
26 | 26 | ||
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c index 0551ceb21bed..468da89153c4 100644 --- a/arch/i386/boot/compressed/relocs.c +++ b/arch/i386/boot/compressed/relocs.c | |||
@@ -19,6 +19,33 @@ static char *strtab[MAX_SHDRS]; | |||
19 | static unsigned long reloc_count, reloc_idx; | 19 | static unsigned long reloc_count, reloc_idx; |
20 | static unsigned long *relocs; | 20 | static unsigned long *relocs; |
21 | 21 | ||
22 | /* | ||
23 | * Following symbols have been audited. There values are constant and do | ||
24 | * not change if bzImage is loaded at a different physical address than | ||
25 | * the address for which it has been compiled. Don't warn user about | ||
26 | * absolute relocations present w.r.t these symbols. | ||
27 | */ | ||
28 | static const char* safe_abs_relocs[] = { | ||
29 | "__kernel_vsyscall", | ||
30 | "__kernel_rt_sigreturn", | ||
31 | "__kernel_sigreturn", | ||
32 | "SYSENTER_RETURN", | ||
33 | }; | ||
34 | |||
35 | static int is_safe_abs_reloc(const char* sym_name) | ||
36 | { | ||
37 | int i, array_size; | ||
38 | |||
39 | array_size = sizeof(safe_abs_relocs)/sizeof(char*); | ||
40 | |||
41 | for(i = 0; i < array_size; i++) { | ||
42 | if (!strcmp(sym_name, safe_abs_relocs[i])) | ||
43 | /* Match found */ | ||
44 | return 1; | ||
45 | } | ||
46 | return 0; | ||
47 | } | ||
48 | |||
22 | static void die(char *fmt, ...) | 49 | static void die(char *fmt, ...) |
23 | { | 50 | { |
24 | va_list ap; | 51 | va_list ap; |
@@ -359,9 +386,8 @@ static void print_absolute_symbols(void) | |||
359 | 386 | ||
360 | static void print_absolute_relocs(void) | 387 | static void print_absolute_relocs(void) |
361 | { | 388 | { |
362 | int i; | 389 | int i, printed = 0; |
363 | printf("Absolute relocations\n"); | 390 | |
364 | printf("Offset Info Type Sym.Value Sym.Name\n"); | ||
365 | for(i = 0; i < ehdr.e_shnum; i++) { | 391 | for(i = 0; i < ehdr.e_shnum; i++) { |
366 | char *sym_strtab; | 392 | char *sym_strtab; |
367 | Elf32_Sym *sh_symtab; | 393 | Elf32_Sym *sh_symtab; |
@@ -387,6 +413,31 @@ static void print_absolute_relocs(void) | |||
387 | if (sym->st_shndx != SHN_ABS) { | 413 | if (sym->st_shndx != SHN_ABS) { |
388 | continue; | 414 | continue; |
389 | } | 415 | } |
416 | |||
417 | /* Absolute symbols are not relocated if bzImage is | ||
418 | * loaded at a non-compiled address. Display a warning | ||
419 | * to user at compile time about the absolute | ||
420 | * relocations present. | ||
421 | * | ||
422 | * User need to audit the code to make sure | ||
423 | * some symbols which should have been section | ||
424 | * relative have not become absolute because of some | ||
425 | * linker optimization or wrong programming usage. | ||
426 | * | ||
427 | * Before warning check if this absolute symbol | ||
428 | * relocation is harmless. | ||
429 | */ | ||
430 | if (is_safe_abs_reloc(name)) | ||
431 | continue; | ||
432 | |||
433 | if (!printed) { | ||
434 | printf("WARNING: Absolute relocations" | ||
435 | " present\n"); | ||
436 | printf("Offset Info Type Sym.Value " | ||
437 | "Sym.Name\n"); | ||
438 | printed = 1; | ||
439 | } | ||
440 | |||
390 | printf("%08x %08x %10s %08x %s\n", | 441 | printf("%08x %08x %10s %08x %s\n", |
391 | rel->r_offset, | 442 | rel->r_offset, |
392 | rel->r_info, | 443 | rel->r_info, |
@@ -395,7 +446,9 @@ static void print_absolute_relocs(void) | |||
395 | name); | 446 | name); |
396 | } | 447 | } |
397 | } | 448 | } |
398 | printf("\n"); | 449 | |
450 | if (printed) | ||
451 | printf("\n"); | ||
399 | } | 452 | } |
400 | 453 | ||
401 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | 454 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) |
@@ -508,25 +561,31 @@ static void emit_relocs(int as_text) | |||
508 | 561 | ||
509 | static void usage(void) | 562 | static void usage(void) |
510 | { | 563 | { |
511 | die("i386_reloc [--abs | --text] vmlinux\n"); | 564 | die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); |
512 | } | 565 | } |
513 | 566 | ||
514 | int main(int argc, char **argv) | 567 | int main(int argc, char **argv) |
515 | { | 568 | { |
516 | int show_absolute; | 569 | int show_absolute_syms, show_absolute_relocs; |
517 | int as_text; | 570 | int as_text; |
518 | const char *fname; | 571 | const char *fname; |
519 | FILE *fp; | 572 | FILE *fp; |
520 | int i; | 573 | int i; |
521 | 574 | ||
522 | show_absolute = 0; | 575 | show_absolute_syms = 0; |
576 | show_absolute_relocs = 0; | ||
523 | as_text = 0; | 577 | as_text = 0; |
524 | fname = NULL; | 578 | fname = NULL; |
525 | for(i = 1; i < argc; i++) { | 579 | for(i = 1; i < argc; i++) { |
526 | char *arg = argv[i]; | 580 | char *arg = argv[i]; |
527 | if (*arg == '-') { | 581 | if (*arg == '-') { |
528 | if (strcmp(argv[1], "--abs") == 0) { | 582 | if (strcmp(argv[1], "--abs-syms") == 0) { |
529 | show_absolute = 1; | 583 | show_absolute_syms = 1; |
584 | continue; | ||
585 | } | ||
586 | |||
587 | if (strcmp(argv[1], "--abs-relocs") == 0) { | ||
588 | show_absolute_relocs = 1; | ||
530 | continue; | 589 | continue; |
531 | } | 590 | } |
532 | else if (strcmp(argv[1], "--text") == 0) { | 591 | else if (strcmp(argv[1], "--text") == 0) { |
@@ -553,8 +612,11 @@ int main(int argc, char **argv) | |||
553 | read_strtabs(fp); | 612 | read_strtabs(fp); |
554 | read_symtabs(fp); | 613 | read_symtabs(fp); |
555 | read_relocs(fp); | 614 | read_relocs(fp); |
556 | if (show_absolute) { | 615 | if (show_absolute_syms) { |
557 | print_absolute_symbols(); | 616 | print_absolute_symbols(); |
617 | return 0; | ||
618 | } | ||
619 | if (show_absolute_relocs) { | ||
558 | print_absolute_relocs(); | 620 | print_absolute_relocs(); |
559 | return 0; | 621 | return 0; |
560 | } | 622 | } |