/* $Id$ */
/* Copyright (c) 2011-2022 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 <errno.h>
#include <System.h>
#include "common.h"


/* public */
/* constants */
const ElfArch elf_arch[] =
{
#if defined(EM_AMD64)
	{ "amd64",	EM_AMD64,	ELFCLASS64,	ELFDATA2LSB, 0x4 },
#elif defined(EM_X86_64)
	{ "amd64",	EM_X86_64,	ELFCLASS64,	ELFDATA2LSB, 0x4 },
#endif
	{ "arm",	EM_ARM,		ELFCLASS32,	ELFDATA2LSB, 0x0 },
	{ "armeb",	EM_ARM,		ELFCLASS32,	ELFDATA2MSB, 0x0 },
	{ "armel",	EM_ARM,		ELFCLASS32,	ELFDATA2LSB, 0x0 },
	{ "i386",	EM_386,		ELFCLASS32,	ELFDATA2LSB, 0x4 },
	{ "i486",	EM_386,		ELFCLASS32,	ELFDATA2LSB, 0x4 },
	{ "i586",	EM_386,		ELFCLASS32,	ELFDATA2LSB, 0x4 },
	{ "i686",	EM_386,		ELFCLASS32,	ELFDATA2LSB, 0x4 },
	{ "mips",	EM_MIPS,	ELFCLASS32,	ELFDATA2MSB, 0x0 },
	{ "mipseb",	EM_MIPS,	ELFCLASS32,	ELFDATA2MSB, 0x0 },
	{ "mipsel",	EM_MIPS,	ELFCLASS32,	ELFDATA2LSB, 0x0 },
	{ "sparc",	EM_SPARC,	ELFCLASS32,	ELFDATA2MSB, 0x0 },
	{ "sparc64",	EM_SPARCV9,	ELFCLASS64,	ELFDATA2MSB, 0x0 },
	{ NULL,		'\0',		'\0',		'\0',        0x0 }
};

#if defined(EM_AMD64) || defined(EM_X86_64)
# define OFFSET 1
#else
# define OFFSET 0
#endif
#if defined(__amd64__) && (defined(EM_AMD64) || defined(EM_X86_64))
const ElfArch * elf_arch_native = &elf_arch[0];
#elif defined(__arm__)
const ElfArch * elf_arch_native = &elf_arch[0 + OFFSET];
#elif defined(__i386__)
const ElfArch * elf_arch_native = &elf_arch[3 + OFFSET];
#elif defined(__sparc64__)
const ElfArch * elf_arch_native = &elf_arch[11 + OFFSET];
#elif defined(__sparc__)
const ElfArch * elf_arch_native = &elf_arch[10 + OFFSET];
#else
const ElfArch * elf_arch_native = NULL;
#endif

const ElfSectionValues elf_section_values[] =
{
	{ ".bss",	SHT_NOBITS,	SHF_ALLOC | SHF_WRITE		},
	{ ".comment",	SHT_PROGBITS,	0				},
	{ ".data",	SHT_PROGBITS,	SHF_ALLOC | SHF_WRITE		},
	{ ".data1",	SHT_PROGBITS,	SHF_ALLOC | SHF_WRITE		},
	{ ".debug",	SHT_PROGBITS,	0				},
	{ ".dynamic",	SHT_DYNAMIC,	0				},
	{ ".dynstr",	SHT_STRTAB,	SHF_ALLOC			},
	{ ".dynsym",	SHT_DYNSYM,	SHF_ALLOC			},
	{ ".fini",	SHT_PROGBITS,	SHF_ALLOC | SHF_EXECINSTR	},
	{ ".got",	SHT_PROGBITS,	0				},
	{ ".hash",	SHT_HASH,	SHF_ALLOC			},
	{ ".init",	SHT_PROGBITS,	SHF_ALLOC | SHF_EXECINSTR	},
	{ ".interp",	SHT_PROGBITS,	0				},
	{ ".line",	SHT_PROGBITS,	0				},
	{ ".note",	SHT_NOTE,	0				},
	{ ".plt",	SHT_PROGBITS,	0				},
	{ ".rodata",	SHT_PROGBITS,	SHF_ALLOC			},
	{ ".rodata1",	SHT_PROGBITS,	SHF_ALLOC			},
	{ ".shstrtab",	SHT_STRTAB,	0				},
	{ ".strtab",	SHT_STRTAB,	0				},
	{ ".symtab",	SHT_SYMTAB,	0				},
	{ ".text",	SHT_PROGBITS,	SHF_ALLOC | SHF_EXECINSTR	},
	{ NULL,		0,		0				}
};


/* functions */
/* elf_error */
int elf_error(AsmFormatPlugin * format)
{
	return -error_set_code(1, "%s: %s", format->helper->get_filename(
				format->helper->format), strerror(errno));
}


/* ElfStrtab */
/* elfstrtab_set */
int elfstrtab_set(AsmFormatPlugin * format, ElfStrtab * strtab,
		char const * name)
{
	size_t len;
	size_t cnt;
	char * p;

	if((len = strlen(name)) == 0 && strtab->cnt != 0)
		return 0;
	if((cnt = strtab->cnt) == 0)
		cnt++;
	if((p = realloc(strtab->buf, sizeof(char) * (cnt + len + 1))) == NULL)
		return -elf_error(format);
	else if(strtab->buf == NULL)
		p[0] = '\0';
	strtab->buf = p;
	if(len == 0)
	{
		strtab->cnt = cnt;
		return 0;
	}
	strtab->cnt = cnt + len + 1;
	memcpy(&strtab->buf[cnt], name, len + 1);
	return cnt;
}
