1/*
2 * Copyright (c) 1999-2004 University of New South Wales
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#pragma once
8
9#include <types.h>
10
11#define R_AARCH64_NONE            0	/* No relocation.  */
12#define R_AARCH64_RELATIVE     1027	/* Adjust by program base.  */
13#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
14/*
15 * File header
16 */
17struct Elf64_Header {
18    unsigned char   e_ident[16];
19    uint16_t        e_type;	/* Relocatable=1, Executable=2 (+ some
20				 * more ..) */
21    uint16_t        e_machine;	/* Target architecture: MIPS=8 */
22    uint32_t        e_version;	/* Elf version (should be 1) */
23    uint64_t        e_entry;	/* Code entry point */
24    uint64_t        e_phoff;	/* Program header table */
25    uint64_t        e_shoff;	/* Section header table */
26    uint32_t        e_flags;	/* Flags */
27    uint16_t        e_ehsize;	/* ELF header size */
28    uint16_t        e_phentsize;	/* Size of one program segment
29					 * header */
30    uint16_t        e_phnum;	/* Number of program segment
31					 * headers */
32    uint16_t        e_shentsize;	/* Size of one section header */
33    uint16_t        e_shnum;	/* Number of section headers */
34    uint16_t        e_shstrndx;	/* Section header index of the
35					 * string table for section header
36					 * * names */
37};
38
39/*
40 * Section header
41*/
42struct Elf64_Shdr {
43    uint32_t        sh_name;
44    uint32_t        sh_type;
45    uint64_t        sh_flags;
46    uint64_t        sh_addr;
47    uint64_t        sh_offset;
48    uint64_t        sh_size;
49    uint32_t        sh_link;
50    uint32_t        sh_info;
51    uint64_t        sh_addralign;
52    uint64_t        sh_entsize;
53};
54
55/*
56 * Program header
57 */
58struct Elf64_Phdr {
59    uint32_t        p_type;	/* Segment type: Loadable segment = 1 */
60    uint32_t        p_flags;	/* Flags: logical "or" of PF_
61					 * constants below */
62    uint64_t        p_offset;	/* Offset of segment in file */
63    uint64_t        p_vaddr;	/* Reqd virtual address of segment
64					 * when loading */
65    uint64_t        p_paddr;	/* Reqd physical address of
66					 * segment */
67    uint64_t        p_filesz;	/* How many bytes this segment
68					 * occupies in file */
69    uint64_t        p_memsz;	/* How many bytes this segment
70					 * should occupy in * memory (when
71					 * * loading, expand the segment
72					 * by * concatenating enough zero
73					 * bytes to it) */
74    uint64_t        p_align;	/* Reqd alignment of segment in
75					 * memory */
76};
77
78/*
79 * Dynamic section
80 */
81struct Elf64_Dyn {
82    uint64_t d_tag;
83    union {
84        uint64_t d_val;
85        uint64_t d_ptr;
86    } d_un;
87};
88
89struct Elf64_Rela {
90    uint64_t r_offset;		/* Address */
91    uint64_t r_info;			/* Relocation type and symbol index */
92    uint64_t r_addend;		/* Addend */
93};
94
95int elf64_checkFile(void *elfFile);
96struct Elf64_Phdr * elf64_getProgramSegmentTable(void *elfFile);
97unsigned elf64_getNumSections(void *elfFile);
98char * elf64_getStringTable(void *elfFile, int string_segment);
99char * elf64_getSegmentStringTable(void *elfFile);
100
101/* Assume the field is at least 4-byte aligned and little-endian */
102static uint64_t elf64_read64(void *addr)
103{
104    uint64_t ret;
105    if (((uintptr_t)addr) % 8 == 0) {
106        ret = *((uint64_t *)addr);
107    } else {
108        ret = *((uint32_t *)(((uintptr_t)addr) + 4));
109        ret = ret << 32;
110        ret |= *((uint32_t *)addr);
111    }
112    return ret;
113}
114
115static inline struct Elf64_Shdr *
116elf64_getSectionTable(struct Elf64_Header *file) {
117    /* Cast heaven! */
118    return (struct Elf64_Shdr*) (uintptr_t) (((uintptr_t) file) + file->e_shoff);
119}
120
121/* accessor functions */
122static inline uint32_t
123elf64_getSectionType(struct Elf64_Header *file, uint16_t s)
124{
125    return elf64_getSectionTable(file)[s].sh_type;
126}
127
128static inline uint32_t
129elf64_getSectionFlags(struct Elf64_Header *file, uint16_t s)
130{
131    return elf64_getSectionTable(file)[s].sh_flags;
132}
133
134char * elf64_getSectionName(void *elfFile, int i);
135uint64_t elf64_getSectionSize(void *elfFile, int i);
136uint64_t elf64_getSectionAddr(struct Elf64_Header *elfFile, int i);
137void * elf64_getSection(void *elfFile, int i);
138void * elf64_getSectionNamed(void *elfFile, char *str);
139int elf64_getSegmentType (void *elfFile, int segment);
140void elf64_getSegmentInfo(void *elfFile, int segment, uint64_t *p_vaddr,
141                          uint64_t *p_paddr, uint64_t *p_filesz,
142                          uint64_t *p_offset, uint64_t *p_memsz);
143void elf64_showDetails(void *elfFile, int size, char *name);
144uint64_t elf64_getEntryPoint (struct Elf64_Header *elfFile);
145
146/* Program Headers functions */
147/* Program header functions */
148uint16_t elf64_getNumProgramHeaders(struct Elf64_Header *file);
149
150static inline struct Elf64_Phdr *
151elf64_getProgramHeaderTable(struct Elf64_Header *file) {
152    /* Cast hell! */
153    uint64_t e_phoff = elf64_read64(&file->e_phoff);
154    return (struct Elf64_Phdr*) (uintptr_t) (((uintptr_t) file) + e_phoff);
155}
156
157/* accessor functions */
158static inline uint32_t
159elf64_getProgramHeaderFlags(struct Elf64_Header *file, uint16_t ph)
160{
161    return elf64_getProgramHeaderTable(file)[ph].p_flags;
162}
163
164static inline uint32_t
165elf64_getProgramHeaderType(struct Elf64_Header *file, uint16_t ph)
166{
167    return elf64_getProgramHeaderTable(file)[ph].p_type;
168}
169
170static inline uint64_t
171elf64_getProgramHeaderFileSize(struct Elf64_Header *file, uint16_t ph)
172{
173    struct Elf64_Phdr  *phdr = &elf64_getProgramHeaderTable(file)[ph];
174    return elf64_read64(&phdr->p_filesz);
175}
176
177static inline uint64_t
178elf64_getProgramHeaderMemorySize(struct Elf64_Header *file, uint16_t ph)
179{
180    struct Elf64_Phdr  *phdr = &elf64_getProgramHeaderTable(file)[ph];
181    return elf64_read64(&phdr->p_memsz);
182}
183
184static inline uint64_t
185elf64_getProgramHeaderVaddr(struct Elf64_Header *file, uint16_t ph)
186{
187    struct Elf64_Phdr  *phdr = &elf64_getProgramHeaderTable(file)[ph];
188    return elf64_read64(&phdr->p_vaddr);
189}
190
191static inline uint64_t
192elf64_getProgramHeaderPaddr(struct Elf64_Header *file, uint16_t ph)
193{
194    struct Elf64_Phdr  *phdr = &elf64_getProgramHeaderTable(file)[ph];
195    return elf64_read64(&phdr->p_paddr);
196}
197
198static inline uint64_t
199elf64_getProgramHeaderOffset(struct Elf64_Header *file, uint16_t ph)
200{
201    struct Elf64_Phdr  *phdr = &elf64_getProgramHeaderTable(file)[ph];
202    return elf64_read64(&phdr->p_offset);
203}
204
205