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