1/*
2 * Copyright (c) 1999-2004 University of New South Wales
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <strops.h>
8#include <binaries/elf/elf.h>
9
10/*
11 * Checks that elfFile points to a valid elf file. Returns 0 if the elf
12 * file is valid, < 0 if invalid.
13 */
14
15int
16elf_checkFile(void *elfFile)
17{
18    return ISELF32 (elfFile)
19           ? elf32_checkFile(elfFile)
20           : elf64_checkFile(elfFile);
21}
22
23/* Program Headers Access functions */
24uint16_t
25elf_getNumProgramHeaders(void *elfFile)
26{
27    return ISELF32 (elfFile)
28           ? elf32_getNumProgramHeaders(elfFile)
29           : elf64_getNumProgramHeaders(elfFile);
30}
31
32uint32_t
33elf_getProgramHeaderFlags(void *elfFile, uint16_t ph)
34{
35    return ISELF32 (elfFile)
36           ? elf32_getProgramHeaderFlags(elfFile, ph)
37           : elf64_getProgramHeaderFlags(elfFile, ph);
38}
39
40uint32_t
41elf_getProgramHeaderType(void *elfFile, uint16_t ph)
42{
43    return ISELF32 (elfFile)
44           ? elf32_getProgramHeaderType(elfFile, ph)
45           : elf64_getProgramHeaderType(elfFile, ph);
46}
47
48uint64_t
49elf_getProgramHeaderPaddr(void *elfFile, uint16_t ph)
50{
51    return ISELF32 (elfFile)
52           ? elf32_getProgramHeaderPaddr(elfFile, ph)
53           : elf64_getProgramHeaderPaddr(elfFile, ph);
54}
55
56uint64_t
57elf_getProgramHeaderVaddr(void *elfFile, uint16_t ph)
58{
59    return ISELF32 (elfFile)
60           ? elf32_getProgramHeaderVaddr(elfFile, ph)
61           : elf64_getProgramHeaderVaddr(elfFile, ph);
62}
63
64uint64_t
65elf_getProgramHeaderMemorySize(void *elfFile, uint16_t ph)
66{
67    return ISELF32 (elfFile)
68           ? elf32_getProgramHeaderMemorySize(elfFile, ph)
69           : elf64_getProgramHeaderMemorySize(elfFile, ph);
70}
71
72uint64_t
73elf_getProgramHeaderFileSize(void *elfFile, uint16_t ph)
74{
75    return ISELF32 (elfFile)
76           ? elf32_getProgramHeaderFileSize(elfFile, ph)
77           : elf64_getProgramHeaderFileSize(elfFile, ph);
78}
79
80uint64_t
81elf_getProgramHeaderOffset(void *elfFile, uint16_t ph)
82{
83    return ISELF32 (elfFile)
84           ? elf32_getProgramHeaderOffset(elfFile, ph)
85           : elf64_getProgramHeaderOffset(elfFile, ph);
86}
87
88char *
89elf_getSegmentStringTable(void *elfFile)
90{
91    return ISELF32 (elfFile)
92           ? elf32_getSegmentStringTable(elfFile)
93           : elf64_getSegmentStringTable(elfFile);
94}
95
96char *
97elf_getStringTable(void *elfFile, int string_segment)
98{
99    return ISELF32 (elfFile)
100           ? elf32_getStringTable(elfFile)
101           : elf64_getStringTable(elfFile, string_segment);
102}
103
104unsigned
105elf_getNumSections(void *elfFile)
106{
107    return ISELF32 (elfFile)
108           ? elf32_getNumSections(elfFile)
109           : elf64_getNumSections(elfFile);
110}
111
112char *
113elf_getSectionName(void *elfFile, int i)
114{
115    return ISELF32 (elfFile)
116           ? elf32_getSectionName(elfFile, i)
117           : elf64_getSectionName(elfFile, i);
118}
119
120uint32_t
121elf_getSectionFlags(void *elfFile, int i)
122{
123    return ISELF32 (elfFile)
124           ? elf32_getSectionFlags(elfFile, i)
125           : elf64_getSectionFlags(elfFile, i);
126}
127
128uint32_t
129elf_getSectionType(void *elfFile, int i)
130{
131    return ISELF32 (elfFile)
132           ? elf32_getSectionType(elfFile, i)
133           : elf64_getSectionType(elfFile, i);
134}
135
136uint64_t
137elf_getSectionSize(void *elfFile, int i)
138{
139    return ISELF32 (elfFile)
140           ? elf32_getSectionSize(elfFile, i)
141           : elf64_getSectionSize(elfFile, i);
142}
143
144uint64_t
145elf_getSectionAddr(void *elfFile, int i)
146{
147    return ISELF32 (elfFile)
148           ? elf32_getSectionAddr(elfFile, i)
149           : elf64_getSectionAddr(elfFile, i);
150}
151
152void *
153elf_getSection(void *elfFile, int i)
154{
155    return ISELF32 (elfFile)
156           ? elf32_getSection(elfFile, i)
157           : elf64_getSection(elfFile, i);
158}
159
160void *
161elf_getSectionNamed(void *elfFile, char *_str)
162{
163    return ISELF32 (elfFile)
164           ? elf32_getSectionNamed(elfFile, _str)
165           : elf64_getSectionNamed(elfFile, _str);
166}
167
168void
169elf_getProgramHeaderInfo(void *elfFile, uint16_t ph, uint64_t *p_vaddr,
170                         uint64_t *p_paddr, uint64_t *p_filesz, uint64_t *p_offset,
171                         uint64_t *p_memsz)
172{
173    *p_vaddr = elf_getProgramHeaderVaddr(elfFile, ph);
174    *p_paddr = elf_getProgramHeaderPaddr(elfFile, ph);
175    *p_filesz = elf_getProgramHeaderFileSize(elfFile, ph);
176    *p_offset = elf_getProgramHeaderOffset(elfFile, ph);
177    *p_memsz = elf_getProgramHeaderMemorySize(elfFile, ph);
178}
179
180uint64_t
181elf_getEntryPoint(void *elfFile)
182{
183    return ISELF32 (elfFile)
184           ? elf32_getEntryPoint (elfFile)
185           : elf64_getEntryPoint (elfFile);
186}
187
188int
189elf_getMemoryBounds(void *elfFile, int phys, uint64_t *min, uint64_t *max)
190{
191    uint64_t mem_min = UINT64_MAX;
192    uint64_t mem_max = 0;
193    int i;
194
195    if (elf_checkFile(elfFile) != 0) {
196        return 0;
197    }
198
199    for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) {
200        uint64_t sect_min, sect_max;
201
202        if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) {
203            continue;
204        }
205
206        if (phys) {
207            sect_min = elf_getProgramHeaderPaddr(elfFile, i);
208        } else {
209            sect_min = elf_getProgramHeaderVaddr(elfFile, i);
210        }
211
212        sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i);
213
214        if (sect_max > mem_max) {
215            mem_max = sect_max;
216        }
217        if (sect_min < mem_min) {
218            mem_min = sect_min;
219        }
220    }
221    *min = mem_min;
222    *max = mem_max;
223
224    return 1;
225}
226
227int
228elf_vaddrInProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr)
229{
230    uint64_t min = elf_getProgramHeaderVaddr(elfFile, ph);
231    uint64_t max = min + elf_getProgramHeaderMemorySize(elfFile, ph);
232    if (vaddr >= min && vaddr < max) {
233        return 1;
234    } else {
235        return 0;
236    }
237}
238
239uint64_t
240elf_vtopProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr)
241{
242    uint64_t ph_phys = elf_getProgramHeaderPaddr(elfFile, ph);
243    uint64_t ph_virt = elf_getProgramHeaderVaddr(elfFile, ph);
244    uint64_t paddr;
245
246    paddr = vaddr - ph_virt + ph_phys;
247
248    return paddr;
249}
250
251int
252elf_loadFile(void *elfFile, int phys)
253{
254    int i;
255
256    if (elf_checkFile(elfFile) != 0) {
257        return 0;
258    }
259
260    for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) {
261        /* Load that section */
262        uint64_t dest, src;
263        size_t len;
264        if (phys) {
265            dest = elf_getProgramHeaderPaddr(elfFile, i);
266        } else {
267            dest = elf_getProgramHeaderVaddr(elfFile, i);
268        }
269        len = elf_getProgramHeaderFileSize(elfFile, i);
270        src = (uint64_t) (uintptr_t) elfFile + elf_getProgramHeaderOffset(elfFile, i);
271        memcpy((void*) (uintptr_t) dest, (void*) (uintptr_t) src, len);
272        dest += len;
273        memset((void*) (uintptr_t) dest, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len);
274    }
275
276    return 1;
277}
278