diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-17 03:02:58 +0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-17 03:02:58 +0400 |
commit | c889ba801dc3b3a0155fa77d567f2c3a6097de1c (patch) | |
tree | 257878e1eb565fc9765dd8fed20815f7781d116a /arch/x86/tools/relocs.c | |
parent | 17c961f7702ff6037b66bb2e5f3ddd58de4ce7e5 (diff) | |
download | linux-c889ba801dc3b3a0155fa77d567f2c3a6097de1c.tar.xz |
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/relocs.c')
-rw-r--r-- | arch/x86/tools/relocs.c | 162 |
1 files changed, 31 insertions, 131 deletions
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 @@ -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdint.h> -#include <inttypes.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <elf.h> -#include <byteswap.h> -#define USE_BSD -#include <endian.h> -#include <regex.h> -#include <tools/le_byteshift.h> +/* This is included from relocs_32/64.c */ #define ElfW(type) _ElfW(ELF_BITS, type) #define _ElfW(bits, type) __ElfW(bits, type) #define __ElfW(bits, type) Elf##bits##_##type -#ifndef ELF_BITS -#define ELF_BITS 32 -#endif - -#if (ELF_BITS == 64) -#define ELF_MACHINE EM_X86_64 -#define ELF_MACHINE_NAME "x86_64" -#define SHT_REL_TYPE SHT_RELA -#define Elf_Rel Elf64_Rela -#else -#define ELF_MACHINE EM_386 -#define ELF_MACHINE_NAME "i386" -#define SHT_REL_TYPE SHT_REL -#define Elf_Rel ElfW(Rel) -#endif - -#if (ELF_BITS == 64) -#define ELF_CLASS ELFCLASS64 -#define ELF_R_SYM(val) ELF64_R_SYM(val) -#define ELF_R_TYPE(val) ELF64_R_TYPE(val) -#define ELF_ST_TYPE(o) ELF64_ST_TYPE(o) -#define ELF_ST_BIND(o) ELF64_ST_BIND(o) -#define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o) -#else -#define ELF_CLASS ELFCLASS32 -#define ELF_R_SYM(val) ELF32_R_SYM(val) -#define ELF_R_TYPE(val) ELF32_R_TYPE(val) -#define ELF_ST_TYPE(o) ELF32_ST_TYPE(o) -#define ELF_ST_BIND(o) ELF32_ST_BIND(o) -#define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) -#endif - #define Elf_Addr ElfW(Addr) #define Elf_Ehdr ElfW(Ehdr) #define Elf_Phdr ElfW(Phdr) #define Elf_Shdr ElfW(Shdr) #define Elf_Sym ElfW(Sym) -static void die(char *fmt, ...); - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static Elf_Ehdr ehdr; struct relocs { @@ -79,14 +31,6 @@ struct section { }; static struct section *secs; -enum symtype { - S_ABS, - S_REL, - S_SEG, - S_LIN, - S_NSYMTYPES -}; - static const char * const sym_regex_kernel[S_NSYMTYPES] = { /* * Following symbols have been audited. There values are constant and do @@ -98,7 +42,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { "^(xen_irq_disable_direct_reloc$|" "xen_save_fl_direct_reloc$|" "VDSO|" -#if (ELF_BITS == 64) +#if ELF_BITS == 64 "__vvar_page|" #endif "__crc_)", @@ -124,7 +68,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { "__end_rodata|" "__initramfs_start|" "(jiffies|jiffies_64)|" -#if (ELF_BITS == 64) +#if ELF_BITS == 64 "__per_cpu_load|" "init_per_cpu__.*|" "__end_rodata_hpage_align|" @@ -189,15 +133,6 @@ static void regex_init(int use_real_mode) } } -static void die(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(1); -} - static const char *sym_type(unsigned type) { static const char *type_name[] = { @@ -255,7 +190,7 @@ static const char *rel_type(unsigned type) { static const char *type_name[] = { #define REL_TYPE(X) [X] = #X -#if (ELF_BITS == 64) +#if ELF_BITS == 64 REL_TYPE(R_X86_64_NONE), REL_TYPE(R_X86_64_64), REL_TYPE(R_X86_64_PC32), @@ -380,7 +315,7 @@ static uint32_t elf32_to_cpu(uint32_t val) #define elf_half_to_cpu(x) elf16_to_cpu(x) #define elf_word_to_cpu(x) elf32_to_cpu(x) -#if (ELF_BITS == 64) +#if ELF_BITS == 64 static uint64_t elf64_to_cpu(uint64_t val) { return le64_to_cpu(val); @@ -582,7 +517,7 @@ static void print_absolute_symbols(void) int i; const char *format; - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) + if (ELF_BITS == 64) format = "%5d %016"PRIx64" %5"PRId64" %10s %10s %12s %s\n"; else format = "%5d %08"PRIx32" %5"PRId32" %10s %10s %12s %s\n"; @@ -622,7 +557,7 @@ static void print_absolute_relocs(void) int i, printed = 0; const char *format; - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) + if (ELF_BITS == 64) format = "%016"PRIx64" %016"PRIx64" %10s %016"PRIx64" %s\n"; else format = "%08"PRIx32" %08"PRIx32" %10s %08"PRIx32" %s\n"; @@ -785,6 +720,8 @@ static void percpu_init(void) } } +#if ELF_BITS == 64 + /* * Check to see if a symbol lies in the .data..percpu section. * 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) strcmp(symname, "__init_begin"); } + static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, const char *symname) { @@ -869,6 +807,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, return 0; } +#else static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname) @@ -984,6 +923,8 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, return 0; } +#endif + static int cmp_relocs(const void *va, const void *vb) { const uint32_t *a, *b; @@ -1016,12 +957,17 @@ static void emit_relocs(int as_text, int use_real_mode) int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname); - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) +#if ELF_BITS == 64 + if (!use_real_mode) do_reloc = do_reloc64; - else if (!use_real_mode) + else + die("--realmode not valid for a 64-bit ELF file"); +#else + if (!use_real_mode) do_reloc = do_reloc32; else do_reloc = do_reloc_real; +#endif /* Collect up the relocations */ walk_relocs(do_reloc); @@ -1053,7 +999,7 @@ static void emit_relocs(int as_text, int use_real_mode) for (i = 0; i < relocs32.count; i++) write_reloc(relocs32.offset[i], stdout); } else { - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { + if (ELF_BITS == 64) { /* Print a stop */ write_reloc(0, stdout); @@ -1071,76 +1017,30 @@ static void emit_relocs(int as_text, int use_real_mode) } } -static void usage(void) -{ - die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); -} +#if ELF_BITS == 64 +# define process process_64 +#else +# define process process_32 +#endif -int main(int argc, char **argv) +void process(FILE *fp, int use_real_mode, int as_text, + int show_absolute_syms, int show_absolute_relocs) { - int show_absolute_syms, show_absolute_relocs; - int as_text, use_real_mode; - const char *fname; - FILE *fp; - int i; - - show_absolute_syms = 0; - show_absolute_relocs = 0; - as_text = 0; - use_real_mode = 0; - fname = NULL; - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - if (*arg == '-') { - if (strcmp(arg, "--abs-syms") == 0) { - show_absolute_syms = 1; - continue; - } - if (strcmp(arg, "--abs-relocs") == 0) { - show_absolute_relocs = 1; - continue; - } - if (strcmp(arg, "--text") == 0) { - as_text = 1; - continue; - } - if (strcmp(arg, "--realmode") == 0) { - use_real_mode = 1; - continue; - } - } - else if (!fname) { - fname = arg; - continue; - } - usage(); - } - if (!fname) { - usage(); - } regex_init(use_real_mode); - fp = fopen(fname, "r"); - if (!fp) { - die("Cannot open %s: %s\n", - fname, strerror(errno)); - } read_ehdr(fp); read_shdrs(fp); read_strtabs(fp); read_symtabs(fp); read_relocs(fp); - if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) + if (ELF_BITS == 64) percpu_init(); if (show_absolute_syms) { print_absolute_symbols(); - goto out; + return; } if (show_absolute_relocs) { print_absolute_relocs(); - goto out; + return; } emit_relocs(as_text, use_real_mode); -out: - fclose(fp); - return 0; } |