// Executable and Linking Format definitions
// Copyright (C) Florian Negele

// This file is part of the Eigen Compiler Suite.

// The ECS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The ECS 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 General Public License for more details.

// Under Section 7 of the GNU General Public License version 3,
// the copyright holder grants you additional permissions to use
// this file as described in the ECS Runtime Support Exception.

// You should have received a copy of the GNU General Public License
// and a copy of the ECS Runtime Support Exception along with
// the ECS.  If not, see <https://www.gnu.org/licenses/>.

#ifndef ECS_DEF_ELF_HEADER_INCLUDED
#define ECS_DEF_ELF_HEADER_INCLUDED

#include "assembly"

#define DT_RELA 7
#define DT_RELAENT 9
#define DT_RELASZ 8
#define DT_STRSZ 10
#define DT_STRTAB 5
#define DT_SYMENT 11
#define DT_SYMTAB 6
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define EM_386 3
#define EM_68K 4
#define EM_AARCH64 183
#define EM_ARM 40
#define EM_MIPS 8
#define EM_OPENRISC 92
#define EM_X86_64 62
#define EM_XTENSA 94
#define ET_EXEC 2
#define EV_CURRENT 1
#define PF_R 4
#define PF_W 2
#define PF_X 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_LOAD 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
#define SHF_WRITE 1
#define SHT_PROGBITS 1
#define SHT_STRTAB 3
#define STB_GLOBAL 1
#define STT_FUNC 2
#define STV_DEFAULT 0

#define HALF(value) DBYTE(value)
#define WORD(value) QBYTE(value)
#define XWORD(value) OBYTE(value)

#define ELF_HEADER(ei_class, ei_data, e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx) \
	BYTE (0x7f, "ELF", ei_class, ei_data, 1, 0) PAD (16) \
	HALF (e_type) HALF (e_machine) WORD (e_version) ADDR (e_entry) OFF (e_phoff) OFF (e_shoff) WORD (e_flags) HALF (e_ehsize) HALF (e_phentsize) HALF (e_phnum) HALF (e_shentsize) HALF (e_shnum) HALF (e_shstrndx)

#if EICLASS == ELFCLASS32

	#define ADDRSIZE 4
	#define DSENTSIZE 8
	#define EHSIZE 52
	#define PHENTSIZE 32
	#define RTENTSIZE 12
	#define SHENTSIZE 40
	#define STENTSIZE 16

	#define ADDR(value) QBYTE(value)
	#define OFF(value) QBYTE(value)

	#define PROGRAM_HEADER(p_type, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_flags, p_align) \
		WORD (p_type) OFF (p_offset) ADDR (p_vaddr) ADDR (p_paddr) WORD (p_filesz) WORD (p_memsz) WORD (p_flags) WORD (p_align)

	#define SECTION_HEADER(sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize) \
		WORD (sh_name) WORD (sh_type) WORD (sh_flags) ADDR (sh_addr) OFF (sh_offset) WORD (sh_size) WORD (sh_link) WORD (sh_info) WORD (sh_addralign) WORD (sh_entsize)

	#define DYNAMIC_SECTION_ENTRY(d_tag, d_val) \
		WORD (d_tag) WORD (d_val)

	#define SYMBOL_TABLE_ENTRY(st_name, st_value, st_size, st_info, st_other, st_shndx) \
		WORD (st_name) ADDR (st_value) WORD (st_size) BYTE (st_info) BYTE (st_other) HALF (st_shndx)

	#define RELOCATION_TABLE_ENTRY(r_offset, r_type, r_info, r_addend) \
		ADDR (r_offset) BYTE (r_type) TBYTE (r_info) WORD (r_addend)

#elif EICLASS == ELFCLASS64

	#define ADDRSIZE 8
	#define DSENTSIZE 16
	#define EHSIZE 64
	#define PHENTSIZE 56
	#define RTENTSIZE 24
	#define SHENTSIZE 64
	#define STENTSIZE 24

	#define ADDR(value) OBYTE(value)
	#define OFF(value) OBYTE(value)

	#define PROGRAM_HEADER(p_type, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_flags, p_align) \
		WORD (p_type) WORD (p_flags) OFF (p_offset) ADDR (p_vaddr) ADDR (p_paddr) XWORD (p_filesz) XWORD (p_memsz) XWORD (p_align)

	#define SECTION_HEADER(sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize) \
		WORD (sh_name) WORD (sh_type) XWORD (sh_flags) ADDR (sh_addr) OFF (sh_offset) XWORD (sh_size) WORD (sh_link) WORD (sh_info) XWORD (sh_addralign) XWORD (sh_entsize)

	#define DYNAMIC_SECTION_ENTRY(d_tag, d_val) \
		XWORD (d_tag) XWORD (d_val)

	#define SYMBOL_TABLE_ENTRY(st_name, st_value, st_size, st_info, st_other, st_shndx) \
		WORD (st_name) BYTE (st_info) BYTE (st_other) HALF (st_shndx) ADDR (st_value) XWORD (st_size)

	#define RELOCATION_TABLE_ENTRY(r_offset, r_type, r_info, r_addend) \
		ADDR (r_offset) QBYTE (r_type) QBYTE (r_info) XWORD (r_addend)

#else

	#error ELF format not supported

#endif

#endif // ECS_DEF_ELF_HEADER_INCLUDED
