all repos — mgba @ d46f12aa8efbd194136d305bf2cb37e3e499b4af

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