diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-16 19:02:58 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-16 19:02:58 -0400 |
commit | c889ba801dc3b3a0155fa77d567f2c3a6097de1c (patch) | |
tree | 257878e1eb565fc9765dd8fed20815f7781d116a | |
parent | 17c961f7702ff6037b66bb2e5f3ddd58de4ce7e5 (diff) |
x86, relocs: Refactor the relocs tool to merge 32- and 64-bit ELF
Refactor the relocs tool so that the same tool can handle 32- and
64-bit ELF.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Kees Cook <keescook@chromium.org>
Link: http://lkml.kernel.org/r/1365797627-20874-5-git-send-email-keescook@chromium.org
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/realmode/rm/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/tools/.gitignore | 3 | ||||
-rw-r--r-- | arch/x86/tools/Makefile | 21 | ||||
-rw-r--r-- | arch/x86/tools/relocs.c | 162 | ||||
-rw-r--r-- | arch/x86/tools/relocs.h | 36 | ||||
-rw-r--r-- | arch/x86/tools/relocs_32.c | 17 | ||||
-rw-r--r-- | arch/x86/tools/relocs_64.c | 17 | ||||
-rw-r--r-- | arch/x86/tools/relocs_common.c | 76 |
9 files changed, 183 insertions, 153 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 0dac17528099..5ef205c5f37b 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -44,7 +44,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE | |||
44 | 44 | ||
45 | targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs | 45 | targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs |
46 | 46 | ||
47 | CMD_RELOCS = arch/x86/tools/relocs_$(BITS) | 47 | CMD_RELOCS = arch/x86/tools/relocs |
48 | quiet_cmd_relocs = RELOCS $@ | 48 | quiet_cmd_relocs = RELOCS $@ |
49 | cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< | 49 | cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< |
50 | $(obj)/vmlinux.relocs: vmlinux FORCE | 50 | $(obj)/vmlinux.relocs: vmlinux FORCE |
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 2b1e4294b8b9..88692871823f 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile | |||
@@ -56,7 +56,7 @@ $(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs | |||
56 | $(call if_changed,objcopy) | 56 | $(call if_changed,objcopy) |
57 | 57 | ||
58 | quiet_cmd_relocs = RELOCS $@ | 58 | quiet_cmd_relocs = RELOCS $@ |
59 | cmd_relocs = arch/x86/tools/relocs_32 --realmode $< > $@ | 59 | cmd_relocs = arch/x86/tools/relocs --realmode $< > $@ |
60 | 60 | ||
61 | targets += realmode.relocs | 61 | targets += realmode.relocs |
62 | $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE | 62 | $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE |
diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore index 2b45d5f063ba..be0ed065249b 100644 --- a/arch/x86/tools/.gitignore +++ b/arch/x86/tools/.gitignore | |||
@@ -1,2 +1 @@ | |||
1 | relocs_32* | relocs | |
2 | relocs_64* | ||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index a8cb70c6b8a1..e8120346903b 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile | |||
@@ -37,22 +37,7 @@ $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/in | |||
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 | 39 | ||
40 | HOSTCFLAGS_relocs_32.o += -DELF_BITS=32 | ||
41 | HOSTCFLAGS_relocs_64.o += -DELF_BITS=64 | ||
42 | |||
43 | quiet_cmd_cp_reloc = GEN $@ | ||
44 | cmd_cp_reloc = cp $< $@ | ||
45 | |||
46 | $(obj)/relocs_%.c: $(srctree)/arch/x86/tools/relocs.c | ||
47 | $(call cmd,cp_reloc) | ||
48 | |||
49 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | 40 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include |
50 | hostprogs-y += relocs_$(BITS) | 41 | hostprogs-y += relocs |
51 | relocs_binaries = relocs_$(BITS) | 42 | relocs-objs := relocs_32.o relocs_64.o relocs_common.o |
52 | ifeq ($(CONFIG_64BIT),y) | 43 | relocs: $(obj)/relocs |
53 | hostprogs-y += relocs_32 | ||
54 | relocs_binaries += relocs_32 | ||
55 | endif | ||
56 | relocs: $(relocs_binaries) | ||
57 | relocs_32: $(obj)/relocs_32 | ||
58 | relocs_64: $(obj)/relocs_64 | ||
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index 1f7ff3d11a05..590be1090892 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -1,63 +1,15 @@ | |||
1 | #include <stdio.h> | 1 | /* This is included from relocs_32/64.c */ |
2 | #include <stdarg.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <stdint.h> | ||
5 | #include <inttypes.h> | ||
6 | #include <string.h> | ||
7 | #include <errno.h> | ||
8 | #include <unistd.h> | ||
9 | #include <elf.h> | ||
10 | #include <byteswap.h> | ||
11 | #define USE_BSD | ||
12 | #include <endian.h> | ||
13 | #include <regex.h> | ||
14 | #include <tools/le_byteshift.h> | ||
15 | 2 | ||
16 | #define ElfW(type) _ElfW(ELF_BITS, type) | 3 | #define ElfW(type) _ElfW(ELF_BITS, type) |
17 | #define _ElfW(bits, type) __ElfW(bits, type) | 4 | #define _ElfW(bits, type) __ElfW(bits, type) |
18 | #define __ElfW(bits, type) Elf##bits##_##type | 5 | #define __ElfW(bits, type) Elf##bits##_##type |
19 | 6 | ||
20 | #ifndef ELF_BITS | ||
21 | #define ELF_BITS 32 | ||
22 | #endif | ||
23 | |||
24 | #if (ELF_BITS == 64) | ||
25 | #define ELF_MACHINE EM_X86_64 | ||
26 | #define ELF_MACHINE_NAME "x86_64" | ||
27 | #define SHT_REL_TYPE SHT_RELA | ||
28 | #define Elf_Rel Elf64_Rela | ||
29 | #else | ||
30 | #define ELF_MACHINE EM_386 | ||
31 | #define ELF_MACHINE_NAME "i386" | ||
32 | #define SHT_REL_TYPE SHT_REL | ||
33 | #define Elf_Rel ElfW(Rel) | ||
34 | #endif | ||
35 | |||
36 | #if (ELF_BITS == 64) | ||
37 | #define ELF_CLASS ELFCLASS64 | ||
38 | #define ELF_R_SYM(val) ELF64_R_SYM(val) | ||
39 | #define ELF_R_TYPE(val) ELF64_R_TYPE(val) | ||
40 | #define ELF_ST_TYPE(o) ELF64_ST_TYPE(o) | ||
41 | #define ELF_ST_BIND(o) ELF64_ST_BIND(o) | ||
42 | #define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o) | ||
43 | #else | ||
44 | #define ELF_CLASS ELFCLASS32 | ||
45 | #define ELF_R_SYM(val) ELF32_R_SYM(val) | ||
46 | #define ELF_R_TYPE(val) ELF32_R_TYPE(val) | ||
47 | #define ELF_ST_TYPE(o) ELF32_ST_TYPE(o) | ||
48 | #define ELF_ST_BIND(o) ELF32_ST_BIND(o) | ||
49 | #define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) | ||
50 | #endif | ||
51 | |||
52 | #define Elf_Addr ElfW(Addr) | 7 | #define Elf_Addr ElfW(Addr) |
53 | #define Elf_Ehdr ElfW(Ehdr) | 8 | #define Elf_Ehdr ElfW(Ehdr) |
54 | #define Elf_Phdr ElfW(Phdr) | 9 | #define Elf_Phdr ElfW(Phdr) |
55 | #define Elf_Shdr ElfW(Shdr) | 10 | #define Elf_Shdr ElfW(Shdr) |
56 | #define Elf_Sym ElfW(Sym) | 11 | #define Elf_Sym ElfW(Sym) |
57 | 12 | ||
58 | static void die(char *fmt, ...); | ||
59 | |||
60 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
61 | static Elf_Ehdr ehdr; | 13 | static Elf_Ehdr ehdr; |
62 | 14 | ||
63 | struct relocs { | 15 | struct relocs { |
@@ -79,14 +31,6 @@ struct section { | |||
79 | }; | 31 | }; |
80 | static struct section *secs; | 32 | static struct section *secs; |
81 | 33 | ||
82 | enum symtype { | ||
83 | S_ABS, | ||
84 | S_REL, | ||
85 | S_SEG, | ||
86 | S_LIN, | ||
87 | S_NSYMTYPES | ||
88 | }; | ||
89 | |||
90 | static const char * const sym_regex_kernel[S_NSYMTYPES] = { | 34 | static const char * const sym_regex_kernel[S_NSYMTYPES] = { |
91 | /* | 35 | /* |
92 | * Following symbols have been audited. There values are constant and do | 36 | * Following symbols have been audited. There values are constant and do |
@@ -98,7 +42,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { | |||
98 | "^(xen_irq_disable_direct_reloc$|" | 42 | "^(xen_irq_disable_direct_reloc$|" |
99 | "xen_save_fl_direct_reloc$|" | 43 | "xen_save_fl_direct_reloc$|" |
100 | "VDSO|" | 44 | "VDSO|" |
101 | #if (ELF_BITS == 64) | 45 | #if ELF_BITS == 64 |
102 | "__vvar_page|" | 46 | "__vvar_page|" |
103 | #endif | 47 | #endif |
104 | "__crc_)", | 48 | "__crc_)", |
@@ -124,7 +68,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { | |||
124 | "__end_rodata|" | 68 | "__end_rodata|" |
125 | "__initramfs_start|" | 69 | "__initramfs_start|" |
126 | "(jiffies|jiffies_64)|" | 70 | "(jiffies|jiffies_64)|" |
127 | #if (ELF_BITS == 64) | 71 | #if ELF_BITS == 64 |
128 | "__per_cpu_load|" | 72 | "__per_cpu_load|" |
129 | "init_per_cpu__.*|" | 73 | "init_per_cpu__.*|" |
130 | "__end_rodata_hpage_align|" | 74 | "__end_rodata_hpage_align|" |
@@ -189,15 +133,6 @@ static void regex_init(int use_real_mode) | |||
189 | } | 133 | } |
190 | } | 134 | } |
191 | 135 | ||
192 | static void die(char *fmt, ...) | ||
193 | { | ||
194 | va_list ap; | ||
195 | va_start(ap, fmt); | ||
196 | vfprintf(stderr, fmt, ap); | ||
197 | va_end(ap); | ||
198 | exit(1); | ||
199 | } | ||
200 | |||
201 | static const char *sym_type(unsigned type) | 136 | static const char *sym_type(unsigned type) |
202 | { | 137 | { |
203 | static const char *type_name[] = { | 138 | static const char *type_name[] = { |
@@ -255,7 +190,7 @@ static const char *rel_type(unsigned type) | |||
255 | { | 190 | { |
256 | static const char *type_name[] = { | 191 | static const char *type_name[] = { |
257 | #define REL_TYPE(X) [X] = #X | 192 | #define REL_TYPE(X) [X] = #X |
258 | #if (ELF_BITS == 64) | 193 | #if ELF_BITS == 64 |
259 | REL_TYPE(R_X86_64_NONE), | 194 | REL_TYPE(R_X86_64_NONE), |
260 | REL_TYPE(R_X86_64_64), | 195 | REL_TYPE(R_X86_64_64), |
261 | REL_TYPE(R_X86_64_PC32), | 196 | REL_TYPE(R_X86_64_PC32), |
@@ -380,7 +315,7 @@ static uint32_t elf32_to_cpu(uint32_t val) | |||
380 | #define elf_half_to_cpu(x) elf16_to_cpu(x) | 315 | #define elf_half_to_cpu(x) elf16_to_cpu(x) |
381 | #define elf_word_to_cpu(x) elf32_to_cpu(x) | 316 | #define elf_word_to_cpu(x) elf32_to_cpu(x) |
382 | 317 | ||
383 | #if (ELF_BITS == 64) | 318 | #if ELF_BITS == 64 |
384 | static uint64_t elf64_to_cpu(uint64_t val) | 319 | static uint64_t elf64_to_cpu(uint64_t val) |
385 | { | 320 | { |
386 | return le64_to_cpu(val); | 321 | return le64_to_cpu(val); |
@@ -582,7 +517,7 @@ static void print_absolute_symbols(void) | |||
582 | int i; | 517 | int i; |
583 | const char *format; | 518 | const char *format; |
584 | 519 | ||
585 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) | 520 | if (ELF_BITS == 64) |
586 | format = "%5d %016"PRIx64" %5"PRId64" %10s %10s %12s %s\n"; | 521 | format = "%5d %016"PRIx64" %5"PRId64" %10s %10s %12s %s\n"; |
587 | else | 522 | else |
588 | format = "%5d %08"PRIx32" %5"PRId32" %10s %10s %12s %s\n"; | 523 | format = "%5d %08"PRIx32" %5"PRId32" %10s %10s %12s %s\n"; |
@@ -622,7 +557,7 @@ static void print_absolute_relocs(void) | |||
622 | int i, printed = 0; | 557 | int i, printed = 0; |
623 | const char *format; | 558 | const char *format; |
624 | 559 | ||
625 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) | 560 | if (ELF_BITS == 64) |
626 | format = "%016"PRIx64" %016"PRIx64" %10s %016"PRIx64" %s\n"; | 561 | format = "%016"PRIx64" %016"PRIx64" %10s %016"PRIx64" %s\n"; |
627 | else | 562 | else |
628 | format = "%08"PRIx32" %08"PRIx32" %10s %08"PRIx32" %s\n"; | 563 | format = "%08"PRIx32" %08"PRIx32" %10s %08"PRIx32" %s\n"; |
@@ -785,6 +720,8 @@ static void percpu_init(void) | |||
785 | } | 720 | } |
786 | } | 721 | } |
787 | 722 | ||
723 | #if ELF_BITS == 64 | ||
724 | |||
788 | /* | 725 | /* |
789 | * Check to see if a symbol lies in the .data..percpu section. | 726 | * Check to see if a symbol lies in the .data..percpu section. |
790 | * For some as yet not understood reason the "__init_begin" | 727 | * For some as yet not understood reason the "__init_begin" |
@@ -798,6 +735,7 @@ static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) | |||
798 | strcmp(symname, "__init_begin"); | 735 | strcmp(symname, "__init_begin"); |
799 | } | 736 | } |
800 | 737 | ||
738 | |||
801 | static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, | 739 | static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, |
802 | const char *symname) | 740 | const char *symname) |
803 | { | 741 | { |
@@ -869,6 +807,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, | |||
869 | return 0; | 807 | return 0; |
870 | } | 808 | } |
871 | 809 | ||
810 | #else | ||
872 | 811 | ||
873 | static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, | 812 | static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, |
874 | const char *symname) | 813 | const char *symname) |
@@ -984,6 +923,8 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, | |||
984 | return 0; | 923 | return 0; |
985 | } | 924 | } |
986 | 925 | ||
926 | #endif | ||
927 | |||
987 | static int cmp_relocs(const void *va, const void *vb) | 928 | static int cmp_relocs(const void *va, const void *vb) |
988 | { | 929 | { |
989 | const uint32_t *a, *b; | 930 | const uint32_t *a, *b; |
@@ -1016,12 +957,17 @@ static void emit_relocs(int as_text, int use_real_mode) | |||
1016 | int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, | 957 | int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, |
1017 | const char *symname); | 958 | const char *symname); |
1018 | 959 | ||
1019 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) | 960 | #if ELF_BITS == 64 |
961 | if (!use_real_mode) | ||
1020 | do_reloc = do_reloc64; | 962 | do_reloc = do_reloc64; |
1021 | else if (!use_real_mode) | 963 | else |
964 | die("--realmode not valid for a 64-bit ELF file"); | ||
965 | #else | ||
966 | if (!use_real_mode) | ||
1022 | do_reloc = do_reloc32; | 967 | do_reloc = do_reloc32; |
1023 | else | 968 | else |
1024 | do_reloc = do_reloc_real; | 969 | do_reloc = do_reloc_real; |
970 | #endif | ||
1025 | 971 | ||
1026 | /* Collect up the relocations */ | 972 | /* Collect up the relocations */ |
1027 | walk_relocs(do_reloc); | 973 | walk_relocs(do_reloc); |
@@ -1053,7 +999,7 @@ static void emit_relocs(int as_text, int use_real_mode) | |||
1053 | for (i = 0; i < relocs32.count; i++) | 999 | for (i = 0; i < relocs32.count; i++) |
1054 | write_reloc(relocs32.offset[i], stdout); | 1000 | write_reloc(relocs32.offset[i], stdout); |
1055 | } else { | 1001 | } else { |
1056 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { | 1002 | if (ELF_BITS == 64) { |
1057 | /* Print a stop */ | 1003 | /* Print a stop */ |
1058 | write_reloc(0, stdout); | 1004 | write_reloc(0, stdout); |
1059 | 1005 | ||
@@ -1071,76 +1017,30 @@ static void emit_relocs(int as_text, int use_real_mode) | |||
1071 | } | 1017 | } |
1072 | } | 1018 | } |
1073 | 1019 | ||
1074 | static void usage(void) | 1020 | #if ELF_BITS == 64 |
1075 | { | 1021 | # define process process_64 |
1076 | die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); | 1022 | #else |
1077 | } | 1023 | # define process process_32 |
1024 | #endif | ||
1078 | 1025 | ||
1079 | int main(int argc, char **argv) | 1026 | void process(FILE *fp, int use_real_mode, int as_text, |
1027 | int show_absolute_syms, int show_absolute_relocs) | ||
1080 | { | 1028 | { |
1081 | int show_absolute_syms, show_absolute_relocs; | ||
1082 | int as_text, use_real_mode; | ||
1083 | const char *fname; | ||
1084 | FILE *fp; | ||
1085 | int i; | ||
1086 | |||
1087 | show_absolute_syms = 0; | ||
1088 | show_absolute_relocs = 0; | ||
1089 | as_text = 0; | ||
1090 | use_real_mode = 0; | ||
1091 | fname = NULL; | ||
1092 | for (i = 1; i < argc; i++) { | ||
1093 | char *arg = argv[i]; | ||
1094 | if (*arg == '-') { | ||
1095 | if (strcmp(arg, "--abs-syms") == 0) { | ||
1096 | show_absolute_syms = 1; | ||
1097 | continue; | ||
1098 | } | ||
1099 | if (strcmp(arg, "--abs-relocs") == 0) { | ||
1100 | show_absolute_relocs = 1; | ||
1101 | continue; | ||
1102 | } | ||
1103 | if (strcmp(arg, "--text") == 0) { | ||
1104 | as_text = 1; | ||
1105 | continue; | ||
1106 | } | ||
1107 | if (strcmp(arg, "--realmode") == 0) { | ||
1108 | use_real_mode = 1; | ||
1109 | continue; | ||
1110 | } | ||
1111 | } | ||
1112 | else if (!fname) { | ||
1113 | fname = arg; | ||
1114 | continue; | ||
1115 | } | ||
1116 | usage(); | ||
1117 | } | ||
1118 | if (!fname) { | ||
1119 | usage(); | ||
1120 | } | ||
1121 | regex_init(use_real_mode); | 1029 | regex_init(use_real_mode); |
1122 | fp = fopen(fname, "r"); | ||
1123 | if (!fp) { | ||
1124 | die("Cannot open %s: %s\n", | ||
1125 | fname, strerror(errno)); | ||
1126 | } | ||
1127 | read_ehdr(fp); | 1030 | read_ehdr(fp); |
1128 | read_shdrs(fp); | 1031 | read_shdrs(fp); |
1129 | read_strtabs(fp); | 1032 | read_strtabs(fp); |
1130 | read_symtabs(fp); | 1033 | read_symtabs(fp); |
1131 | read_relocs(fp); | 1034 | read_relocs(fp); |
1132 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) | 1035 | if (ELF_BITS == 64) |
1133 | percpu_init(); | 1036 | percpu_init(); |
1134 | if (show_absolute_syms) { | 1037 | if (show_absolute_syms) { |
1135 | print_absolute_symbols(); | 1038 | print_absolute_symbols(); |
1136 | goto out; | 1039 | return; |
1137 | } | 1040 | } |
1138 | if (show_absolute_relocs) { | 1041 | if (show_absolute_relocs) { |
1139 | print_absolute_relocs(); | 1042 | print_absolute_relocs(); |
1140 | goto out; | 1043 | return; |
1141 | } | 1044 | } |
1142 | emit_relocs(as_text, use_real_mode); | 1045 | emit_relocs(as_text, use_real_mode); |
1143 | out: | ||
1144 | fclose(fp); | ||
1145 | return 0; | ||
1146 | } | 1046 | } |
diff --git a/arch/x86/tools/relocs.h b/arch/x86/tools/relocs.h new file mode 100644 index 000000000000..07cdb1eca4fa --- /dev/null +++ b/arch/x86/tools/relocs.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef RELOCS_H | ||
2 | #define RELOCS_H | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdarg.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <stdint.h> | ||
8 | #include <inttypes.h> | ||
9 | #include <string.h> | ||
10 | #include <errno.h> | ||
11 | #include <unistd.h> | ||
12 | #include <elf.h> | ||
13 | #include <byteswap.h> | ||
14 | #define USE_BSD | ||
15 | #include <endian.h> | ||
16 | #include <regex.h> | ||
17 | #include <tools/le_byteshift.h> | ||
18 | |||
19 | void die(char *fmt, ...); | ||
20 | |||
21 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
22 | |||
23 | enum symtype { | ||
24 | S_ABS, | ||
25 | S_REL, | ||
26 | S_SEG, | ||
27 | S_LIN, | ||
28 | S_NSYMTYPES | ||
29 | }; | ||
30 | |||
31 | void process_32(FILE *fp, int use_real_mode, int as_text, | ||
32 | int show_absolute_syms, int show_absolute_relocs); | ||
33 | void process_64(FILE *fp, int use_real_mode, int as_text, | ||
34 | int show_absolute_syms, int show_absolute_relocs); | ||
35 | |||
36 | #endif /* RELOCS_H */ | ||
diff --git a/arch/x86/tools/relocs_32.c b/arch/x86/tools/relocs_32.c new file mode 100644 index 000000000000..b2ade2bb4162 --- /dev/null +++ b/arch/x86/tools/relocs_32.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "relocs.h" | ||
2 | |||
3 | #define ELF_BITS 32 | ||
4 | |||
5 | #define ELF_MACHINE EM_386 | ||
6 | #define ELF_MACHINE_NAME "i386" | ||
7 | #define SHT_REL_TYPE SHT_REL | ||
8 | #define Elf_Rel ElfW(Rel) | ||
9 | |||
10 | #define ELF_CLASS ELFCLASS32 | ||
11 | #define ELF_R_SYM(val) ELF32_R_SYM(val) | ||
12 | #define ELF_R_TYPE(val) ELF32_R_TYPE(val) | ||
13 | #define ELF_ST_TYPE(o) ELF32_ST_TYPE(o) | ||
14 | #define ELF_ST_BIND(o) ELF32_ST_BIND(o) | ||
15 | #define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) | ||
16 | |||
17 | #include "relocs.c" | ||
diff --git a/arch/x86/tools/relocs_64.c b/arch/x86/tools/relocs_64.c new file mode 100644 index 000000000000..56b61b743c4c --- /dev/null +++ b/arch/x86/tools/relocs_64.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "relocs.h" | ||
2 | |||
3 | #define ELF_BITS 64 | ||
4 | |||
5 | #define ELF_MACHINE EM_X86_64 | ||
6 | #define ELF_MACHINE_NAME "x86_64" | ||
7 | #define SHT_REL_TYPE SHT_RELA | ||
8 | #define Elf_Rel Elf64_Rela | ||
9 | |||
10 | #define ELF_CLASS ELFCLASS64 | ||
11 | #define ELF_R_SYM(val) ELF64_R_SYM(val) | ||
12 | #define ELF_R_TYPE(val) ELF64_R_TYPE(val) | ||
13 | #define ELF_ST_TYPE(o) ELF64_ST_TYPE(o) | ||
14 | #define ELF_ST_BIND(o) ELF64_ST_BIND(o) | ||
15 | #define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o) | ||
16 | |||
17 | #include "relocs.c" | ||
diff --git a/arch/x86/tools/relocs_common.c b/arch/x86/tools/relocs_common.c new file mode 100644 index 000000000000..44d396823a53 --- /dev/null +++ b/arch/x86/tools/relocs_common.c | |||
@@ -0,0 +1,76 @@ | |||
1 | #include "relocs.h" | ||
2 | |||
3 | void die(char *fmt, ...) | ||
4 | { | ||
5 | va_list ap; | ||
6 | va_start(ap, fmt); | ||
7 | vfprintf(stderr, fmt, ap); | ||
8 | va_end(ap); | ||
9 | exit(1); | ||
10 | } | ||
11 | |||
12 | static void usage(void) | ||
13 | { | ||
14 | die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); | ||
15 | } | ||
16 | |||
17 | int main(int argc, char **argv) | ||
18 | { | ||
19 | int show_absolute_syms, show_absolute_relocs; | ||
20 | int as_text, use_real_mode; | ||
21 | const char *fname; | ||
22 | FILE *fp; | ||
23 | int i; | ||
24 | unsigned char e_ident[EI_NIDENT]; | ||
25 | |||
26 | show_absolute_syms = 0; | ||
27 | show_absolute_relocs = 0; | ||
28 | as_text = 0; | ||
29 | use_real_mode = 0; | ||
30 | fname = NULL; | ||
31 | for (i = 1; i < argc; i++) { | ||
32 | char *arg = argv[i]; | ||
33 | if (*arg == '-') { | ||
34 | if (strcmp(arg, "--abs-syms") == 0) { | ||
35 | show_absolute_syms = 1; | ||
36 | continue; | ||
37 | } | ||
38 | if (strcmp(arg, "--abs-relocs") == 0) { | ||
39 | show_absolute_relocs = 1; | ||
40 | continue; | ||
41 | } | ||
42 | if (strcmp(arg, "--text") == 0) { | ||
43 | as_text = 1; | ||
44 | continue; | ||
45 | } | ||
46 | if (strcmp(arg, "--realmode") == 0) { | ||
47 | use_real_mode = 1; | ||
48 | continue; | ||
49 | } | ||
50 | } | ||
51 | else if (!fname) { | ||
52 | fname = arg; | ||
53 | continue; | ||
54 | } | ||
55 | usage(); | ||
56 | } | ||
57 | if (!fname) { | ||
58 | usage(); | ||
59 | } | ||
60 | fp = fopen(fname, "r"); | ||
61 | if (!fp) { | ||
62 | die("Cannot open %s: %s\n", fname, strerror(errno)); | ||
63 | } | ||
64 | if (fread(&e_ident, 1, EI_NIDENT, fp) != EI_NIDENT) { | ||
65 | die("Cannot read %s: %s", fname, strerror(errno)); | ||
66 | } | ||
67 | rewind(fp); | ||
68 | if (e_ident[EI_CLASS] == ELFCLASS64) | ||
69 | process_64(fp, use_real_mode, as_text, | ||
70 | show_absolute_syms, show_absolute_relocs); | ||
71 | else | ||
72 | process_32(fp, use_real_mode, as_text, | ||
73 | show_absolute_syms, show_absolute_relocs); | ||
74 | fclose(fp); | ||
75 | return 0; | ||
76 | } | ||