1 /*
2  * Copyright (c) 2015 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #include <inttypes.h>
11 
12 /* elf defines */
13 #define ELF_MAGIC "\x7f""ELF"
14 
15 /* e_ident */
16 #define EI_MAG0 0
17 #define EI_MAG1 1
18 #define EI_MAG2 2
19 #define EI_MAG3 3
20 #define EI_CLASS 4
21 #define EI_DATA 5
22 #define EI_VERSION 6
23 #define EI_OSABI 7
24 #define EI_ABIVERSION 8
25 #define EI_PAD 9
26 #define EI_NIDENT 16
27 
28 /* e_machine */
29 #define EM_NONE     0
30 #define EM_SPARC    2
31 #define EM_386      3
32 #define EM_68K      4
33 #define EM_MIPS     8
34 #define EM_SPARC32PLUS  18
35 #define EM_PPC      20
36 #define EM_PPC64    21
37 #define EM_ARM      40
38 #define EM_SH       42
39 #define EM_SPARCV9  43
40 #define EM_IA_64    50
41 #define EM_X86_64   62
42 #define EM_OR1K     92
43 #define EM_VC4      137
44 #define EM_AARCH64  183
45 #define EM_MICROBLAZE 189
46 #define EM_RISCV    243
47 #define EM_ALPHA    0x9026
48 
49 /* e_ident[EI_CLASS] */
50 #define ELFCLASS32 1
51 #define ELFCLASS64 2
52 
53 /* e_ident[EI_DATA] */
54 #define ELFDATA2LSB 1
55 #define ELFDATA2MSB 2
56 
57 /* e_ident[EI_VERSION] */
58 #define EV_CURRENT 1
59 
60 /* e_type */
61 #define ET_REL 1
62 #define ET_EXEC 2
63 #define ET_DYN 3
64 #define ET_CORE 4
65 
66 /* e_flags */
67 #define EF_ARM_RELEXEC          0x1
68 #define EF_ARM_HASENTRY         0x2
69 #define EF_ARM_SYMSARESORTED    0x4
70 #define EF_ARM_DYNSYMSUSESEGIDX 0x8
71 #define EF_ARM_MAPSYMSFIRST     0x10
72 #define EF_ARM_LE8              0x00400000
73 #define EF_ARM_BE8              0x00800000
74 #define EF_ARM_EABIMASK         0xFF000000
75 #define EF_ARM_EABI_UNKNOWN     0x00000000
76 #define EF_ARM_EABI_VER1        0x01000000
77 #define EF_ARM_EABI_VER2        0x02000000
78 #define EF_ARM_EABI_VER3        0x03000000
79 #define EF_ARM_EABI_VER4        0x04000000
80 #define EF_ARM_EABI_VER5        0x05000000
81 #define EF_ARM_INTERWORK        0x00000004
82 #define EF_ARM_APCS_26          0x00000008
83 #define EF_ARM_APCS_FLOAT       0x00000010
84 #define EF_ARM_PIC              0x00000020
85 #define EF_ARM_ALIGN8           0x00000040
86 #define EF_ARM_NEW_ABI          0x00000080
87 #define EF_ARM_OLD_ABI          0x00000100
88 #define EF_ARM_SOFT_FLOAT       0x00000200
89 #define EF_ARM_VFP_FLOAT        0x00000400
90 #define EF_ARM_MAVERICK_FLOAT   0x00000800
91 
92 #define EF_RISCV_RVC            0x1
93 #define EF_RISCV_FLOAT_ABI_SOFT 0x0
94 #define EF_RISCV_FLOAT_ABI_SINGLE 0x2
95 #define EF_RISCV_FLOAT_ABI_DOUBLE 0x4
96 #define EF_RISCV_FLOAT_ABI_QUAD 0x6
97 #define EF_RISCV_FLOAT_ABI      0x6
98 #define EF_RISCV_RVE            0x8
99 #define EF_RISCV_TSO            0x10
100 
101 #define SHT_NULL 0
102 #define SHT_PROGBITS 1
103 #define SHT_SYMTAB 2
104 #define SHT_STRTAB 3
105 #define SHT_RELA 4
106 #define SHT_HASH 5
107 #define SHT_DYNAMIC 6
108 #define SHT_NOTE 7
109 #define SHT_NOBITS 8
110 #define SHT_REL 9
111 #define SHT_SHLIB 10
112 #define SHT_DYNSYM 11
113 #define SHT_INIT_ARRAY 14
114 #define SHT_FINI_ARRAY 15
115 #define SHT_PREINIT_ARRAY 16
116 #define SHT_GROUP 17
117 #define SHT_SYMTAB_SHNDX 18
118 #define SHT_LOOS   0x60000000
119 #define SHT_HIOS   0x6fffffff
120 #define SHT_LOPROC 0x70000000
121 #define SHT_HIPROC 0x7fffffff
122 #define SHT_LOUSER 0x80000000
123 #define SHT_HIUSER 0xffffffff
124 
125 #define SHF_WRITE 0x1
126 #define SHF_ALLOC 0x2
127 #define SHF_EXECINSTR 0x4
128 #define SHF_TLS 0x400
129 #define SHF_MASKPROC 0xf0000000
130 
131 #define PF_X        0x1
132 #define PF_W        0x2
133 #define PF_R        0x4
134 #define PF_MASKPROC 0xf0000000
135 
136 #define PT_NULL 0
137 #define PT_LOAD 1
138 #define PT_DYNAMIC 2
139 #define PT_INTERP 3
140 #define PT_NOTE 4
141 #define PT_SHLIB 5
142 #define PT_PHDR 6
143 #define PT_TLS 7
144 #define PT_LOOS   0x60000000
145 #define PT_HIOS   0x6fffffff
146 #define PT_LOPROC 0x70000000
147 #define PT_HIPROC 0x7fffffff
148 
149 #define SHN_UNDEF 0
150 #define SHN_LORESERVE 0xff00
151 #define SHN_LOPROC 0xff00
152 #define SHN_HIPROC 0xff1f
153 #define SHN_ABS 0xfff1
154 #define SHN_COMMON 0xfff2
155 #define SHN_HIRESERVE 0xffff
156 
157 #define STT_NOTYPE 0
158 #define STT_OBJECT 1
159 #define STT_FUNC 2
160 #define STT_SECTION 3
161 #define STT_FILE 4
162 #define STT_TLS 6
163 #define STT_LOPROC 13
164 #define STT_HIPROC 15
165 
166 #define STB_LOCAL 0
167 #define STB_GLOBAL 1
168 #define STB_WEAK 2
169 #define STB_LOPROC 13
170 #define STB_HIPROC 15
171 
172 #define STN_UNDEF 0
173 
174 /* d_tag */
175 #define DT_NULL 0
176 #define DT_NEEDED 1
177 #define DT_PLTRELSZ 2
178 #define DT_PLTGOT 3
179 #define DT_HASH 4
180 #define DT_STRTAB 5
181 #define DT_SYMTAB 6
182 #define DT_RELA 7
183 #define DT_RELASZ 8
184 #define DT_RELAENT 9
185 #define DT_STRSZ 10
186 #define DT_SYMENT 11
187 #define DT_INIT 12
188 #define DT_FINI 13
189 #define DT_SONAME 14
190 #define DT_RPATH 15
191 #define DT_SYMBOLIC 16
192 #define DT_REL 17
193 #define DT_RELSZ 18
194 #define DT_RELENT 19
195 #define DT_PLTREL 20
196 #define DT_DEBUG 21
197 #define DT_TEXTREL 22
198 #define DT_JMPREL 23
199 #define DT_BIND_NOW 24
200 #define DT_INIT_ARRAY 25
201 #define DT_FINI_ARRAY 26
202 #define DT_INIT_ARRAYSZ 27
203 #define DT_FINI_ARRAYSZ 28
204 #define DT_RUNPATH 29
205 #define DT_FLAGS 30
206 #define DT_ENCODING 32
207 #define DT_PREINIT_ARRAY 32
208 #define DT_PREINIT_ARRAYSZ 33
209 #define DT_LOOS   0x6000000d
210 #define DT_HIOS   0x6fff0000
211 #define DT_LOPROC 0x70000000
212 #define DT_HIPROC 0x7fffffff
213 
214 /*
215  * i386 relocation types
216  */
217 #define R_386_NONE 0
218 #define R_386_32 1
219 #define R_386_PC32 2
220 #define R_386_GOT32 3
221 #define R_386_PLT32 4
222 #define R_386_COPY 5
223 #define R_386_GLOB_DAT 6
224 #define R_386_JMP_SLOT 7
225 #define R_386_RELATIVE 8
226 #define R_386_GOTOFF 9
227 #define R_386_GOTPC 10
228 
229 /*
230  * x86-64 relocation types
231  */
232 #define R_X86_64_NONE 0
233 #define R_X86_64_64 1
234 #define R_X86_64_PC32 2
235 #define R_X86_64_GOT32 3
236 #define R_X86_64_PLT32 4
237 #define R_X86_64_COPY 5
238 #define R_X86_64_GLOB_DAT 6
239 #define R_X86_64_JUMP_SLOT 7
240 #define R_X86_64_RELATIVE 8
241 #define R_X86_64_GOTPCREL 9
242 #define R_X86_64_32 10
243 #define R_X86_64_32S 11
244 #define R_X86_64_16 12
245 #define R_X86_64_PC16 13
246 #define R_X86_64_8 14
247 #define R_X86_64_PC8 15
248 #define R_X86_64_DPTMOD64 16
249 #define R_X86_64_DTPOFF64 17
250 #define R_X86_64_TPOFF64 18
251 #define R_X86_64_TLSGD 19
252 #define R_X86_64_TLSLD 20
253 #define R_X86_64_DTPOFF32 21
254 #define R_X86_64_GOTTPOFF 22
255 #define R_X86_64_TPOFF32 23
256 
257 /*
258  * sh4 relocation types
259  */
260 #define R_SH_NONE 0
261 #define R_SH_DIR32 1
262 #define R_SH_REL32 2
263 #define R_SH_DIR8WPN 3
264 #define R_SH_IND12W 4
265 #define R_SH_DIR8WPL 5
266 #define R_SH_DIR8WPZ 6
267 #define R_SH_DIR8BP 7
268 #define R_SH_DIR8W 8
269 #define R_SH_DIR8L 9
270 #define R_SH_SWITCH16 25
271 #define R_SH_SWITCH32 26
272 #define R_SH_USES 27
273 #define R_SH_COUNT 28
274 #define R_SH_ALIGN 29
275 
276 #define R_SH_CODE 30
277 #define R_SH_DATA 31
278 #define R_SH_LABEL 32
279 #define R_SH_SWITCH8 33
280 #define R_SH_GNU_VTINHERIT 34
281 #define R_SH_GNU_VTENTRY 35
282 #define R_SH_LOOP_START 36
283 #define R_SH_LOOP_END 37
284 #define R_SH_DIR5U 45
285 #define R_SH_DIR6U 46
286 #define R_SH_DIR6S 47
287 #define R_SH_DIR10S 48
288 #define R_SH_DIR10SW 49
289 #define R_SH_DIR10SL 50
290 #define R_SH_DIR10SQ 51
291 #define R_SH_GOT32 160
292 #define R_SH_PLT32 161
293 #define R_SH_COPY 162
294 #define R_SH_GLOB_DAT 163
295 #define R_SH_JMP_SLOT 164
296 #define R_SH_RELATIVE 165
297 #define R_SH_GOTOFF 166
298 #define R_SH_GOTPC 167
299 #define R_SH_GOTPLT32 168
300 #define R_SH_GOT_LOW16 169
301 #define R_SH_GOT_MEDLOW16 170
302 #define R_SH_GOT_MEDHI16 171
303 #define R_SH_GOT_HI16 172
304 #define R_SH_GOTPLT_LOW16 173
305 #define R_SH_GOTPLT_MEDLOW16 174
306 #define R_SH_GOTPLT_MEDHI16 175
307 #define R_SH_GOTPLT_HI16 176
308 #define R_SH_PLT_LOW16 177
309 #define R_SH_PLT_MEDLOW16 178
310 #define R_SH_PLT_MEDHI16 179
311 #define R_SH_PLT_HI16 180
312 #define R_SH_GOTOFF_LOW16 181
313 #define R_SH_GOTOFF_MEDLOW16 182
314 #define R_SH_GOTOFF_MEDHI16 183
315 #define R_SH_GOTOFF_HI16 184
316 #define R_SH_GOTPC_LOW16 185
317 #define R_SH_GOTPC_MEDLOW16 186
318 #define R_SH_GOTPC_MEDHI16 187
319 #define R_SH_GOTPC_HI16 188
320 #define R_SH_GOT10BY4 189
321 #define R_SH_GOTPLT10BY4 190
322 #define R_SH_GOT10BY8 191
323 #define R_SH_GOTPLT10BY8 192
324 #define R_SH_COPY64 193
325 #define R_SH_GLOB_DAT64 194
326 #define R_SH_JMP_SLOT64 195
327 #define R_SH_RELATIVE64 196
328 #define R_SH_SHMEDIA_CODE 242
329 #define R_SH_PT_16 243
330 #define R_SH_IMMS16 244
331 #define R_SH_IMMU16 245
332 #define R_SH_IMM_LOW16 246
333 #define R_SH_IMM_LOW16_PCREL 247
334 #define R_SH_IMM_MEDLOW16 248
335 #define R_SH_IMM_MEDLOW16_PCREL 249
336 #define R_SH_IMM_MEDHI16 250
337 #define R_SH_IMM_MEDHI16_PCREL 251
338 #define R_SH_IMM_HI16 252
339 #define R_SH_IMM_HI16_PCREL 253
340 #define R_SH_64 254
341 #define R_SH_64_PCREL 255
342 
343 /*
344  * ppc relocation types
345  */
346 #define R_PPC_NONE      0
347 #define R_PPC_ADDR32        1   /* 32bit absolute address */
348 #define R_PPC_ADDR24        2   /* 26bit address, 2 bits ignored.  */
349 #define R_PPC_ADDR16        3   /* 16bit absolute address */
350 #define R_PPC_ADDR16_LO     4   /* lower 16bit of absolute address */
351 #define R_PPC_ADDR16_HI     5   /* high 16bit of absolute address */
352 #define R_PPC_ADDR16_HA     6   /* adjusted high 16bit */
353 #define R_PPC_ADDR14        7   /* 16bit address, 2 bits ignored */
354 #define R_PPC_ADDR14_BRTAKEN    8
355 #define R_PPC_ADDR14_BRNTAKEN   9
356 #define R_PPC_REL24     10  /* PC relative 26 bit */
357 #define R_PPC_REL14     11  /* PC relative 16 bit */
358 #define R_PPC_REL14_BRTAKEN 12
359 #define R_PPC_REL14_BRNTAKEN    13
360 #define R_PPC_GOT16     14
361 #define R_PPC_GOT16_LO      15
362 #define R_PPC_GOT16_HI      16
363 #define R_PPC_GOT16_HA      17
364 #define R_PPC_PLTREL24      18
365 #define R_PPC_COPY      19
366 #define R_PPC_GLOB_DAT      20
367 #define R_PPC_JMP_SLOT      21
368 #define R_PPC_RELATIVE      22
369 #define R_PPC_LOCAL24PC     23
370 #define R_PPC_UADDR32       24
371 #define R_PPC_UADDR16       25
372 #define R_PPC_REL32     26
373 #define R_PPC_PLT32     27
374 #define R_PPC_PLTREL32      28
375 #define R_PPC_PLT16_LO      29
376 #define R_PPC_PLT16_HI      30
377 #define R_PPC_PLT16_HA      31
378 #define R_PPC_SDAREL16      32
379 #define R_PPC_SECTOFF       33
380 #define R_PPC_SECTOFF_LO    34
381 #define R_PPC_SECTOFF_HI    35
382 #define R_PPC_SECTOFF_HA    36
383 #define R_PPC_NUM       37
384 
385 /*
386  * ARM relocation types
387  */
388 #define R_ARM_NONE          0
389 #define R_ARM_PC24          1
390 #define R_ARM_ABS32         2
391 #define R_ARM_REL32         3
392 #define R_ARM_PC13          4
393 #define R_ARM_ABS16         5
394 #define R_ARM_ABS12         6
395 #define R_ARM_THM_ABS5      7
396 #define R_ARM_ABS8          8
397 #define R_ARM_SBREL32       9
398 #define R_ARM_THM_PC22      10
399 #define R_ARM_THM_PC8       11
400 #define R_ARM_AMP_VCALL9    12
401 #define R_ARM_SWI24         13
402 #define R_ARM_THM_SWI8      14
403 #define R_ARM_XPC25         15
404 #define R_ARM_THM_XPC22     16
405 #define R_ARM_TLS_DTPMOD32  17  /* ID of module containing symbol */
406 #define R_ARM_TLS_DTPOFF32  18  /* Offset in TLS block */
407 #define R_ARM_TLS_TPOFF32   19  /* Offset in static TLS block */
408 #define R_ARM_COPY          20  /* Copy data from shared object. */
409 #define R_ARM_GLOB_DAT      21  /* Set GOT entry to data address. */
410 #define R_ARM_JUMP_SLOT     22  /* Set GOT entry to code address. */
411 #define R_ARM_RELATIVE      23  /* Add load address of shared object. */
412 #define R_ARM_GOTOFF        24  /* Add GOT-relative symbol address. */
413 #define R_ARM_GOTPC         25  /* Add PC-relative GOT table address. */
414 #define R_ARM_GOT32         26  /* Add PC-relative GOT offset. */
415 #define R_ARM_PLT32         27  /* Add PC-relative PLT offset. */
416 #define R_ARM_GNU_VTENTRY   100
417 #define R_ARM_GNU_VTINHERIT 101
418 #define R_ARM_RSBREL32      250
419 #define R_ARM_THM_RPC22     251
420 #define R_ARM_RREL32        252
421 #define R_ARM_RABS32        253
422 #define R_ARM_RPC24         254
423 #define R_ARM_RBASE         255
424 
425 /* elf32 stuff */
426 typedef uint32_t Elf32_Addr;
427 typedef uint16_t Elf32_Half;
428 typedef uint32_t Elf32_Off;
429 typedef int32_t  Elf32_Sword;
430 typedef uint32_t Elf32_Word;
431 
432 struct Elf32_Ehdr {
433     unsigned char   e_ident[EI_NIDENT];
434     Elf32_Half      e_type;
435     Elf32_Half      e_machine;
436     Elf32_Word      e_version;
437     Elf32_Addr      e_entry;
438     Elf32_Off       e_phoff;
439     Elf32_Off       e_shoff;
440     Elf32_Word      e_flags;
441     Elf32_Half      e_ehsize;
442     Elf32_Half      e_phentsize;
443     Elf32_Half      e_phnum;
444     Elf32_Half      e_shentsize;
445     Elf32_Half      e_shnum;
446     Elf32_Half      e_shstrndx;
447 };
448 
449 struct Elf32_Shdr {
450     Elf32_Word      sh_name;
451     Elf32_Word      sh_type;
452     Elf32_Word      sh_flags;
453     Elf32_Addr      sh_addr;
454     Elf32_Off       sh_offset;
455     Elf32_Word      sh_size;
456     Elf32_Word      sh_link;
457     Elf32_Word      sh_info;
458     Elf32_Word      sh_addralign;
459     Elf32_Word      sh_entsize;
460 };
461 
462 struct Elf32_Phdr {
463     Elf32_Word      p_type;
464     Elf32_Off       p_offset;
465     Elf32_Addr      p_vaddr;
466     Elf32_Addr      p_paddr;
467     Elf32_Word      p_filesz;
468     Elf32_Word      p_memsz;
469     Elf32_Word      p_flags;
470     Elf32_Word      p_align;
471 };
472 
473 struct Elf32_Sym {
474     Elf32_Word      st_name;
475     Elf32_Addr      st_value;
476     Elf32_Word      st_size;
477     unsigned char   st_info;
478     unsigned char   st_other;
479     Elf32_Half      st_shndx;
480 };
481 
482 #define ELF32_ST_BIND(i) ((i) >> 4)
483 #define ELF32_ST_TYPE(i) ((i) & 0xf)
484 #define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xf))
485 
486 struct Elf32_Rel {
487     Elf32_Addr r_offset;
488     Elf32_Word r_info;
489 };
490 
491 struct Elf32_Rela {
492     Elf32_Addr r_offset;
493     Elf32_Word r_info;
494     Elf32_Sword r_addend;
495 };
496 
497 #define ELF32_R_SYM(i) ((i) >> 8)
498 #define ELF32_R_TYPE(i) ((unsigned char)(i))
499 #define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
500 
501 struct Elf32_Dyn {
502     Elf32_Sword d_tag;
503     union {
504         Elf32_Word d_val;
505         Elf32_Addr d_ptr;
506     } d_un;
507 };
508 
509 /* elf64 stuff */
510 typedef uint64_t Elf64_Addr;
511 typedef uint16_t Elf64_Half;
512 typedef uint64_t Elf64_Off;
513 typedef int32_t  Elf64_Sword;
514 typedef int64_t  Elf64_Sxword;
515 typedef uint32_t Elf64_Word;
516 typedef uint64_t Elf64_Lword;
517 typedef uint64_t Elf64_Xword;
518 
519 
520 struct Elf64_Ehdr {
521     unsigned char e_ident[EI_NIDENT];
522     Elf64_Half  e_type;
523     Elf64_Half  e_machine;
524     Elf64_Word  e_version;
525     Elf64_Addr  e_entry;
526     Elf64_Off   e_phoff;
527     Elf64_Off   e_shoff;
528     Elf64_Word  e_flags;
529     Elf64_Half  e_ehsize;
530     Elf64_Half  e_phentsize;
531     Elf64_Half  e_phnum;
532     Elf64_Half  e_shentsize;
533     Elf64_Half  e_shnum;
534     Elf64_Half  e_shstrndx;
535 };
536 
537 struct Elf64_Shdr {
538     Elf64_Word  sh_name;
539     Elf64_Word  sh_type;
540     Elf64_Xword sh_flags;
541     Elf64_Addr  sh_addr;
542     Elf64_Off   sh_offset;
543     Elf64_Xword sh_size;
544     Elf64_Word  sh_link;
545     Elf64_Word  sh_info;
546     Elf64_Xword sh_addralign;
547     Elf64_Xword sh_entsize;
548 };
549 
550 struct Elf64_Phdr {
551     Elf64_Word  p_type;
552     Elf64_Word  p_flags;
553     Elf64_Off   p_offset;
554     Elf64_Addr  p_vaddr;
555     Elf64_Addr  p_paddr;
556     Elf64_Xword p_filesz;
557     Elf64_Xword p_memsz;
558     Elf64_Xword p_align;
559 };
560 
561 #define ELF64_ST_BIND(info)     ((info) >> 4)
562 #define ELF64_ST_TYPE(info)     ((info) & 0xf)
563 #define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
564 
565 struct Elf64_Rel {
566     Elf64_Addr  r_offset;
567     Elf64_Xword r_info;
568 };
569 
570 struct Elf64_Rela {
571     Elf64_Addr   r_offset;
572     Elf64_Xword  r_info;
573     Elf64_Sxword r_addend;
574 };
575 
576 #define ELF64_R_SYM(info)   ((info) >> 32)
577 #define ELF64_R_TYPE(info)  ((info) & 0xffffffffL)
578 
579 #define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
580 
581 #define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
582 #define ELF64_R_TYPE_ID(info)   (((Elf64_Xword)(info)<<56)>>56)
583 #define ELF64_R_TYPE_INFO(data, type) (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
584 
585