1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #include <libelf.h>
  25 #include <stdio.h>
  26 #include <stdlib.h>
  27 
  28 /**
  29  * TODO: This is an intial and crude attempt to access structure
  30  * fields of some ELF structrures. Need to figure out a way to access the
  31  * given field of a given structure instead of writing one shim function
  32  * per access of each of the structure field.
  33  **/
  34 
  35 #define STRINGIFYHELPER(x) #x
  36 #define STRINGIFY(x) STRINGIFYHELPER(x)
  37 #define FUNC_NAME(S, F) set_ ## S ## _ ## F
  38 #define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr)
  39 #define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr)
  40 #define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr)
  41 #define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F
  42 #define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F
  43 #define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F
  44 
  45 /*
  46    Example:
  47    SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
  48    expands to
  49    set_Ehdr_e_machine(int elfclass, void * strPtr, int val) {
  50 }
  51 */
  52 
  53 #define SET_TYPE_BASED_FIELD(S, F, T)                               \
  54     void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) {   \
  55        if (elfclass == ELFCLASS32)  {                               \
  56            ACCESS_FIELD32(S, F) = val;                    \
  57        } else if (elfclass == ELFCLASS64) {               \
  58            ACCESS_FIELD64(S, F) = val;                    \
  59        } else {                                           \
  60            printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \
  61     }  \
  62     return; \
  63 }
  64 
  65 /*
  66    Example:
  67    SET_FIELD(Ehdr, e_machine, int)
  68    expands to
  69    set_Ehdr_e_machine(void * strPtr, int val) {
  70 }
  71 */
  72 
  73 #define SET_FIELD(S, F, T)                               \
  74     void FUNC_NAME(S, F)(void * structPtr, T val) {      \
  75        ACCESS_FIELD(S, F) = val;                         \
  76        return; \
  77 }
  78 
  79 int size_of_Sym(int elfclass) {
  80     if (elfclass == ELFCLASS32)  {
  81         return sizeof(Elf32_Sym);
  82     } else if (elfclass == ELFCLASS64) {
  83         return sizeof(Elf64_Sym);
  84     } else {
  85         printf("Unknown ELF Class %d provided\n", elfclass);
  86     }
  87     return -1;
  88 }
  89 
  90 int size_of_Rela(int elfclass) {
  91     if (elfclass == ELFCLASS32)  {
  92         return sizeof(Elf32_Rela);
  93     } else if (elfclass == ELFCLASS64) {
  94         return sizeof(Elf64_Rela);
  95     } else {
  96         printf("Unknown ELF Class %d provided\n", elfclass);
  97     }
  98     return -1;
  99 }
 100 
 101 int size_of_Rel(int elfclass) {
 102     if (elfclass == ELFCLASS32)  {
 103         return sizeof(Elf32_Rel);
 104     } else if (elfclass == ELFCLASS64) {
 105         return sizeof(Elf64_Rel);
 106     } else {
 107         printf("Unknown ELF Class %d provided\n", elfclass);
 108     }
 109     return -1;
 110 }
 111 
 112 /* ELF Header field access */
 113 
 114 void ehdr_set_data_encoding(void * ehdr, int val)  {
 115     ((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val;
 116     return;
 117 }
 118 
 119 SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
 120 SET_TYPE_BASED_FIELD(Ehdr, e_type, int)
 121 SET_TYPE_BASED_FIELD(Ehdr, e_version, int)
 122 SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int)
 123 
 124 /* Data descriptor field access */
 125 SET_FIELD(Data, d_align, int)
 126 SET_FIELD(Data, d_off, int)
 127 SET_FIELD(Data, d_buf, void*)
 128 SET_FIELD(Data, d_type, int)
 129 SET_FIELD(Data, d_size, int)
 130 SET_FIELD(Data, d_version, int)
 131 
 132 /* Section Header Access functions */
 133 SET_TYPE_BASED_FIELD(Shdr, sh_name, int)
 134 SET_TYPE_BASED_FIELD(Shdr, sh_type, int)
 135 SET_TYPE_BASED_FIELD(Shdr, sh_flags, int)
 136 SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int)
 137 SET_TYPE_BASED_FIELD(Shdr, sh_link, int)
 138 SET_TYPE_BASED_FIELD(Shdr, sh_info, int)
 139 
 140 /* Set the Program Header to be of PH_PHDR type and initialize other
 141    related fields of the program header.
 142 */
 143 void phdr_set_type_self(int elfclass, void * ehdr, void * phdr)  {
 144     if (elfclass == ELFCLASS32) {
 145         Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr;
 146         Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr;
 147         phdr32->p_type = PT_PHDR;
 148         phdr32->p_offset = ehdr32->e_phoff;
 149         phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT);
 150     } else if (elfclass == ELFCLASS64) {
 151         Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr;
 152         Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr;
 153         phdr64->p_type = PT_PHDR;
 154         phdr64->p_offset = ehdr64->e_phoff;
 155         phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT);
 156     } else {
 157         printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass);
 158     }
 159     return;
 160 }
 161 
 162 /*
 163   Create symbol table entry with given type and binding
 164 */
 165 void * create_sym_entry(int elfclass, int index, int type, int bind,
 166                         int shndx, int size, int value) {
 167   void * symentry = NULL;
 168     if (elfclass == ELFCLASS32) {
 169       Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym));
 170       sym32->st_name = index;
 171       sym32->st_value = value;
 172       sym32->st_size = size;
 173       sym32->st_info = ELF32_ST_INFO(bind, type);
 174       sym32->st_other = 0;  // TODO: Add an argument to get this value ??
 175       sym32->st_shndx = shndx;
 176       symentry = sym32;
 177     } else if (elfclass == ELFCLASS64) {
 178       Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym));
 179       sym64->st_name = index;
 180       sym64->st_value = value;
 181       sym64->st_size = size;
 182       sym64->st_info = ELF64_ST_INFO(bind, type);
 183       sym64->st_other = 0;  // TODO: Add an argument to get this value ??
 184       sym64->st_shndx = shndx;
 185       symentry = sym64;
 186     } else {
 187         printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass);
 188     }
 189     return (void *) symentry;
 190 }
 191 
 192 // Create a reloc (or reloca entry if argument reloca is non-zero)
 193 void * create_reloc_entry(int elfclass, int roffset, int symtabIdx,
 194                           int relocType, int raddend, int reloca) {
 195   void * relocentry = NULL;
 196   if (elfclass == ELFCLASS32) {
 197     if (reloca) {
 198       Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela));
 199       rela32->r_offset = roffset;
 200       rela32->r_info = ELF32_R_INFO(symtabIdx, relocType);
 201       rela32->r_addend = raddend;
 202       relocentry = rela32;
 203     } else {
 204       Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel));
 205       rel32->r_offset = roffset;
 206       rel32->r_info = ELF32_R_INFO(symtabIdx, relocType);
 207       relocentry = rel32;
 208     }
 209   } else if (elfclass == ELFCLASS64) {
 210     if (reloca) {
 211       Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela));
 212       rela64->r_offset = roffset;
 213       rela64->r_info = ELF64_R_INFO(symtabIdx, relocType);
 214       rela64->r_addend = raddend;
 215       relocentry = rela64;
 216     } else {
 217       Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel));
 218       rel64->r_offset = roffset;
 219       rel64->r_info = ELF64_R_INFO(symtabIdx, relocType);
 220       relocentry = rel64;
 221     }
 222   } else {
 223     printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass);
 224   }
 225   return (void *) relocentry;
 226 }