|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|