/****************************************************************************
 * include/elf64.h
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

#ifndef __INCLUDE_ELF64_H
#define __INCLUDE_ELF64_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <stdint.h>
#include <elf.h>

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

#define ELF_CLASS         ELFCLASS64

/* See ELF-64 Object File Format: Version 1.5 Draft 2 */

#define ELF64_ST_BIND(i)     ((i) >> 4)
#define ELF64_ST_TYPE(i)     ((i) & 0xf)
#define ELF64_ST_INFO(b,t)   (((b) << 4) | ((t) & 0xf))

/* Generic macro to abstract ELF32/ELF64 type/bind */

#define ELF_ST_TYPE(a)       ELF64_ST_TYPE(a)
#define ELF_ST_BIND(a)       ELF64_ST_BIND(a)

/* Definitions for Elf64_Rel*::r_info */

#define ELF64_R_SYM(i)       ((i) >> 32)
#define ELF64_R_TYPE(i)      ((i) & 0xffffffffL)
#define ELF64_R_INFO(s,t)    (((s)<< 32) + ((t) & 0xffffffffL))

#define ELF_R_SYM(i)         ELF64_R_SYM(i)
#define ELF_R_TYPE(i)        ELF64_R_TYPE(i)

/****************************************************************************
 * Public Type Definitions
 ****************************************************************************/

/* Table 1: ELF-64 Data Types */

typedef uint64_t Elf64_Addr;    /* Unsigned program address */
typedef uint64_t Elf64_Off;     /* Unsigned file offset */
typedef uint16_t Elf64_Half;    /* Unsigned medium integer */
typedef uint32_t Elf64_Word;    /* Unsigned long integer */
typedef int32_t  Elf64_Sword;   /* Signed integer */
typedef uint64_t Elf64_Xword;   /* Unsigned long integer */
typedef int64_t  Elf64_Sxword;  /* Signed large integer */

/* Figure 2: ELF-64 Header */

typedef struct
{
  unsigned char e_ident[EI_NIDENT]; /* ELF identification */
  Elf64_Half    e_type;             /* Object file type */
  Elf64_Half    e_machine;          /* Machine type */
  Elf64_Word    e_version;          /* Object file version */
  Elf64_Addr    e_entry;            /* Entry point address */
  Elf64_Off     e_phoff;            /* Program header offset */
  Elf64_Off     e_shoff;            /* Section header offset */
  Elf64_Word    e_flags;            /* Processor-specific flags */
  Elf64_Half    e_ehsize;           /* ELF header size */
  Elf64_Half    e_phentsize;        /* Size of program header entry */
  Elf64_Half    e_phnum;            /* Number of program header entry */
  Elf64_Half    e_shentsize;        /* Size of section header entry */
  Elf64_Half    e_shnum;            /* Number of section header entries */
  Elf64_Half    e_shstrndx;         /* Section name string table index */
} Elf64_Ehdr;

/* Figure 3: ELF-64 Section Header */

typedef struct
{
  Elf64_Word    sh_name;       /* Section name */
  Elf64_Word    sh_type;       /* Section type */
  Elf64_Xword   sh_flags;      /* Section attributes */
  Elf64_Addr    sh_addr;       /* Virtual address in memory */
  Elf64_Off     sh_offset;     /* Offset in file */
  Elf64_Xword   sh_size;       /* Size of section */
  Elf64_Word    sh_link;       /* Link to other section */
  Elf64_Word    sh_info;       /* Miscellaneous information */
  Elf64_Xword   sh_addralign;  /* Address alignment boundary */
  Elf64_Xword   sh_entsize;    /* Size of entries, if section has table */
} Elf64_Shdr;

/* Figure 4: ELF-64 Symbol Table Entry */

typedef struct
{
  Elf64_Word    st_name;   /* Symbol name */
  unsigned char st_info;   /* Type and Binding attributes */
  unsigned char st_other;  /* Reserved */
  Elf64_Half    st_shndx;  /* Section table index */
  Elf64_Addr    st_value;  /* Symbol value */
  Elf64_Xword   st_size;   /* Size of object (e.g., common) */
} Elf64_Sym;

/* Figure 5: ELF-64 Relocation Entries */

typedef struct
{
  Elf64_Addr    r_offset; /* Address of reference */
  Elf64_Xword   r_info;   /* Symbol index and type of relocation */
} Elf64_Rel;

typedef struct
{
  Elf64_Addr    r_offset; /* Address of reference */
  Elf64_Xword   r_info;   /* Symbol index and type of relocation */
  Elf64_Sxword  r_addend; /* Constant part of expression */
} Elf64_Rela;

/* Figure 6: ELF-64 Program Header Table Entry */

typedef struct
{
  Elf64_Word    p_type;     /* Type of segment */
  Elf64_Word    p_flags;    /* Segment attributes */
  Elf64_Off     p_offset;   /* Offset in file */
  Elf64_Addr    p_vaddr;    /* Virtual address in memory */
  Elf64_Addr    p_paddr;    /* Reserved */
  Elf64_Xword   p_filesz;   /* Size of segment in file */
  Elf64_Xword   p_memsz;    /* Size of segment in memory */
  Elf64_Xword   p_align;    /* Alignment of segment */
} Elf64_Phdr;

/* Figure 7. Format of a Note Section */

typedef struct
{
  Elf64_Word    n_namesz;   /* Length of the note's name.  */
  Elf64_Word    n_descsz;   /* Length of the note's descriptor.  */
  Elf64_Word    n_type;     /* Type of the note.  */
} Elf64_Nhdr;

/* Figure 8: Dynamic Table Structure */

typedef struct
{
  Elf64_Sxword  d_tag;
  union
  {
    Elf64_Xword d_val;
    Elf64_Addr  d_ptr;
  } d_un;
} Elf64_Dyn;

typedef Elf64_Addr Elf_Addr;
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Rel  Elf_Rel;
typedef Elf64_Rela Elf_Rela;
typedef Elf64_Nhdr Elf_Nhdr;
typedef Elf64_Phdr Elf_Phdr;
typedef Elf64_Sym  Elf_Sym;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Off  Elf_Off;
typedef Elf64_Word Elf_Word;
typedef Elf64_Dyn  Elf_Dyn;

#endif /* __INCLUDE_ELF64_H */