aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/tools
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2013-04-16 19:02:58 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-04-16 19:02:58 -0400
commitc889ba801dc3b3a0155fa77d567f2c3a6097de1c (patch)
tree257878e1eb565fc9765dd8fed20815f7781d116a /arch/x86/tools
parent17c961f7702ff6037b66bb2e5f3ddd58de4ce7e5 (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
Diffstat (limited to 'arch/x86/tools')
-rw-r--r--arch/x86/tools/.gitignore3
-rw-r--r--arch/x86/tools/Makefile21
-rw-r--r--arch/x86/tools/relocs.c162
-rw-r--r--arch/x86/tools/relocs.h36
-rw-r--r--arch/x86/tools/relocs_32.c17
-rw-r--r--arch/x86/tools/relocs_64.c17
-rw-r--r--arch/x86/tools/relocs_common.c76
7 files changed, 181 insertions, 151 deletions
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 @@
1relocs_32* relocs
2relocs_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
40HOSTCFLAGS_relocs_32.o += -DELF_BITS=32
41HOSTCFLAGS_relocs_64.o += -DELF_BITS=64
42
43quiet_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
49HOST_EXTRACFLAGS += -I$(srctree)/tools/include 40HOST_EXTRACFLAGS += -I$(srctree)/tools/include
50hostprogs-y += relocs_$(BITS) 41hostprogs-y += relocs
51relocs_binaries = relocs_$(BITS) 42relocs-objs := relocs_32.o relocs_64.o relocs_common.o
52ifeq ($(CONFIG_64BIT),y) 43relocs: $(obj)/relocs
53 hostprogs-y += relocs_32
54 relocs_binaries += relocs_32
55endif
56relocs: $(relocs_binaries)
57relocs_32: $(obj)/relocs_32
58relocs_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
58static void die(char *fmt, ...);
59
60#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
61static Elf_Ehdr ehdr; 13static Elf_Ehdr ehdr;
62 14
63struct relocs { 15struct relocs {
@@ -79,14 +31,6 @@ struct section {
79}; 31};
80static struct section *secs; 32static struct section *secs;
81 33
82enum symtype {
83 S_ABS,
84 S_REL,
85 S_SEG,
86 S_LIN,
87 S_NSYMTYPES
88};
89
90static const char * const sym_regex_kernel[S_NSYMTYPES] = { 34static 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
192static 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
201static const char *sym_type(unsigned type) 136static 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
384static uint64_t elf64_to_cpu(uint64_t val) 319static 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
801static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, 739static 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
873static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, 812static 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
987static int cmp_relocs(const void *va, const void *vb) 928static 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
1074static 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
1079int main(int argc, char **argv) 1026void 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);
1143out:
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
19void die(char *fmt, ...);
20
21#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
22
23enum symtype {
24 S_ABS,
25 S_REL,
26 S_SEG,
27 S_LIN,
28 S_NSYMTYPES
29};
30
31void process_32(FILE *fp, int use_real_mode, int as_text,
32 int show_absolute_syms, int show_absolute_relocs);
33void 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
3void 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
12static void usage(void)
13{
14 die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n");
15}
16
17int 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}