diff options
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | arch/x86/Makefile | 3 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/Makefile | 9 | ||||
| -rw-r--r-- | arch/x86/tools/.gitignore | 1 | ||||
| -rw-r--r-- | arch/x86/tools/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/tools/relocs.c (renamed from arch/x86/boot/compressed/relocs.c) | 233 | ||||
| -rw-r--r-- | scripts/Makefile | 2 |
7 files changed, 196 insertions, 65 deletions
| @@ -442,7 +442,7 @@ asm-generic: | |||
| 442 | 442 | ||
| 443 | no-dot-config-targets := clean mrproper distclean \ | 443 | no-dot-config-targets := clean mrproper distclean \ |
| 444 | cscope gtags TAGS tags help %docs check% coccicheck \ | 444 | cscope gtags TAGS tags help %docs check% coccicheck \ |
| 445 | include/linux/version.h headers_% archheaders \ | 445 | include/linux/version.h headers_% archheaders archscripts \ |
| 446 | kernelversion %src-pkg | 446 | kernelversion %src-pkg |
| 447 | 447 | ||
| 448 | config-targets := 0 | 448 | config-targets := 0 |
| @@ -979,7 +979,7 @@ prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ | |||
| 979 | include/config/auto.conf | 979 | include/config/auto.conf |
| 980 | $(cmd_crmodverdir) | 980 | $(cmd_crmodverdir) |
| 981 | 981 | ||
| 982 | archprepare: archheaders prepare1 scripts_basic | 982 | archprepare: archheaders archscripts prepare1 scripts_basic |
| 983 | 983 | ||
| 984 | prepare0: archprepare FORCE | 984 | prepare0: archprepare FORCE |
| 985 | $(Q)$(MAKE) $(build)=. | 985 | $(Q)$(MAKE) $(build)=. |
| @@ -1049,8 +1049,11 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) | |||
| 1049 | PHONY += archheaders | 1049 | PHONY += archheaders |
| 1050 | archheaders: | 1050 | archheaders: |
| 1051 | 1051 | ||
| 1052 | PHONY += archscripts | ||
| 1053 | archscripts: | ||
| 1054 | |||
| 1052 | PHONY += __headers | 1055 | PHONY += __headers |
| 1053 | __headers: include/linux/version.h scripts_basic asm-generic archheaders FORCE | 1056 | __headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE |
| 1054 | $(Q)$(MAKE) $(build)=scripts build_unifdef | 1057 | $(Q)$(MAKE) $(build)=scripts build_unifdef |
| 1055 | 1058 | ||
| 1056 | PHONY += headers_install_all | 1059 | PHONY += headers_install_all |
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 41a7237606a3..94e91e401da9 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
| @@ -134,6 +134,9 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) | |||
| 134 | KBUILD_CFLAGS += $(mflags-y) | 134 | KBUILD_CFLAGS += $(mflags-y) |
| 135 | KBUILD_AFLAGS += $(mflags-y) | 135 | KBUILD_AFLAGS += $(mflags-y) |
| 136 | 136 | ||
| 137 | archscripts: | ||
| 138 | $(Q)$(MAKE) $(build)=arch/x86/tools relocs | ||
| 139 | |||
| 137 | ### | 140 | ### |
| 138 | # Syscall table generation | 141 | # Syscall table generation |
| 139 | 142 | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index fd55a2ff3ad8..e398bb5d63bb 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
| @@ -40,13 +40,12 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S | |||
| 40 | $(obj)/vmlinux.bin: vmlinux FORCE | 40 | $(obj)/vmlinux.bin: vmlinux FORCE |
| 41 | $(call if_changed,objcopy) | 41 | $(call if_changed,objcopy) |
| 42 | 42 | ||
| 43 | targets += vmlinux.bin.all vmlinux.relocs | ||
| 43 | 44 | ||
| 44 | targets += vmlinux.bin.all vmlinux.relocs relocs | 45 | CMD_RELOCS = arch/x86/tools/relocs |
| 45 | hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs | ||
| 46 | |||
| 47 | quiet_cmd_relocs = RELOCS $@ | 46 | quiet_cmd_relocs = RELOCS $@ |
| 48 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< | 47 | cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< |
| 49 | $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE | 48 | $(obj)/vmlinux.relocs: vmlinux FORCE |
| 50 | $(call if_changed,relocs) | 49 | $(call if_changed,relocs) |
| 51 | 50 | ||
| 52 | vmlinux.bin.all-y := $(obj)/vmlinux.bin | 51 | vmlinux.bin.all-y := $(obj)/vmlinux.bin |
diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore new file mode 100644 index 000000000000..be0ed065249b --- /dev/null +++ b/arch/x86/tools/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| relocs | |||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index d511aa97533a..733057b435b0 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile | |||
| @@ -36,3 +36,7 @@ HOSTCFLAGS_insn_sanity.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x | |||
| 36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
| 37 | 37 | ||
| 38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
| 39 | |||
| 40 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
| 41 | hostprogs-y += relocs | ||
| 42 | relocs: $(obj)/relocs | ||
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/tools/relocs.c index fb7117a4ade1..02914706e5b9 100644 --- a/arch/x86/boot/compressed/relocs.c +++ b/arch/x86/tools/relocs.c | |||
| @@ -18,6 +18,8 @@ static void die(char *fmt, ...); | |||
| 18 | static Elf32_Ehdr ehdr; | 18 | static Elf32_Ehdr ehdr; |
| 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 | static unsigned long reloc16_count, reloc16_idx; | ||
| 22 | static unsigned long *relocs16; | ||
| 21 | 23 | ||
| 22 | struct section { | 24 | struct section { |
| 23 | Elf32_Shdr shdr; | 25 | Elf32_Shdr shdr; |
| @@ -28,52 +30,82 @@ struct section { | |||
| 28 | }; | 30 | }; |
| 29 | static struct section *secs; | 31 | static struct section *secs; |
| 30 | 32 | ||
| 33 | enum symtype { | ||
| 34 | S_ABS, | ||
| 35 | S_REL, | ||
| 36 | S_SEG, | ||
| 37 | S_LIN, | ||
| 38 | S_NSYMTYPES | ||
| 39 | }; | ||
| 40 | |||
| 41 | static const char * const sym_regex_kernel[S_NSYMTYPES] = { | ||
| 31 | /* | 42 | /* |
| 32 | * Following symbols have been audited. There values are constant and do | 43 | * Following symbols have been audited. There values are constant and do |
| 33 | * not change if bzImage is loaded at a different physical address than | 44 | * not change if bzImage is loaded at a different physical address than |
| 34 | * the address for which it has been compiled. Don't warn user about | 45 | * the address for which it has been compiled. Don't warn user about |
| 35 | * absolute relocations present w.r.t these symbols. | 46 | * absolute relocations present w.r.t these symbols. |
| 36 | */ | 47 | */ |
| 37 | static const char abs_sym_regex[] = | 48 | [S_ABS] = |
| 38 | "^(xen_irq_disable_direct_reloc$|" | 49 | "^(xen_irq_disable_direct_reloc$|" |
| 39 | "xen_save_fl_direct_reloc$|" | 50 | "xen_save_fl_direct_reloc$|" |
| 40 | "VDSO|" | 51 | "VDSO|" |
| 41 | "__crc_)"; | 52 | "__crc_)", |
| 42 | static regex_t abs_sym_regex_c; | ||
| 43 | static int is_abs_reloc(const char *sym_name) | ||
| 44 | { | ||
| 45 | return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0); | ||
| 46 | } | ||
| 47 | 53 | ||
| 48 | /* | 54 | /* |
| 49 | * These symbols are known to be relative, even if the linker marks them | 55 | * These symbols are known to be relative, even if the linker marks them |
| 50 | * as absolute (typically defined outside any section in the linker script.) | 56 | * as absolute (typically defined outside any section in the linker script.) |
| 51 | */ | 57 | */ |
| 52 | static const char rel_sym_regex[] = | 58 | [S_REL] = |
| 53 | "^_end$"; | 59 | "^_end$", |
| 54 | static regex_t rel_sym_regex_c; | 60 | }; |
| 55 | static int is_rel_reloc(const char *sym_name) | 61 | |
| 62 | |||
| 63 | static const char * const sym_regex_realmode[S_NSYMTYPES] = { | ||
| 64 | /* | ||
| 65 | * These are 16-bit segment symbols when compiling 16-bit code. | ||
| 66 | */ | ||
| 67 | [S_SEG] = | ||
| 68 | "^real_mode_seg$", | ||
| 69 | |||
| 70 | /* | ||
| 71 | * These are offsets belonging to segments, as opposed to linear addresses, | ||
| 72 | * when compiling 16-bit code. | ||
| 73 | */ | ||
| 74 | [S_LIN] = | ||
| 75 | "^pa_", | ||
| 76 | }; | ||
| 77 | |||
| 78 | static const char * const *sym_regex; | ||
| 79 | |||
| 80 | static regex_t sym_regex_c[S_NSYMTYPES]; | ||
| 81 | static int is_reloc(enum symtype type, const char *sym_name) | ||
| 56 | { | 82 | { |
| 57 | return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0); | 83 | return sym_regex[type] && |
| 84 | !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); | ||
| 58 | } | 85 | } |
| 59 | 86 | ||
| 60 | static void regex_init(void) | 87 | static void regex_init(int use_real_mode) |
| 61 | { | 88 | { |
| 62 | char errbuf[128]; | 89 | char errbuf[128]; |
| 63 | int err; | 90 | int err; |
| 64 | 91 | int i; | |
| 65 | err = regcomp(&abs_sym_regex_c, abs_sym_regex, | ||
| 66 | REG_EXTENDED|REG_NOSUB); | ||
| 67 | if (err) { | ||
| 68 | regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf); | ||
| 69 | die("%s", errbuf); | ||
| 70 | } | ||
| 71 | 92 | ||
| 72 | err = regcomp(&rel_sym_regex_c, rel_sym_regex, | 93 | if (use_real_mode) |
| 73 | REG_EXTENDED|REG_NOSUB); | 94 | sym_regex = sym_regex_realmode; |
| 74 | if (err) { | 95 | else |
| 75 | regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf); | 96 | sym_regex = sym_regex_kernel; |
| 76 | die("%s", errbuf); | 97 | |
| 98 | for (i = 0; i < S_NSYMTYPES; i++) { | ||
| 99 | if (!sym_regex[i]) | ||
| 100 | continue; | ||
| 101 | |||
| 102 | err = regcomp(&sym_regex_c[i], sym_regex[i], | ||
| 103 | REG_EXTENDED|REG_NOSUB); | ||
| 104 | |||
| 105 | if (err) { | ||
| 106 | regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); | ||
| 107 | die("%s", errbuf); | ||
| 108 | } | ||
| 77 | } | 109 | } |
| 78 | } | 110 | } |
| 79 | 111 | ||
| @@ -154,6 +186,10 @@ static const char *rel_type(unsigned type) | |||
| 154 | REL_TYPE(R_386_RELATIVE), | 186 | REL_TYPE(R_386_RELATIVE), |
| 155 | REL_TYPE(R_386_GOTOFF), | 187 | REL_TYPE(R_386_GOTOFF), |
| 156 | REL_TYPE(R_386_GOTPC), | 188 | REL_TYPE(R_386_GOTPC), |
| 189 | REL_TYPE(R_386_8), | ||
| 190 | REL_TYPE(R_386_PC8), | ||
| 191 | REL_TYPE(R_386_16), | ||
| 192 | REL_TYPE(R_386_PC16), | ||
| 157 | #undef REL_TYPE | 193 | #undef REL_TYPE |
| 158 | }; | 194 | }; |
| 159 | const char *name = "unknown type rel type name"; | 195 | const char *name = "unknown type rel type name"; |
| @@ -189,7 +225,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) | |||
| 189 | name = sym_strtab + sym->st_name; | 225 | name = sym_strtab + sym->st_name; |
| 190 | } | 226 | } |
| 191 | else { | 227 | else { |
| 192 | name = sec_name(secs[sym->st_shndx].shdr.sh_name); | 228 | name = sec_name(sym->st_shndx); |
| 193 | } | 229 | } |
| 194 | return name; | 230 | return name; |
| 195 | } | 231 | } |
| @@ -472,7 +508,7 @@ static void print_absolute_relocs(void) | |||
| 472 | * Before warning check if this absolute symbol | 508 | * Before warning check if this absolute symbol |
| 473 | * relocation is harmless. | 509 | * relocation is harmless. |
| 474 | */ | 510 | */ |
| 475 | if (is_abs_reloc(name) || is_rel_reloc(name)) | 511 | if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) |
| 476 | continue; | 512 | continue; |
| 477 | 513 | ||
| 478 | if (!printed) { | 514 | if (!printed) { |
| @@ -496,7 +532,8 @@ static void print_absolute_relocs(void) | |||
| 496 | printf("\n"); | 532 | printf("\n"); |
| 497 | } | 533 | } |
| 498 | 534 | ||
| 499 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | 535 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), |
| 536 | int use_real_mode) | ||
| 500 | { | 537 | { |
| 501 | int i; | 538 | int i; |
| 502 | /* Walk through the relocations */ | 539 | /* Walk through the relocations */ |
| @@ -521,30 +558,62 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
| 521 | Elf32_Rel *rel; | 558 | Elf32_Rel *rel; |
| 522 | Elf32_Sym *sym; | 559 | Elf32_Sym *sym; |
| 523 | unsigned r_type; | 560 | unsigned r_type; |
| 561 | const char *symname; | ||
| 524 | rel = &sec->reltab[j]; | 562 | rel = &sec->reltab[j]; |
| 525 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; | 563 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; |
| 526 | r_type = ELF32_R_TYPE(rel->r_info); | 564 | r_type = ELF32_R_TYPE(rel->r_info); |
| 527 | /* Don't visit relocations to absolute symbols */ | 565 | |
| 528 | if (sym->st_shndx == SHN_ABS && | ||
| 529 | !is_rel_reloc(sym_name(sym_strtab, sym))) { | ||
| 530 | continue; | ||
| 531 | } | ||
| 532 | switch (r_type) { | 566 | switch (r_type) { |
| 533 | case R_386_NONE: | 567 | case R_386_NONE: |
| 534 | case R_386_PC32: | 568 | case R_386_PC32: |
| 569 | case R_386_PC16: | ||
| 570 | case R_386_PC8: | ||
| 535 | /* | 571 | /* |
| 536 | * NONE can be ignored and and PC relative | 572 | * NONE can be ignored and and PC relative |
| 537 | * relocations don't need to be adjusted. | 573 | * relocations don't need to be adjusted. |
| 538 | */ | 574 | */ |
| 539 | break; | 575 | break; |
| 576 | |||
| 577 | case R_386_16: | ||
| 578 | symname = sym_name(sym_strtab, sym); | ||
| 579 | if (!use_real_mode) | ||
| 580 | goto bad; | ||
| 581 | if (sym->st_shndx == SHN_ABS) { | ||
| 582 | if (is_reloc(S_ABS, symname)) | ||
| 583 | break; | ||
| 584 | else if (!is_reloc(S_SEG, symname)) | ||
| 585 | goto bad; | ||
| 586 | } else { | ||
| 587 | if (is_reloc(S_LIN, symname)) | ||
| 588 | goto bad; | ||
| 589 | else | ||
| 590 | break; | ||
| 591 | } | ||
| 592 | visit(rel, sym); | ||
| 593 | break; | ||
| 594 | |||
| 540 | case R_386_32: | 595 | case R_386_32: |
| 541 | /* Visit relocations that need to be adjusted */ | 596 | symname = sym_name(sym_strtab, sym); |
| 597 | if (sym->st_shndx == SHN_ABS) { | ||
| 598 | if (is_reloc(S_ABS, symname)) | ||
| 599 | break; | ||
| 600 | else if (!is_reloc(S_REL, symname)) | ||
| 601 | goto bad; | ||
| 602 | } else { | ||
| 603 | if (use_real_mode && | ||
| 604 | !is_reloc(S_LIN, symname)) | ||
| 605 | break; | ||
| 606 | } | ||
| 542 | visit(rel, sym); | 607 | visit(rel, sym); |
| 543 | break; | 608 | break; |
| 544 | default: | 609 | default: |
| 545 | die("Unsupported relocation type: %s (%d)\n", | 610 | die("Unsupported relocation type: %s (%d)\n", |
| 546 | rel_type(r_type), r_type); | 611 | rel_type(r_type), r_type); |
| 547 | break; | 612 | break; |
| 613 | bad: | ||
| 614 | symname = sym_name(sym_strtab, sym); | ||
| 615 | die("Invalid %s relocation: %s\n", | ||
| 616 | rel_type(r_type), symname); | ||
| 548 | } | 617 | } |
| 549 | } | 618 | } |
| 550 | } | 619 | } |
| @@ -552,13 +621,19 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
| 552 | 621 | ||
| 553 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 622 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
| 554 | { | 623 | { |
| 555 | reloc_count += 1; | 624 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
| 625 | reloc16_count++; | ||
| 626 | else | ||
| 627 | reloc_count++; | ||
| 556 | } | 628 | } |
| 557 | 629 | ||
| 558 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 630 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
| 559 | { | 631 | { |
| 560 | /* Remember the address that needs to be adjusted. */ | 632 | /* Remember the address that needs to be adjusted. */ |
| 561 | relocs[reloc_idx++] = rel->r_offset; | 633 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
| 634 | relocs16[reloc16_idx++] = rel->r_offset; | ||
| 635 | else | ||
| 636 | relocs[reloc_idx++] = rel->r_offset; | ||
| 562 | } | 637 | } |
| 563 | 638 | ||
| 564 | static int cmp_relocs(const void *va, const void *vb) | 639 | static int cmp_relocs(const void *va, const void *vb) |
| @@ -568,23 +643,41 @@ static int cmp_relocs(const void *va, const void *vb) | |||
| 568 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; | 643 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; |
| 569 | } | 644 | } |
| 570 | 645 | ||
| 571 | static void emit_relocs(int as_text) | 646 | static int write32(unsigned int v, FILE *f) |
| 647 | { | ||
| 648 | unsigned char buf[4]; | ||
| 649 | |||
| 650 | put_unaligned_le32(v, buf); | ||
| 651 | return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; | ||
| 652 | } | ||
| 653 | |||
| 654 | static void emit_relocs(int as_text, int use_real_mode) | ||
| 572 | { | 655 | { |
| 573 | int i; | 656 | int i; |
| 574 | /* Count how many relocations I have and allocate space for them. */ | 657 | /* Count how many relocations I have and allocate space for them. */ |
| 575 | reloc_count = 0; | 658 | reloc_count = 0; |
| 576 | walk_relocs(count_reloc); | 659 | walk_relocs(count_reloc, use_real_mode); |
| 577 | relocs = malloc(reloc_count * sizeof(relocs[0])); | 660 | relocs = malloc(reloc_count * sizeof(relocs[0])); |
| 578 | if (!relocs) { | 661 | if (!relocs) { |
| 579 | die("malloc of %d entries for relocs failed\n", | 662 | die("malloc of %d entries for relocs failed\n", |
| 580 | reloc_count); | 663 | reloc_count); |
| 581 | } | 664 | } |
| 665 | |||
| 666 | relocs16 = malloc(reloc16_count * sizeof(relocs[0])); | ||
| 667 | if (!relocs16) { | ||
| 668 | die("malloc of %d entries for relocs16 failed\n", | ||
| 669 | reloc16_count); | ||
| 670 | } | ||
| 582 | /* Collect up the relocations */ | 671 | /* Collect up the relocations */ |
| 583 | reloc_idx = 0; | 672 | reloc_idx = 0; |
| 584 | walk_relocs(collect_reloc); | 673 | walk_relocs(collect_reloc, use_real_mode); |
| 674 | |||
| 675 | if (reloc16_count && !use_real_mode) | ||
| 676 | die("Segment relocations found but --realmode not specified\n"); | ||
| 585 | 677 | ||
| 586 | /* Order the relocations for more efficient processing */ | 678 | /* Order the relocations for more efficient processing */ |
| 587 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); | 679 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); |
| 680 | qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); | ||
| 588 | 681 | ||
| 589 | /* Print the relocations */ | 682 | /* Print the relocations */ |
| 590 | if (as_text) { | 683 | if (as_text) { |
| @@ -593,58 +686,83 @@ static void emit_relocs(int as_text) | |||
| 593 | */ | 686 | */ |
| 594 | printf(".section \".data.reloc\",\"a\"\n"); | 687 | printf(".section \".data.reloc\",\"a\"\n"); |
| 595 | printf(".balign 4\n"); | 688 | printf(".balign 4\n"); |
| 596 | for (i = 0; i < reloc_count; i++) { | 689 | if (use_real_mode) { |
| 597 | printf("\t .long 0x%08lx\n", relocs[i]); | 690 | printf("\t.long %lu\n", reloc16_count); |
| 691 | for (i = 0; i < reloc16_count; i++) | ||
| 692 | printf("\t.long 0x%08lx\n", relocs16[i]); | ||
| 693 | printf("\t.long %lu\n", reloc_count); | ||
| 694 | for (i = 0; i < reloc_count; i++) { | ||
| 695 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
| 696 | } | ||
| 697 | } else { | ||
| 698 | /* Print a stop */ | ||
| 699 | printf("\t.long 0x%08lx\n", (unsigned long)0); | ||
| 700 | for (i = 0; i < reloc_count; i++) { | ||
| 701 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
| 702 | } | ||
| 598 | } | 703 | } |
| 704 | |||
| 599 | printf("\n"); | 705 | printf("\n"); |
| 600 | } | 706 | } |
| 601 | else { | 707 | else { |
| 602 | unsigned char buf[4]; | 708 | if (use_real_mode) { |
| 603 | /* Print a stop */ | 709 | write32(reloc16_count, stdout); |
| 604 | fwrite("\0\0\0\0", 4, 1, stdout); | 710 | for (i = 0; i < reloc16_count; i++) |
| 605 | /* Now print each relocation */ | 711 | write32(relocs16[i], stdout); |
| 606 | for (i = 0; i < reloc_count; i++) { | 712 | write32(reloc_count, stdout); |
| 607 | put_unaligned_le32(relocs[i], buf); | 713 | |
| 608 | fwrite(buf, 4, 1, stdout); | 714 | /* Now print each relocation */ |
| 715 | for (i = 0; i < reloc_count; i++) | ||
| 716 | write32(relocs[i], stdout); | ||
| 717 | } else { | ||
| 718 | /* Print a stop */ | ||
| 719 | write32(0, stdout); | ||
| 720 | |||
| 721 | /* Now print each relocation */ | ||
| 722 | for (i = 0; i < reloc_count; i++) { | ||
| 723 | write32(relocs[i], stdout); | ||
| 724 | } | ||
| 609 | } | 725 | } |
| 610 | } | 726 | } |
| 611 | } | 727 | } |
| 612 | 728 | ||
| 613 | static void usage(void) | 729 | static void usage(void) |
| 614 | { | 730 | { |
| 615 | die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); | 731 | die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); |
| 616 | } | 732 | } |
| 617 | 733 | ||
| 618 | int main(int argc, char **argv) | 734 | int main(int argc, char **argv) |
| 619 | { | 735 | { |
| 620 | int show_absolute_syms, show_absolute_relocs; | 736 | int show_absolute_syms, show_absolute_relocs; |
| 621 | int as_text; | 737 | int as_text, use_real_mode; |
| 622 | const char *fname; | 738 | const char *fname; |
| 623 | FILE *fp; | 739 | FILE *fp; |
| 624 | int i; | 740 | int i; |
| 625 | 741 | ||
| 626 | regex_init(); | ||
| 627 | |||
| 628 | show_absolute_syms = 0; | 742 | show_absolute_syms = 0; |
| 629 | show_absolute_relocs = 0; | 743 | show_absolute_relocs = 0; |
| 630 | as_text = 0; | 744 | as_text = 0; |
| 745 | use_real_mode = 0; | ||
| 631 | fname = NULL; | 746 | fname = NULL; |
| 632 | for (i = 1; i < argc; i++) { | 747 | for (i = 1; i < argc; i++) { |
| 633 | char *arg = argv[i]; | 748 | char *arg = argv[i]; |
| 634 | if (*arg == '-') { | 749 | if (*arg == '-') { |
| 635 | if (strcmp(argv[1], "--abs-syms") == 0) { | 750 | if (strcmp(arg, "--abs-syms") == 0) { |
| 636 | show_absolute_syms = 1; | 751 | show_absolute_syms = 1; |
| 637 | continue; | 752 | continue; |
| 638 | } | 753 | } |
| 639 | 754 | if (strcmp(arg, "--abs-relocs") == 0) { | |
| 640 | if (strcmp(argv[1], "--abs-relocs") == 0) { | ||
| 641 | show_absolute_relocs = 1; | 755 | show_absolute_relocs = 1; |
| 642 | continue; | 756 | continue; |
| 643 | } | 757 | } |
| 644 | else if (strcmp(argv[1], "--text") == 0) { | 758 | if (strcmp(arg, "--text") == 0) { |
| 645 | as_text = 1; | 759 | as_text = 1; |
| 646 | continue; | 760 | continue; |
| 647 | } | 761 | } |
| 762 | if (strcmp(arg, "--realmode") == 0) { | ||
| 763 | use_real_mode = 1; | ||
| 764 | continue; | ||
| 765 | } | ||
| 648 | } | 766 | } |
| 649 | else if (!fname) { | 767 | else if (!fname) { |
| 650 | fname = arg; | 768 | fname = arg; |
| @@ -655,6 +773,7 @@ int main(int argc, char **argv) | |||
| 655 | if (!fname) { | 773 | if (!fname) { |
| 656 | usage(); | 774 | usage(); |
| 657 | } | 775 | } |
| 776 | regex_init(use_real_mode); | ||
| 658 | fp = fopen(fname, "r"); | 777 | fp = fopen(fname, "r"); |
| 659 | if (!fp) { | 778 | if (!fp) { |
| 660 | die("Cannot open %s: %s\n", | 779 | die("Cannot open %s: %s\n", |
| @@ -673,6 +792,6 @@ int main(int argc, char **argv) | |||
| 673 | print_absolute_relocs(); | 792 | print_absolute_relocs(); |
| 674 | return 0; | 793 | return 0; |
| 675 | } | 794 | } |
| 676 | emit_relocs(as_text); | 795 | emit_relocs(as_text, use_real_mode); |
| 677 | return 0; | 796 | return 0; |
| 678 | } | 797 | } |
diff --git a/scripts/Makefile b/scripts/Makefile index df7678febf27..36266665dbcb 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | # conmakehash: Create arrays for initializing the kernel console tables | 8 | # conmakehash: Create arrays for initializing the kernel console tables |
| 9 | # docproc: Used in Documentation/DocBook | 9 | # docproc: Used in Documentation/DocBook |
| 10 | 10 | ||
| 11 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
| 12 | |||
| 11 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms | 13 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms |
| 12 | hostprogs-$(CONFIG_LOGO) += pnmtologo | 14 | hostprogs-$(CONFIG_LOGO) += pnmtologo |
| 13 | hostprogs-$(CONFIG_VT) += conmakehash | 15 | hostprogs-$(CONFIG_VT) += conmakehash |
