Asm
/* $Id$ */
/* Copyright (c) 2011-2015 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/>. */
#include <stdlib.h>
#include <string.h>
#include "common.h"
#if (ELFSIZE == 64)
# define elf_init elf64_init
# define elf_section elf64_section
# define esSZ es64
# define esSZ_cnt es64_cnt
#elif (ELFSIZE == 32)
# define elf_init elf32_init
# define elf_section elf32_section
# define esSZ es32
# define esSZ_cnt es32_cnt
#else
# error Unsupported ELF size
#endif
/* public */
/* functions */
/* elf_init */
int elf_init(AsmFormatPlugin * format)
{
AsmFormatPluginHelper * helper = format->helper;
Elf * elf = format;
const ElfArch * ea = elf->arch;
Elf_Ehdr hdr;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
memset(&hdr, 0, sizeof(hdr));
memcpy(&hdr.e_ident, ELFMAG, SELFMAG);
hdr.e_ident[EI_CLASS] = ELFCLASS;
hdr.e_ident[EI_DATA] = ea->endian;
hdr.e_ident[EI_VERSION] = EV_CURRENT;
if(ea->endian == ELFDATA2MSB)
{
hdr.e_type = _htob16(ET_REL);
hdr.e_machine = _htob16(ea->machine);
hdr.e_version = _htob32(EV_CURRENT);
hdr.e_ehsize = _htob16(sizeof(hdr));
hdr.e_shentsize = _htob16(sizeof(Elf_Shdr));
hdr.e_shstrndx = _htob16(SHN_UNDEF);
}
else
{
hdr.e_type = _htol16(ET_REL);
hdr.e_machine = _htol16(ea->machine);
hdr.e_version = _htol32(EV_CURRENT);
hdr.e_ehsize = _htol16(sizeof(hdr));
hdr.e_shentsize = _htol16(sizeof(Elf_Shdr));
hdr.e_shstrndx = _htol16(SHN_UNDEF);
}
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
return 0;
}
/* elf_section */
static ElfSectionValues const * _section_values(char const * name);
int elf_section(AsmFormatPlugin * format, char const * name)
{
AsmFormatPluginHelper * helper = format->helper;
Elf * elf = format;
int ss;
Elf_Shdr * p;
ElfSectionValues const * esv;
long offset;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
if((ss = elfstrtab_set(format, &elf->shstrtab, name)) < 0)
return -1;
if((p = realloc(elf->esSZ, sizeof(*p) * (elf->esSZ_cnt + 1))) == NULL)
return elf_error(format);
elf->esSZ = p;
p = &elf->esSZ[elf->esSZ_cnt++];
memset(p, 0, sizeof(*p));
esv = _section_values(name);
p->sh_name = ss;
p->sh_type = esv->type;
p->sh_flags = esv->flags;
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0)
return -1;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() offset %ld\n", __func__, offset);
#endif
p->sh_offset = offset;
p->sh_link = SHN_UNDEF; /* FIXME */
return 0;
}
/* section_values */
static ElfSectionValues const * _section_values(char const * name)
{
ElfSectionValues const * esv;
int cmp;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
for(esv = elf_section_values; esv->name != NULL; esv++)
if((cmp = strcmp(esv->name, name)) == 0)
return esv;
else if(cmp > 0)
break;
for(; esv->name != NULL; esv++);
return esv;
}