diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-08 14:22:24 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-18 22:49:40 -0400 |
commit | 6520fe5564acf07ade7b18a1272db1184835c487 (patch) | |
tree | 363c95dea4c9202c2fbe1ebcfd9dd7b97c7422ac /arch | |
parent | 36be50515fe2aef61533b516fa2576a2c7fe7664 (diff) |
x86, realmode: 16-bit real-mode code support for relocs tool
A new option is added to the relocs tool called '--realmode'.
This option causes the generation of 16-bit segment relocations
and 32-bit linear relocations for the real-mode code. When
the real-mode code is moved to the low-memory during kernel
initialization, these relocation entries can be used to
relocate the code properly.
In the assembly code 16-bit segment relocations must be relative
to the 'real_mode_seg' absolute symbol. Linear relocations must be
relative to a symbol prefixed with 'pa_'.
16-bit segment relocation is used to load cs:ip in 16-bit code.
Linear relocations are used in the 32-bit code for relocatable
data references. They are declared in the linker script of the
real-mode code.
The relocs tool is moved to arch/x86/tools/relocs.c, and added new
target archscripts that can be used to build scripts needed building
an architecture. be compiled before building the arch/x86 tree.
[ hpa: accelerating this because it detects invalid absolute
relocations, a serious bug in binutils 2.22.52.0.x which currently
produces bad kernels. ]
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-2-git-send-email-jarkko.sakkinen@intel.com
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: <stable@vger.kernel.org>
Diffstat (limited to 'arch')
-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 |
5 files changed, 188 insertions, 62 deletions
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 41a7237606a..94e91e401da 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 fd55a2ff3ad..e398bb5d63b 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 00000000000..be0ed065249 --- /dev/null +++ b/arch/x86/tools/.gitignore | |||
@@ -0,0 +1 @@ | |||
relocs | |||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index d511aa97533..733057b435b 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 fb7117a4ade..02914706e5b 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 | } |