Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+183 -153
+1 -1
arch/x86/boot/compressed/Makefile
··· 44 44 45 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 48 quiet_cmd_relocs = RELOCS $@ 49 49 cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< 50 50 $(obj)/vmlinux.relocs: vmlinux FORCE
+1 -1
arch/x86/realmode/rm/Makefile
··· 56 56 $(call if_changed,objcopy) 57 57 58 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 61 targets += realmode.relocs 62 62 $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
+1 -2
arch/x86/tools/.gitignore
··· 1 - relocs_32* 2 - relocs_64* 1 + relocs
+3 -18
arch/x86/tools/Makefile
··· 37 37 38 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 40 HOST_EXTRACFLAGS += -I$(srctree)/tools/include 50 - hostprogs-y += relocs_$(BITS) 51 - relocs_binaries = relocs_$(BITS) 52 - ifeq ($(CONFIG_64BIT),y) 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 41 + hostprogs-y += relocs 42 + relocs-objs := relocs_32.o relocs_64.o relocs_common.o 43 + relocs: $(obj)/relocs
+31 -131
arch/x86/tools/relocs.c
··· 1 - #include <stdio.h> 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> 1 + /* This is included from relocs_32/64.c */ 15 2 16 3 #define ElfW(type) _ElfW(ELF_BITS, type) 17 4 #define _ElfW(bits, type) __ElfW(bits, type) 18 5 #define __ElfW(bits, type) Elf##bits##_##type 19 - 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 6 52 7 #define Elf_Addr ElfW(Addr) 53 8 #define Elf_Ehdr ElfW(Ehdr) ··· 10 55 #define Elf_Shdr ElfW(Shdr) 11 56 #define Elf_Sym ElfW(Sym) 12 57 13 - static void die(char *fmt, ...); 14 - 15 - #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 16 58 static Elf_Ehdr ehdr; 17 59 18 60 struct relocs { ··· 31 79 }; 32 80 static struct section *secs; 33 81 34 - enum symtype { 35 - S_ABS, 36 - S_REL, 37 - S_SEG, 38 - S_LIN, 39 - S_NSYMTYPES 40 - }; 41 - 42 82 static const char * const sym_regex_kernel[S_NSYMTYPES] = { 43 83 /* 44 84 * Following symbols have been audited. There values are constant and do ··· 42 98 "^(xen_irq_disable_direct_reloc$|" 43 99 "xen_save_fl_direct_reloc$|" 44 100 "VDSO|" 45 - #if (ELF_BITS == 64) 101 + #if ELF_BITS == 64 46 102 "__vvar_page|" 47 103 #endif 48 104 "__crc_)", ··· 68 124 "__end_rodata|" 69 125 "__initramfs_start|" 70 126 "(jiffies|jiffies_64)|" 71 - #if (ELF_BITS == 64) 127 + #if ELF_BITS == 64 72 128 "__per_cpu_load|" 73 129 "init_per_cpu__.*|" 74 130 "__end_rodata_hpage_align|" ··· 133 189 } 134 190 } 135 191 136 - static void die(char *fmt, ...) 137 - { 138 - va_list ap; 139 - va_start(ap, fmt); 140 - vfprintf(stderr, fmt, ap); 141 - va_end(ap); 142 - exit(1); 143 - } 144 - 145 192 static const char *sym_type(unsigned type) 146 193 { 147 194 static const char *type_name[] = { ··· 190 255 { 191 256 static const char *type_name[] = { 192 257 #define REL_TYPE(X) [X] = #X 193 - #if (ELF_BITS == 64) 258 + #if ELF_BITS == 64 194 259 REL_TYPE(R_X86_64_NONE), 195 260 REL_TYPE(R_X86_64_64), 196 261 REL_TYPE(R_X86_64_PC32), ··· 315 380 #define elf_half_to_cpu(x) elf16_to_cpu(x) 316 381 #define elf_word_to_cpu(x) elf32_to_cpu(x) 317 382 318 - #if (ELF_BITS == 64) 383 + #if ELF_BITS == 64 319 384 static uint64_t elf64_to_cpu(uint64_t val) 320 385 { 321 386 return le64_to_cpu(val); ··· 517 582 int i; 518 583 const char *format; 519 584 520 - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 585 + if (ELF_BITS == 64) 521 586 format = "%5d %016"PRIx64" %5"PRId64" %10s %10s %12s %s\n"; 522 587 else 523 588 format = "%5d %08"PRIx32" %5"PRId32" %10s %10s %12s %s\n"; ··· 557 622 int i, printed = 0; 558 623 const char *format; 559 624 560 - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 625 + if (ELF_BITS == 64) 561 626 format = "%016"PRIx64" %016"PRIx64" %10s %016"PRIx64" %s\n"; 562 627 else 563 628 format = "%08"PRIx32" %08"PRIx32" %10s %08"PRIx32" %s\n"; ··· 720 785 } 721 786 } 722 787 788 + #if ELF_BITS == 64 789 + 723 790 /* 724 791 * Check to see if a symbol lies in the .data..percpu section. 725 792 * For some as yet not understood reason the "__init_begin" ··· 734 797 return (sym->st_shndx == per_cpu_shndx) && 735 798 strcmp(symname, "__init_begin"); 736 799 } 800 + 737 801 738 802 static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, 739 803 const char *symname) ··· 807 869 return 0; 808 870 } 809 871 872 + #else 810 873 811 874 static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, 812 875 const char *symname) ··· 923 984 return 0; 924 985 } 925 986 987 + #endif 988 + 926 989 static int cmp_relocs(const void *va, const void *vb) 927 990 { 928 991 const uint32_t *a, *b; ··· 957 1016 int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, 958 1017 const char *symname); 959 1018 960 - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 1019 + #if ELF_BITS == 64 1020 + if (!use_real_mode) 961 1021 do_reloc = do_reloc64; 962 - else if (!use_real_mode) 1022 + else 1023 + die("--realmode not valid for a 64-bit ELF file"); 1024 + #else 1025 + if (!use_real_mode) 963 1026 do_reloc = do_reloc32; 964 1027 else 965 1028 do_reloc = do_reloc_real; 1029 + #endif 966 1030 967 1031 /* Collect up the relocations */ 968 1032 walk_relocs(do_reloc); ··· 999 1053 for (i = 0; i < relocs32.count; i++) 1000 1054 write_reloc(relocs32.offset[i], stdout); 1001 1055 } else { 1002 - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 1056 + if (ELF_BITS == 64) { 1003 1057 /* Print a stop */ 1004 1058 write_reloc(0, stdout); 1005 1059 ··· 1017 1071 } 1018 1072 } 1019 1073 1020 - static void usage(void) 1021 - { 1022 - die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); 1023 - } 1074 + #if ELF_BITS == 64 1075 + # define process process_64 1076 + #else 1077 + # define process process_32 1078 + #endif 1024 1079 1025 - int main(int argc, char **argv) 1080 + void process(FILE *fp, int use_real_mode, int as_text, 1081 + int show_absolute_syms, int show_absolute_relocs) 1026 1082 { 1027 - int show_absolute_syms, show_absolute_relocs; 1028 - int as_text, use_real_mode; 1029 - const char *fname; 1030 - FILE *fp; 1031 - int i; 1032 - 1033 - show_absolute_syms = 0; 1034 - show_absolute_relocs = 0; 1035 - as_text = 0; 1036 - use_real_mode = 0; 1037 - fname = NULL; 1038 - for (i = 1; i < argc; i++) { 1039 - char *arg = argv[i]; 1040 - if (*arg == '-') { 1041 - if (strcmp(arg, "--abs-syms") == 0) { 1042 - show_absolute_syms = 1; 1043 - continue; 1044 - } 1045 - if (strcmp(arg, "--abs-relocs") == 0) { 1046 - show_absolute_relocs = 1; 1047 - continue; 1048 - } 1049 - if (strcmp(arg, "--text") == 0) { 1050 - as_text = 1; 1051 - continue; 1052 - } 1053 - if (strcmp(arg, "--realmode") == 0) { 1054 - use_real_mode = 1; 1055 - continue; 1056 - } 1057 - } 1058 - else if (!fname) { 1059 - fname = arg; 1060 - continue; 1061 - } 1062 - usage(); 1063 - } 1064 - if (!fname) { 1065 - usage(); 1066 - } 1067 1083 regex_init(use_real_mode); 1068 - fp = fopen(fname, "r"); 1069 - if (!fp) { 1070 - die("Cannot open %s: %s\n", 1071 - fname, strerror(errno)); 1072 - } 1073 1084 read_ehdr(fp); 1074 1085 read_shdrs(fp); 1075 1086 read_strtabs(fp); 1076 1087 read_symtabs(fp); 1077 1088 read_relocs(fp); 1078 - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 1089 + if (ELF_BITS == 64) 1079 1090 percpu_init(); 1080 1091 if (show_absolute_syms) { 1081 1092 print_absolute_symbols(); 1082 - goto out; 1093 + return; 1083 1094 } 1084 1095 if (show_absolute_relocs) { 1085 1096 print_absolute_relocs(); 1086 - goto out; 1097 + return; 1087 1098 } 1088 1099 emit_relocs(as_text, use_real_mode); 1089 - out: 1090 - fclose(fp); 1091 - return 0; 1092 1100 }
+36
arch/x86/tools/relocs.h
··· 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 */
+17
arch/x86/tools/relocs_32.c
··· 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"
+17
arch/x86/tools/relocs_64.c
··· 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"
+76
arch/x86/tools/relocs_common.c
··· 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 + }