src/util/elf-read.c (view raw)
1/* Copyright (c) 2013-2017 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba-util/elf-read.h>
7
8#ifdef USE_ELF
9
10#include <mgba-util/vfs.h>
11
12DEFINE_VECTOR(ELFProgramHeaders, Elf32_Phdr);
13DEFINE_VECTOR(ELFSectionHeaders, Elf32_Shdr);
14
15static bool _elfInit = false;
16
17struct ELF {
18 Elf* e;
19 struct VFile* vf;
20 size_t size;
21 char* memory;
22};
23
24struct ELF* ELFOpen(struct VFile* vf) {
25 if (!_elfInit) {
26 _elfInit = elf_version(EV_CURRENT) != EV_NONE;
27 if (!_elfInit) {
28 return NULL;
29 }
30 }
31 if (!vf) {
32 return NULL;
33 }
34 size_t size = vf->size(vf);
35 char* memory = vf->map(vf, size, MAP_READ);
36 if (!memory) {
37 return NULL;
38 }
39
40 Elf* e = elf_memory(memory, size);
41 if (!e || elf_kind(e) != ELF_K_ELF) {
42 elf_end(e);
43 vf->unmap(vf, memory, size);
44 return false;
45 }
46 struct ELF* elf = malloc(sizeof(*elf));
47 elf->e = e;
48 elf->vf = vf;
49 elf->size = size;
50 elf->memory = memory;
51 return elf;
52}
53
54void ELFClose(struct ELF* elf) {
55 elf_end(elf->e);
56 elf->vf->unmap(elf->vf, elf->memory, elf->size);
57 free(elf);
58}
59
60void* ELFBytes(struct ELF* elf, size_t* size) {
61 if (size) {
62 *size = elf->size;
63 }
64 return elf->memory;
65}
66
67uint16_t ELFMachine(struct ELF* elf) {
68 Elf32_Ehdr* hdr = elf32_getehdr(elf->e);
69 if (!hdr) {
70 return 0;
71 }
72 return hdr->e_machine;
73}
74
75uint32_t ELFEntry(struct ELF* elf) {
76 Elf32_Ehdr* hdr = elf32_getehdr(elf->e);
77 if (!hdr) {
78 return 0;
79 }
80 return hdr->e_entry;
81}
82
83void ELFGetProgramHeaders(struct ELF* elf, struct ELFProgramHeaders* ph) {
84 ELFProgramHeadersClear(ph);
85 Elf32_Ehdr* hdr = elf32_getehdr(elf->e);
86 Elf32_Phdr* phdr = elf32_getphdr(elf->e);
87 if (!hdr || !phdr) {
88 return;
89 }
90 ELFProgramHeadersResize(ph, hdr->e_phnum);
91 memcpy(ELFProgramHeadersGetPointer(ph, 0), phdr, sizeof(*phdr) * hdr->e_phnum);
92}
93
94void ELFGetSectionHeaders(struct ELF* elf, struct ELFSectionHeaders* sh) {
95 ELFSectionHeadersClear(sh);
96 Elf_Scn* section = elf_getscn(elf->e, 0);
97 do {
98 *ELFSectionHeadersAppend(sh) = *elf32_getshdr(section);
99 } while ((section = elf_nextscn(elf->e, section)));
100}
101
102Elf32_Shdr* ELFGetSectionHeader(struct ELF* elf, size_t index) {
103 Elf_Scn* section = elf_getscn(elf->e, index);
104 return elf32_getshdr(section);
105}
106
107size_t ELFFindSection(struct ELF* elf, const char* name) {
108 Elf32_Ehdr* hdr = elf32_getehdr(elf->e);
109 size_t shstrtab = hdr->e_shstrndx;
110 if (strcmp(name, ".shstrtab") == 0) {
111 return shstrtab;
112 }
113 Elf_Scn* section = NULL;
114 while ((section = elf_nextscn(elf->e, section))) {
115 Elf32_Shdr* shdr = elf32_getshdr(section);
116 const char* sname = elf_strptr(elf->e, shstrtab, shdr->sh_name);
117 if (strcmp(sname, name) == 0) {
118 return elf_ndxscn(section);
119 }
120 }
121 return 0;
122}
123
124const char* ELFGetString(struct ELF* elf, size_t section, size_t string) {
125 return elf_strptr(elf->e, section, string);
126}
127
128#endif