x86, relocs: Generalize ELF structure names
authorKees Cook <keescook@chromium.org>
Fri, 12 Apr 2013 20:13:42 +0000 (13:13 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 16 Apr 2013 22:19:06 +0000 (15:19 -0700)
In preparation for making the reloc tool operate on 64-bit relocations,
generalize the structure names for easy recompilation via #defines.

Based on work by Neill Clift and Michael Davidson.

Signed-off-by: Kees Cook <keescook@chromium.org>
Link: http://lkml.kernel.org/r/1365797627-20874-2-git-send-email-keescook@chromium.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/x86/tools/relocs.c

index 79d67bd..fd28ef7 100644 (file)
 #include <regex.h>
 #include <tools/le_byteshift.h>
 
+#define ElfW(type)             _ElfW(ELF_BITS, type)
+#define _ElfW(bits, type)      __ElfW(bits, type)
+#define __ElfW(bits, type)     Elf##bits##_##type
+
+#define ELF_BITS               32
+#define ELF_MACHINE            EM_386
+#define ELF_MACHINE_NAME       "i386"
+#define SHT_REL_TYPE           SHT_REL
+
+#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)
+
+#define Elf_Rel                        ElfW(Rel)
+#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 Elf32_Ehdr ehdr;
+static Elf_Ehdr ehdr;
 static unsigned long reloc_count, reloc_idx;
 static unsigned long *relocs;
 static unsigned long reloc16_count, reloc16_idx;
 static unsigned long *relocs16;
 
 struct section {
-       Elf32_Shdr     shdr;
+       Elf_Shdr       shdr;
        struct section *link;
-       Elf32_Sym      *symtab;
-       Elf32_Rel      *reltab;
+       Elf_Sym        *symtab;
+       Elf_Rel        *reltab;
        char           *strtab;
 };
 static struct section *secs;
@@ -240,7 +262,7 @@ static const char *sec_name(unsigned shndx)
        return name;
 }
 
-static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
+static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
 {
        const char *name;
        name = "<noname>";
@@ -274,6 +296,12 @@ static uint32_t elf32_to_cpu(uint32_t val)
        return le32_to_cpu(val);
 }
 
+#define elf_half_to_cpu(x)     elf16_to_cpu(x)
+#define elf_word_to_cpu(x)     elf32_to_cpu(x)
+#define elf_addr_to_cpu(x)     elf32_to_cpu(x)
+#define elf_off_to_cpu(x)      elf32_to_cpu(x)
+#define elf_xword_to_cpu(x)    elf32_to_cpu(x)
+
 static void read_ehdr(FILE *fp)
 {
        if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
@@ -283,8 +311,8 @@ static void read_ehdr(FILE *fp)
        if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
                die("No ELF magic\n");
        }
-       if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
-               die("Not a 32 bit executable\n");
+       if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) {
+               die("Not a %d bit executable\n", ELF_BITS);
        }
        if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
                die("Not a LSB ELF executable\n");
@@ -293,36 +321,36 @@ static void read_ehdr(FILE *fp)
                die("Unknown ELF version\n");
        }
        /* Convert the fields to native endian */
-       ehdr.e_type      = elf16_to_cpu(ehdr.e_type);
-       ehdr.e_machine   = elf16_to_cpu(ehdr.e_machine);
-       ehdr.e_version   = elf32_to_cpu(ehdr.e_version);
-       ehdr.e_entry     = elf32_to_cpu(ehdr.e_entry);
-       ehdr.e_phoff     = elf32_to_cpu(ehdr.e_phoff);
-       ehdr.e_shoff     = elf32_to_cpu(ehdr.e_shoff);
-       ehdr.e_flags     = elf32_to_cpu(ehdr.e_flags);
-       ehdr.e_ehsize    = elf16_to_cpu(ehdr.e_ehsize);
-       ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
-       ehdr.e_phnum     = elf16_to_cpu(ehdr.e_phnum);
-       ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
-       ehdr.e_shnum     = elf16_to_cpu(ehdr.e_shnum);
-       ehdr.e_shstrndx  = elf16_to_cpu(ehdr.e_shstrndx);
+       ehdr.e_type      = elf_half_to_cpu(ehdr.e_type);
+       ehdr.e_machine   = elf_half_to_cpu(ehdr.e_machine);
+       ehdr.e_version   = elf_word_to_cpu(ehdr.e_version);
+       ehdr.e_entry     = elf_addr_to_cpu(ehdr.e_entry);
+       ehdr.e_phoff     = elf_off_to_cpu(ehdr.e_phoff);
+       ehdr.e_shoff     = elf_off_to_cpu(ehdr.e_shoff);
+       ehdr.e_flags     = elf_word_to_cpu(ehdr.e_flags);
+       ehdr.e_ehsize    = elf_half_to_cpu(ehdr.e_ehsize);
+       ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize);
+       ehdr.e_phnum     = elf_half_to_cpu(ehdr.e_phnum);
+       ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize);
+       ehdr.e_shnum     = elf_half_to_cpu(ehdr.e_shnum);
+       ehdr.e_shstrndx  = elf_half_to_cpu(ehdr.e_shstrndx);
 
        if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
                die("Unsupported ELF header type\n");
        }
