all repos — mgba @ d270a42de8c19c73ef1eeaca165b458673139260

mGBA Game Boy Advance Emulator

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	ELFProgramHeadersResize(ph, hdr->e_phnum);
 88	memcpy(ELFProgramHeadersGetPointer(ph, 0), phdr, sizeof(*phdr) * hdr->e_phnum);
 89}
 90
 91void ELFGetSectionHeaders(struct ELF* elf, struct ELFSectionHeaders* sh) {
 92	ELFSectionHeadersClear(sh);
 93	Elf_Scn* section = elf_getscn(elf->e, 0);
 94	do {
 95		*ELFSectionHeadersAppend(sh) = *elf32_getshdr(section);
 96	} while ((section = elf_nextscn(elf->e, section)));
 97}
 98
 99Elf32_Shdr* ELFGetSectionHeader(struct ELF* elf, size_t index) {
100	Elf_Scn* section = elf_getscn(elf->e, index);
101	return elf32_getshdr(section);
102}
103
104size_t ELFFindSection(struct ELF* elf, const char* name) {
105	Elf32_Ehdr* hdr = elf32_getehdr(elf->e);
106	size_t shstrtab = hdr->e_shstrndx;
107	if (strcmp(name, ".shstrtab") == 0) {
108		return shstrtab;
109	}
110	Elf_Scn* section = NULL;
111	while ((section = elf_nextscn(elf->e, section))) {
112		Elf32_Shdr* shdr = elf32_getshdr(section);
113		const char* sname = elf_strptr(elf->e, shstrtab, shdr->sh_name);
114		if (strcmp(sname, name) == 0) {
115			return elf_ndxscn(section);
116		}
117	}
118	return 0;
119}
120
121const char* ELFGetString(struct ELF* elf, size_t section, size_t string) {
122	return elf_strptr(elf->e, section, string);
123}
124
125#endif