Asm

/* $Id$ */
/* Copyright (c) 2011-2017 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS Devel Asm */
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* FIXME:
* - ensure the first section output is of type SHN_UNDEF
* - use set_string() to store and remember strings? */
#include <System.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "elf/common.h"
#include "elf/elf.h"
/* ELF */
/* private */
/* prototypes */
/* plug-in */
static AsmFormatPlugin * _elf_init(AsmFormatPluginHelper * helper,
char const * arch);
static int _elf_destroy(AsmFormatPlugin * format);
static int _elf_section(AsmFormatPlugin * format, char const * name);
static char const * _elf_guess(AsmFormatPlugin * format, char const * hint);
static char const * _elf_detect(AsmFormatPlugin * format);
static int _elf_decode(AsmFormatPlugin * format, int raw);
static int _elf_decode_section(AsmFormatPlugin * format, AsmSection * section,
AsmArchInstructionCall ** calls, size_t * calls_cnt);
/* public */
/* variables */
/* format_plugin */
AsmFormatPluginDefinition format_plugin =
{
"elf",
"ELF",
LICENSE_GNU_LGPL3_FLAGS,
ELFMAG,
SELFMAG,
_elf_init,
_elf_destroy,
_elf_guess,
NULL,
NULL,
_elf_section,
_elf_detect,
_elf_decode,
_elf_decode_section
};
/* private */
/* functions */
/* plug-in */
/* elf_init */
static const ElfArch * _init_arch(char const * arch);
static AsmFormatPlugin * _elf_init(AsmFormatPluginHelper * helper,
char const * arch)
{
Elf * elf;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, arch);
#endif
if((elf = object_new(sizeof(*elf))) == NULL)
return NULL;
elf->helper = helper;
elf->destroy = NULL;
elf->decode = NULL;
elf->shstrtab.buf = NULL;
elf->shstrtab.cnt = 0;
elf->es32 = NULL;
elf->es32_cnt = 0;
elf->es64 = NULL;
elf->es64_cnt = 0;
if(arch == NULL)
{
elf->arch = NULL;
return elf;
}
if((elf->arch = _init_arch(arch)) == NULL)
{
object_delete(elf);
return NULL;
}
if(elf->arch->capacity == ELFCLASS32)
{
if(elf32_init(elf) != 0)
return NULL;
elf->destroy = elf32_destroy;
elf->section = elf32_section;
elf->decode = elf32_decode;
}
else if(elf->arch->capacity == ELFCLASS64)
{
if(elf64_init(elf) != 0)
return NULL;
elf->destroy = elf64_destroy;
elf->section = elf64_section;
elf->decode = elf64_decode;
}
else
return NULL;
return elf;
}
static const ElfArch * _init_arch(char const * arch)
{
const ElfArch * ea;
for(ea = elf_arch; ea->arch != NULL; ea++)
if(strcmp(ea->arch, arch) == 0)
return ea;
error_set_code(1, "%s: %s", arch, "Unsupported ELF architecture");
return NULL;
}
/* elf_destroy */
static int _elf_destroy(AsmFormatPlugin * format)
{
Elf * elf = format;
int ret = 0;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
if(format->destroy != NULL)
ret = format->destroy(elf);
free(elf->es32);
free(elf->es64);
object_delete(elf);
return ret;
}
/* elf_section */
static int _elf_section(AsmFormatPlugin * format, char const * name)
{
if(format->section == NULL)
return -1;
return format->section(format, name);
}
/* elf_guess */
static char const * _elf_guess(AsmFormatPlugin * format, char const * hint)
{
/* XXX share these tables with _elf_detect() */
struct
{
char const * quirk;
char const * arch;
} quirks[] =
{
{ "arm", "armel" },
{ "mips", "mipsel" },
{ "x86", "i686" },
{ "x86-64", "amd64" },
{ "x86_64", "amd64" }
};
char const * arch[] =
{
"alpha",
"amd64",
"armeb", "armel",
"i386", "i486", "i586", "i686",
"mips", "mips64",
"sparc", "sparc64",
};
size_t i;
(void) format;
if(hint == NULL)
return NULL;
for(i = 0; i < sizeof(quirks) / sizeof(*quirks); i++)
if(string_compare(hint, quirks[i].quirk) == 0)
return quirks[i].arch;
for(i = 0; i < sizeof(arch) / sizeof(*arch); i++)
if(string_compare(hint, arch[i]) == 0)
return hint;
return NULL;
}
/* elf_detect */
static char const * _elf_detect(AsmFormatPlugin * format)
{
AsmFormatPluginHelper * helper = format->helper;
char const * ret;
union
{
Elf32_Ehdr ehdr32;
Elf64_Ehdr ehdr64;
} ehdr;
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return NULL;
if(helper->read(helper->format, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
return NULL;
switch(ehdr.ehdr32.e_ident[EI_CLASS])
{
case ELFCLASS32:
if((ret = elf32_detect(format, &ehdr.ehdr32)) != NULL)
format->decode = elf32_decode;
break;
case ELFCLASS64:
if((ret = elf64_detect(format, &ehdr.ehdr64)) != NULL)
format->decode = elf64_decode;
break;
default:
ret = NULL;
error_set_code(1, "%s: %s 0x%x\n",
helper->get_filename(helper->format),
"Unsupported ELF class",
ehdr.ehdr32.e_ident[EI_CLASS]);
break;
}
return ret;
}
/* elf_decode */
static int _elf_decode(AsmFormatPlugin * format, int raw)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, raw);
#endif
if(_elf_detect(format) == NULL)
return -1;
return format->decode(format, raw);
}
/* elf_decode_section */
static int _elf_decode_section(AsmFormatPlugin * format, AsmSection * section,
AsmArchInstructionCall ** calls, size_t * calls_cnt)
{
AsmFormatPluginHelper * helper = format->helper;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
return helper->decode(helper->format, section->offset, section->size,
section->base, calls, calls_cnt);
}