-       if (ehdr.e_machine != EM_386) {
-               die("Not for x86\n");
+       if (ehdr.e_machine != ELF_MACHINE) {
+               die("Not for %s\n", ELF_MACHINE_NAME);
        }
        if (ehdr.e_version != EV_CURRENT) {
                die("Unknown ELF version\n");
        }
-       if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+       if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) {
                die("Bad Elf header size\n");
        }
-       if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
+       if (ehdr.e_phentsize != sizeof(Elf_Phdr)) {
                die("Bad program header entry\n");
        }
-       if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
+       if (ehdr.e_shentsize != sizeof(Elf_Shdr)) {
                die("Bad section header entry\n");
        }
        if (ehdr.e_shstrndx >= ehdr.e_shnum) {
@@ -333,7 +361,7 @@ static void read_ehdr(FILE *fp)
 static void read_shdrs(FILE *fp)
 {
        int i;
-       Elf32_Shdr shdr;
+       Elf_Shdr shdr;
 
        secs = calloc(ehdr.e_shnum, sizeof(struct section));
        if (!secs) {
@@ -349,16 +377,16 @@ static void read_shdrs(FILE *fp)
                if (fread(&shdr, sizeof shdr, 1, fp) != 1)
                        die("Cannot read ELF section headers %d/%d: %s\n",
                            i, ehdr.e_shnum, strerror(errno));
-               sec->shdr.sh_name      = elf32_to_cpu(shdr.sh_name);
-               sec->shdr.sh_type      = elf32_to_cpu(shdr.sh_type);
-               sec->shdr.sh_flags     = elf32_to_cpu(shdr.sh_flags);
-               sec->shdr.sh_addr      = elf32_to_cpu(shdr.sh_addr);
-               sec->shdr.sh_offset    = elf32_to_cpu(shdr.sh_offset);
-               sec->shdr.sh_size      = elf32_to_cpu(shdr.sh_size);
-               sec->shdr.sh_link      = elf32_to_cpu(shdr.sh_link);
-               sec->shdr.sh_info      = elf32_to_cpu(shdr.sh_info);
-               sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
-               sec->shdr.sh_entsize   = elf32_to_cpu(shdr.sh_entsize);
+               sec->shdr.sh_name      = elf_word_to_cpu(shdr.sh_name);
+               sec->shdr.sh_type      = elf_word_to_cpu(shdr.sh_type);
+               sec->shdr.sh_flags     = elf_xword_to_cpu(shdr.sh_flags);
+               sec->shdr.sh_addr      = elf_addr_to_cpu(shdr.sh_addr);
+               sec->shdr.sh_offset    = elf_off_to_cpu(shdr.sh_offset);
+               sec->shdr.sh_size      = elf_xword_to_cpu(shdr.sh_size);
+               sec->shdr.sh_link      = elf_word_to_cpu(shdr.sh_link);
+               sec->shdr.sh_info      = elf_word_to_cpu(shdr.sh_info);
+               sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign);
+               sec->shdr.sh_entsize   = elf_xword_to_cpu(shdr.sh_entsize);
                if (sec->shdr.sh_link < ehdr.e_shnum)
                        sec->link = &secs[sec->shdr.sh_link];
        }
@@ -412,12 +440,12 @@ static void read_symtabs(FILE *fp)
                        die("Cannot read symbol table: %s\n",
                                strerror(errno));
                }
-               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
-                       Elf32_Sym *sym = &sec->symtab[j];
-                       sym->st_name  = elf32_to_cpu(sym->st_name);
-                       sym->st_value = elf32_to_cpu(sym->st_value);
-                       sym->st_size  = elf32_to_cpu(sym->st_size);
-                       sym->st_shndx = elf16_to_cpu(sym->st_shndx);
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
+                       Elf_Sym *sym = &sec->symtab[j];
+                       sym->st_name  = elf_word_to_cpu(sym->st_name);
+                       sym->st_value = elf_addr_to_cpu(sym->st_value);
+                       sym->st_size  = elf_xword_to_cpu(sym->st_size);
+                       sym->st_shndx = elf_half_to_cpu(sym->st_shndx);
                }
        }
 }
@@ -428,7 +456,7 @@ static void read_relocs(FILE *fp)
        int i,j;
        for (i = 0; i < ehdr.e_shnum; i++) {
                struct section *sec = &secs[i];
-               if (sec->shdr.sh_type != SHT_REL) {
+               if (sec->shdr.sh_type != SHT_REL_TYPE) {
                        continue;
                }
                sec->reltab = malloc(sec->shdr.sh_size);
@@ -445,10 +473,10 @@ static void read_relocs(FILE *fp)
                        die("Cannot read symbol table: %s\n",
                                strerror(errno));
                }
-               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
-                       Elf32_Rel *rel = &sec->reltab[j];
-                       rel->r_offset = elf32_to_cpu(rel->r_offset);
-                       rel->r_info   = elf32_to_cpu(rel->r_info);
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+                       Elf_Rel *rel = &sec->reltab[j];
+                       rel->r_offset = elf_addr_to_cpu(rel->r_offset);
+                       rel->r_info   = elf_xword_to_cpu(rel->r_info);
                }
        }
 }
@@ -468,8 +496,8 @@ static void print_absolute_symbols(void)
                        continue;
                }
                sym_strtab = sec->link->strtab;
-               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
-                       Elf32_Sym *sym;
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
+                       Elf_Sym *sym;
                        const char *name;
                        sym = &sec->symtab[j];
                        name = sym_name(sym_strtab, sym);
@@ -478,9 +506,9 @@ static void print_absolute_symbols(void)
                        }
                        printf("%5d %08x %5d %10s %10s %12s %s\n",
                                j, sym->st_value, sym->st_size,
-                               sym_type(ELF32_ST_TYPE(sym->st_info)),
-                               sym_bind(ELF32_ST_BIND(sym->st_info)),
-                               sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
+                               sym_type(ELF_ST_TYPE(sym->st_info)),
+                               sym_bind(ELF_ST_BIND(sym->st_info)),
+                               sym_visibility(ELF_ST_VISIBILITY(sym->st_other)),
                                name);
                }
        }
@@ -495,9 +523,9 @@ static void print_absolute_relocs(void)
                struct section *sec = &secs[i];
                struct section *sec_applies, *sec_symtab;
                char *sym_strtab;
-               Elf32_Sym *sh_symtab;
+               Elf_Sym *sh_symtab;
                int j;
-               if (sec->shdr.sh_type != SHT_REL) {
+               if (sec->shdr.sh_type != SHT_REL_TYPE) {
                        continue;
                }
                sec_symtab  = sec->link;
@@ -507,12 +535,12 @@ static void print_absolute_relocs(void)
                }
                sh_symtab  = sec_symtab->symtab;
                sym_strtab = sec_symtab->link->strtab;
-               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
-                       Elf32_Rel *rel;
-                       Elf32_Sym *sym;
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+                       Elf_Rel *rel;
+                       Elf_Sym *sym;
                        const char *name;
                        rel = &sec->reltab[j];
-                       sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+                       sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
                        name = sym_name(sym_strtab, sym);
                        if (sym->st_shndx != SHN_ABS) {
                                continue;
@@ -545,7 +573,7 @@ static void print_absolute_relocs(void)
                        printf("%08x %08x %10s %08x  %s\n",
                                rel->r_offset,
                                rel->r_info,
-                               rel_type(ELF32_R_TYPE(rel->r_info)),
+                               rel_type(ELF_R_TYPE(rel->r_info)),
                                sym->st_value,
                                name);
                }
@@ -555,19 +583,19 @@ static void print_absolute_relocs(void)
                printf("\n");
 }
 
-static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
+static void walk_relocs(void (*visit)(Elf_Rel *rel, Elf_Sym *sym),
                        int use_real_mode)
 {
        int i;
        /* Walk through the relocations */
        for (i = 0; i < ehdr.e_shnum; i++) {
                char *sym_strtab;
-               Elf32_Sym *sh_symtab;
+               Elf_Sym *sh_symtab;
                struct section *sec_applies, *sec_symtab;
                int j;
                struct section *sec = &secs[i];
 
-               if (sec->shdr.sh_type != SHT_REL) {
+               if (sec->shdr.sh_type != SHT_REL_TYPE) {
                        continue;
                }
                sec_symtab  = sec->link;
@@ -577,16 +605,16 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
                }
                sh_symtab = sec_symtab->symtab;
                sym_strtab = sec_symtab->link->strtab;
-               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
-                       Elf32_Rel *rel;
-                       Elf32_Sym *sym;
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+                       Elf_Rel *rel;
+                       Elf_Sym *sym;
                        unsigned r_type;
                        const char *symname;
                        int shn_abs;
 
                        rel = &sec->reltab[j];
-                       sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
-                       r_type = ELF32_R_TYPE(rel->r_info);
+                       sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
+                       r_type = ELF_R_TYPE(rel->r_info);
 
                        shn_abs = sym->st_shndx == SHN_ABS;
 
@@ -647,18 +675,18 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
        }
 }
 
-static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+static void count_reloc(Elf_Rel *rel, Elf_Sym *sym)
 {
-       if (ELF32_R_TYPE(rel->r_info) == R_386_16)
+       if (ELF_R_TYPE(rel->r_info) == R_386_16)
                reloc16_count++;
        else
                reloc_count++;
 }
 
-static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+static void collect_reloc(Elf_Rel *rel, Elf_Sym *sym)
 {
        /* Remember the address that needs to be adjusted. */
-       if (ELF32_R_TYPE(rel->r_info) == R_386_16)
+       if (ELF_R_TYPE(rel->r_info) == R_386_16)
                relocs16[reloc16_idx++] = rel->r_offset;
        else
                relocs[reloc_idx++] = rel->r_offset;