blob: 05751f3ce71f169bf471542baa2c3ced01af72c3 [file] [log] [blame]
Warner Losh310df052021-08-06 12:05:02 -06001/*
2 * ELF loading code
3 *
4 * Copyright (c) 2013 Stacey D. Son
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
blueswir184778502008-10-26 20:33:16 +000019
Peter Maydell22311972016-01-29 17:49:53 +000020#include "qemu/osdep.h"
blueswir184778502008-10-26 20:33:16 +000021
22#include "qemu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020023#include "disas/disas.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020024#include "qemu/path.h"
blueswir184778502008-10-26 20:33:16 +000025
Warner Losh98b34d32021-08-04 17:13:24 -060026static abi_ulong target_auxents; /* Where the AUX entries are in target */
27static size_t target_auxents_sz; /* Size of AUX entries including AT_NULL */
28
Warner Losh0475f8f2021-08-06 14:20:16 -060029#include "target_arch_reg.h"
Warner Losh98b34d32021-08-04 17:13:24 -060030#include "target_os_elf.h"
31#include "target_os_stack.h"
Warner Losha8fe6d52021-08-03 22:04:20 -060032#include "target_os_thread.h"
Warner Losh0475f8f2021-08-06 14:20:16 -060033#include "target_os_user.h"
blueswir184778502008-10-26 20:33:16 +000034
Warner Losh98b34d32021-08-04 17:13:24 -060035abi_ulong target_stksiz;
36abi_ulong target_stkbas;
blueswir184778502008-10-26 20:33:16 +000037
Warner Losh0475f8f2021-08-06 14:20:16 -060038static int elf_core_dump(int signr, CPUArchState *env);
39
Warner Loshb4bebee2021-04-23 09:05:57 -060040static inline void memcpy_fromfs(void *to, const void *from, unsigned long n)
blueswir184778502008-10-26 20:33:16 +000041{
Warner Loshb62f7902021-08-02 22:59:12 -060042 memcpy(to, from, n);
blueswir184778502008-10-26 20:33:16 +000043}
44
blueswir184778502008-10-26 20:33:16 +000045#ifdef BSWAP_NEEDED
46static void bswap_ehdr(struct elfhdr *ehdr)
47{
Warner Loshb62f7902021-08-02 22:59:12 -060048 bswap16s(&ehdr->e_type); /* Object file type */
blueswir184778502008-10-26 20:33:16 +000049 bswap16s(&ehdr->e_machine); /* Architecture */
50 bswap32s(&ehdr->e_version); /* Object file version */
51 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
52 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
53 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
54 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
55 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
Warner Loshb62f7902021-08-02 22:59:12 -060056 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
blueswir184778502008-10-26 20:33:16 +000057 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
Warner Loshb62f7902021-08-02 22:59:12 -060058 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
blueswir184778502008-10-26 20:33:16 +000059 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
Warner Loshb62f7902021-08-02 22:59:12 -060060 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
blueswir184778502008-10-26 20:33:16 +000061}
62
Warner Loshb62f7902021-08-02 22:59:12 -060063static void bswap_phdr(struct elf_phdr *phdr, int phnum)
blueswir184778502008-10-26 20:33:16 +000064{
Warner Loshb62f7902021-08-02 22:59:12 -060065 int i;
66
67 for (i = 0; i < phnum; i++, phdr++) {
68 bswap32s(&phdr->p_type); /* Segment type */
69 bswap32s(&phdr->p_flags); /* Segment flags */
70 bswaptls(&phdr->p_offset); /* Segment file offset */
71 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
72 bswaptls(&phdr->p_paddr); /* Segment physical address */
73 bswaptls(&phdr->p_filesz); /* Segment size in file */
74 bswaptls(&phdr->p_memsz); /* Segment size in memory */
75 bswaptls(&phdr->p_align); /* Segment alignment */
76 }
blueswir184778502008-10-26 20:33:16 +000077}
78
Warner Loshb62f7902021-08-02 22:59:12 -060079static void bswap_shdr(struct elf_shdr *shdr, int shnum)
blueswir184778502008-10-26 20:33:16 +000080{
Warner Loshb62f7902021-08-02 22:59:12 -060081 int i;
82
83 for (i = 0; i < shnum; i++, shdr++) {
84 bswap32s(&shdr->sh_name);
85 bswap32s(&shdr->sh_type);
86 bswaptls(&shdr->sh_flags);
87 bswaptls(&shdr->sh_addr);
88 bswaptls(&shdr->sh_offset);
89 bswaptls(&shdr->sh_size);
90 bswap32s(&shdr->sh_link);
91 bswap32s(&shdr->sh_info);
92 bswaptls(&shdr->sh_addralign);
93 bswaptls(&shdr->sh_entsize);
94 }
blueswir184778502008-10-26 20:33:16 +000095}
96
97static void bswap_sym(struct elf_sym *sym)
98{
99 bswap32s(&sym->st_name);
100 bswaptls(&sym->st_value);
101 bswaptls(&sym->st_size);
102 bswap16s(&sym->st_shndx);
103}
Warner Loshb62f7902021-08-02 22:59:12 -0600104
Warner Losh0475f8f2021-08-06 14:20:16 -0600105static void bswap_note(struct elf_note *en)
106{
107 bswap32s(&en->n_namesz);
108 bswap32s(&en->n_descsz);
109 bswap32s(&en->n_type);
110}
111
Warner Loshb62f7902021-08-02 22:59:12 -0600112#else /* ! BSWAP_NEEDED */
113
114static void bswap_ehdr(struct elfhdr *ehdr) { }
115static void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
116static void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
117static void bswap_sym(struct elf_sym *sym) { }
Warner Losh0475f8f2021-08-06 14:20:16 -0600118static void bswap_note(struct elf_note *en) { }
Warner Loshb62f7902021-08-02 22:59:12 -0600119
120#endif /* ! BSWAP_NEEDED */
blueswir184778502008-10-26 20:33:16 +0000121
Warner Losh0475f8f2021-08-06 14:20:16 -0600122#include "elfcore.c"
123
blueswir184778502008-10-26 20:33:16 +0000124/*
125 * 'copy_elf_strings()' copies argument/envelope strings from user
126 * memory to free pages in kernel mem. These are in a format ready
127 * to be put directly into the top of new user memory.
128 *
129 */
Warner Loshb4bebee2021-04-23 09:05:57 -0600130static abi_ulong copy_elf_strings(int argc, char **argv, void **page,
blueswir184778502008-10-26 20:33:16 +0000131 abi_ulong p)
132{
133 char *tmp, *tmp1, *pag = NULL;
134 int len, offset = 0;
135
136 if (!p) {
137 return 0; /* bullet-proofing */
138 }
139 while (argc-- > 0) {
140 tmp = argv[argc];
141 if (!tmp) {
Peter Maydell9bb93182014-06-02 13:24:37 +0100142 fprintf(stderr, "VFS: argc is wrong");
blueswir184778502008-10-26 20:33:16 +0000143 exit(-1);
144 }
145 tmp1 = tmp;
146 while (*tmp++);
147 len = tmp - tmp1;
148 if (p < len) { /* this shouldn't happen - 128kB */
149 return 0;
150 }
151 while (len) {
152 --p; --tmp; --len;
153 if (--offset < 0) {
154 offset = p % TARGET_PAGE_SIZE;
Warner Loshb4bebee2021-04-23 09:05:57 -0600155 pag = (char *)page[p / TARGET_PAGE_SIZE];
blueswir184778502008-10-26 20:33:16 +0000156 if (!pag) {
Stefan Weilc580dee2011-11-21 21:06:22 +0100157 pag = g_try_malloc0(TARGET_PAGE_SIZE);
Warner Loshb4bebee2021-04-23 09:05:57 -0600158 page[p / TARGET_PAGE_SIZE] = pag;
blueswir184778502008-10-26 20:33:16 +0000159 if (!pag)
160 return 0;
161 }
162 }
163 if (len == 0 || offset == 0) {
164 *(pag + offset) = *tmp;
165 }
166 else {
167 int bytes_to_copy = (len > offset) ? offset : len;
168 tmp -= bytes_to_copy;
169 p -= bytes_to_copy;
170 offset -= bytes_to_copy;
171 len -= bytes_to_copy;
172 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
173 }
174 }
175 }
176 return p;
177}
178
Warner Losh98b34d32021-08-04 17:13:24 -0600179static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
180 abi_ulong *stackp, abi_ulong *stringp)
blueswir184778502008-10-26 20:33:16 +0000181{
Warner Losh98b34d32021-08-04 17:13:24 -0600182 abi_ulong stack_base, size;
183 abi_long addr;
blueswir184778502008-10-26 20:33:16 +0000184
185 /* Create enough stack to hold everything. If we don't use
186 * it for args, we'll use it for something else...
187 */
Warner Losh312a0b12021-08-06 18:48:37 -0600188 size = target_dflssiz;
Warner Losh98b34d32021-08-04 17:13:24 -0600189 stack_base = TARGET_USRSTACK - size;
190 addr = target_mmap(stack_base,
blueswir184778502008-10-26 20:33:16 +0000191 size + qemu_host_page_size,
192 PROT_READ | PROT_WRITE,
193 MAP_PRIVATE | MAP_ANON,
194 -1, 0);
Warner Losh98b34d32021-08-04 17:13:24 -0600195 if (addr == -1) {
blueswir184778502008-10-26 20:33:16 +0000196 perror("stk mmap");
197 exit(-1);
198 }
199 /* we reserve one extra page at the top of the stack as guard */
Warner Losh98b34d32021-08-04 17:13:24 -0600200 target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
blueswir184778502008-10-26 20:33:16 +0000201
Warner Losh98b34d32021-08-04 17:13:24 -0600202 target_stksiz = size;
203 target_stkbas = addr;
blueswir184778502008-10-26 20:33:16 +0000204
Warner Losh98b34d32021-08-04 17:13:24 -0600205 if (setup_initial_stack(bprm, stackp, stringp) != 0) {
206 perror("stk setup");
207 exit(-1);
blueswir184778502008-10-26 20:33:16 +0000208 }
blueswir184778502008-10-26 20:33:16 +0000209}
210
211static void set_brk(abi_ulong start, abi_ulong end)
212{
213 /* page-align the start and end addresses... */
214 start = HOST_PAGE_ALIGN(start);
215 end = HOST_PAGE_ALIGN(end);
216 if (end <= start)
217 return;
Warner Loshb4bebee2021-04-23 09:05:57 -0600218 if (target_mmap(start, end - start,
blueswir184778502008-10-26 20:33:16 +0000219 PROT_READ | PROT_WRITE | PROT_EXEC,
220 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) {
221 perror("cannot mmap brk");
222 exit(-1);
223 }
224}
225
226
227/* We need to explicitly zero any fractional pages after the data
228 section (i.e. bss). This would contain the junk from the file that
229 should not be in memory. */
230static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
231{
232 abi_ulong nbyte;
233
234 if (elf_bss >= last_bss)
235 return;
236
237 /* XXX: this is really a hack : if the real host page size is
238 smaller than the target page size, some pages after the end
239 of the file may not be mapped. A better fix would be to
240 patch target_mmap(), but it is more complicated as the file
241 size must be known */
242 if (qemu_real_host_page_size < qemu_host_page_size) {
243 abi_ulong end_addr, end_addr1;
Paolo Bonzini0c2d70c2015-12-02 13:00:54 +0100244 end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
blueswir184778502008-10-26 20:33:16 +0000245 end_addr = HOST_PAGE_ALIGN(elf_bss);
246 if (end_addr1 < end_addr) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800247 mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
Warner Loshb4bebee2021-04-23 09:05:57 -0600248 PROT_READ | PROT_WRITE | PROT_EXEC,
249 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
blueswir184778502008-10-26 20:33:16 +0000250 }
251 }
252
Warner Loshb4bebee2021-04-23 09:05:57 -0600253 nbyte = elf_bss & (qemu_host_page_size - 1);
blueswir184778502008-10-26 20:33:16 +0000254 if (nbyte) {
255 nbyte = qemu_host_page_size - nbyte;
256 do {
257 /* FIXME - what to do if put_user() fails? */
258 put_user_u8(0, elf_bss);
259 elf_bss++;
260 } while (--nbyte);
261 }
262}
263
Warner Loshb4bebee2021-04-23 09:05:57 -0600264static abi_ulong load_elf_interp(struct elfhdr *interp_elf_ex,
blueswir184778502008-10-26 20:33:16 +0000265 int interpreter_fd,
266 abi_ulong *interp_load_addr)
267{
Warner Loshb4bebee2021-04-23 09:05:57 -0600268 struct elf_phdr *elf_phdata = NULL;
269 struct elf_phdr *eppnt;
270 abi_ulong load_addr = 0;
271 int load_addr_set = 0;
272 int retval;
273 abi_ulong last_bss, elf_bss;
274 abi_ulong error;
275 int i;
blueswir184778502008-10-26 20:33:16 +0000276
Warner Loshb4bebee2021-04-23 09:05:57 -0600277 elf_bss = 0;
278 last_bss = 0;
279 error = 0;
blueswir184778502008-10-26 20:33:16 +0000280
Warner Loshb4bebee2021-04-23 09:05:57 -0600281 bswap_ehdr(interp_elf_ex);
Warner Loshb4bebee2021-04-23 09:05:57 -0600282 /* First of all, some simple consistency checks */
283 if ((interp_elf_ex->e_type != ET_EXEC &&
284 interp_elf_ex->e_type != ET_DYN) ||
285 !elf_check_arch(interp_elf_ex->e_machine)) {
286 return ~((abi_ulong)0UL);
287 }
blueswir184778502008-10-26 20:33:16 +0000288
289
Warner Loshb4bebee2021-04-23 09:05:57 -0600290 /* Now read in all of the header information */
blueswir184778502008-10-26 20:33:16 +0000291
Warner Loshb4bebee2021-04-23 09:05:57 -0600292 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
293 return ~(abi_ulong)0UL;
blueswir184778502008-10-26 20:33:16 +0000294
Warner Loshb4bebee2021-04-23 09:05:57 -0600295 elf_phdata = (struct elf_phdr *)
296 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
blueswir184778502008-10-26 20:33:16 +0000297
Warner Loshb4bebee2021-04-23 09:05:57 -0600298 if (!elf_phdata)
299 return ~((abi_ulong)0UL);
blueswir184778502008-10-26 20:33:16 +0000300
Warner Loshb4bebee2021-04-23 09:05:57 -0600301 /*
302 * If the size of this structure has changed, then punt, since
303 * we will be doing the wrong thing.
304 */
305 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
306 free(elf_phdata);
307 return ~((abi_ulong)0UL);
308 }
blueswir184778502008-10-26 20:33:16 +0000309
Warner Loshb4bebee2021-04-23 09:05:57 -0600310 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
311 if (retval >= 0) {
312 retval = read(interpreter_fd,
313 (char *) elf_phdata,
314 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
315 }
316 if (retval < 0) {
317 perror("load_elf_interp");
318 exit(-1);
Warner Loshffa03662021-04-30 08:17:23 -0600319 free(elf_phdata);
Warner Loshb4bebee2021-04-23 09:05:57 -0600320 return retval;
321 }
Warner Loshb62f7902021-08-02 22:59:12 -0600322 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
blueswir184778502008-10-26 20:33:16 +0000323
Warner Loshb4bebee2021-04-23 09:05:57 -0600324 if (interp_elf_ex->e_type == ET_DYN) {
325 /* in order to avoid hardcoding the interpreter load
326 address in qemu, we allocate a big enough memory zone */
327 error = target_mmap(0, INTERP_MAP_SIZE,
328 PROT_NONE, MAP_PRIVATE | MAP_ANON,
329 -1, 0);
330 if (error == -1) {
331 perror("mmap");
332 exit(-1);
blueswir184778502008-10-26 20:33:16 +0000333 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600334 load_addr = error;
335 load_addr_set = 1;
336 }
blueswir184778502008-10-26 20:33:16 +0000337
Warner Loshb4bebee2021-04-23 09:05:57 -0600338 eppnt = elf_phdata;
339 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++)
340 if (eppnt->p_type == PT_LOAD) {
blueswir184778502008-10-26 20:33:16 +0000341 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
342 int elf_prot = 0;
343 abi_ulong vaddr = 0;
344 abi_ulong k;
345
346 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
347 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
348 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
349 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
350 elf_type |= MAP_FIXED;
351 vaddr = eppnt->p_vaddr;
352 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600353 error = target_mmap(load_addr + TARGET_ELF_PAGESTART(vaddr),
354 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
355 elf_prot,
356 elf_type,
357 interpreter_fd,
358 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
blueswir184778502008-10-26 20:33:16 +0000359
360 if (error == -1) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600361 /* Real error */
362 close(interpreter_fd);
363 free(elf_phdata);
364 return ~((abi_ulong)0UL);
blueswir184778502008-10-26 20:33:16 +0000365 }
366
367 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600368 load_addr = error;
369 load_addr_set = 1;
blueswir184778502008-10-26 20:33:16 +0000370 }
371
372 /*
373 * Find the end of the file mapping for this phdr, and keep
374 * track of the largest address we see for this.
375 */
376 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
377 if (k > elf_bss) elf_bss = k;
378
379 /*
380 * Do the same thing for the memory mapping - between
381 * elf_bss and last_bss is the bss section.
382 */
383 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
384 if (k > last_bss) last_bss = k;
blueswir184778502008-10-26 20:33:16 +0000385 }
blueswir184778502008-10-26 20:33:16 +0000386
Warner Loshb4bebee2021-04-23 09:05:57 -0600387 /* Now use mmap to map the library into memory. */
388
389 close(interpreter_fd);
390
391 /*
392 * Now fill out the bss section. First pad the last page up
393 * to the page boundary, and then perform a mmap to make sure
394 * that there are zeromapped pages up to and including the last
395 * bss page.
396 */
397 padzero(elf_bss, last_bss);
398 elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
399
400 /* Map the last of the bss segment */
401 if (last_bss > elf_bss) {
402 target_mmap(elf_bss, last_bss - elf_bss,
403 PROT_READ | PROT_WRITE | PROT_EXEC,
404 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
405 }
406 free(elf_phdata);
407
408 *interp_load_addr = load_addr;
409 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
blueswir184778502008-10-26 20:33:16 +0000410}
411
412static int symfind(const void *s0, const void *s1)
413{
Stefan Weilc7c530c2012-01-05 15:39:39 +0100414 target_ulong addr = *(target_ulong *)s0;
blueswir184778502008-10-26 20:33:16 +0000415 struct elf_sym *sym = (struct elf_sym *)s1;
416 int result = 0;
Stefan Weilc7c530c2012-01-05 15:39:39 +0100417 if (addr < sym->st_value) {
blueswir184778502008-10-26 20:33:16 +0000418 result = -1;
Stefan Weilc7c530c2012-01-05 15:39:39 +0100419 } else if (addr >= sym->st_value + sym->st_size) {
blueswir184778502008-10-26 20:33:16 +0000420 result = 1;
421 }
422 return result;
423}
424
425static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
426{
427#if ELF_CLASS == ELFCLASS32
428 struct elf_sym *syms = s->disas_symtab.elf32;
429#else
430 struct elf_sym *syms = s->disas_symtab.elf64;
431#endif
432
433 // binary search
blueswir184778502008-10-26 20:33:16 +0000434 struct elf_sym *sym;
435
Stefan Weilc7c530c2012-01-05 15:39:39 +0100436 sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +0000437 if (sym != NULL) {
blueswir184778502008-10-26 20:33:16 +0000438 return s->disas_strtab + sym->st_name;
439 }
440
441 return "";
442}
443
444/* FIXME: This should use elf_ops.h */
445static int symcmp(const void *s0, const void *s1)
446{
447 struct elf_sym *sym0 = (struct elf_sym *)s0;
448 struct elf_sym *sym1 = (struct elf_sym *)s1;
449 return (sym0->st_value < sym1->st_value)
450 ? -1
451 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
452}
453
454/* Best attempt to load symbols from this ELF object. */
455static void load_symbols(struct elfhdr *hdr, int fd)
456{
457 unsigned int i, nsyms;
458 struct elf_shdr sechdr, symtab, strtab;
459 char *strings;
460 struct syminfo *s;
Stefan Weil29718712011-01-16 16:28:20 +0100461 struct elf_sym *syms, *new_syms;
blueswir184778502008-10-26 20:33:16 +0000462
463 lseek(fd, hdr->e_shoff, SEEK_SET);
464 for (i = 0; i < hdr->e_shnum; i++) {
465 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
466 return;
Warner Loshb62f7902021-08-02 22:59:12 -0600467 bswap_shdr(&sechdr, 1);
blueswir184778502008-10-26 20:33:16 +0000468 if (sechdr.sh_type == SHT_SYMTAB) {
469 symtab = sechdr;
470 lseek(fd, hdr->e_shoff
471 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
472 if (read(fd, &strtab, sizeof(strtab))
473 != sizeof(strtab))
474 return;
Warner Loshb62f7902021-08-02 22:59:12 -0600475 bswap_shdr(&strtab, 1);
blueswir184778502008-10-26 20:33:16 +0000476 goto found;
477 }
478 }
479 return; /* Shouldn't happen... */
480
481 found:
482 /* Now know where the strtab and symtab are. Snarf them. */
483 s = malloc(sizeof(*s));
484 syms = malloc(symtab.sh_size);
Stefan Weil29718712011-01-16 16:28:20 +0100485 if (!syms) {
486 free(s);
blueswir184778502008-10-26 20:33:16 +0000487 return;
Stefan Weil29718712011-01-16 16:28:20 +0100488 }
blueswir184778502008-10-26 20:33:16 +0000489 s->disas_strtab = strings = malloc(strtab.sh_size);
Stefan Weil29718712011-01-16 16:28:20 +0100490 if (!s->disas_strtab) {
491 free(s);
492 free(syms);
blueswir184778502008-10-26 20:33:16 +0000493 return;
Stefan Weil29718712011-01-16 16:28:20 +0100494 }
blueswir184778502008-10-26 20:33:16 +0000495
496 lseek(fd, symtab.sh_offset, SEEK_SET);
Stefan Weil29718712011-01-16 16:28:20 +0100497 if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
498 free(s);
499 free(syms);
500 free(strings);
blueswir184778502008-10-26 20:33:16 +0000501 return;
Stefan Weil29718712011-01-16 16:28:20 +0100502 }
blueswir184778502008-10-26 20:33:16 +0000503
504 nsyms = symtab.sh_size / sizeof(struct elf_sym);
505
506 i = 0;
507 while (i < nsyms) {
blueswir184778502008-10-26 20:33:16 +0000508 bswap_sym(syms + i);
blueswir184778502008-10-26 20:33:16 +0000509 // Throw away entries which we do not need.
510 if (syms[i].st_shndx == SHN_UNDEF ||
511 syms[i].st_shndx >= SHN_LORESERVE ||
512 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
513 nsyms--;
514 if (i < nsyms) {
515 syms[i] = syms[nsyms];
516 }
517 continue;
518 }
blueswir184778502008-10-26 20:33:16 +0000519 i++;
520 }
Stefan Weil29718712011-01-16 16:28:20 +0100521
522 /* Attempt to free the storage associated with the local symbols
523 that we threw away. Whether or not this has any effect on the
524 memory allocation depends on the malloc implementation and how
525 many symbols we managed to discard. */
526 new_syms = realloc(syms, nsyms * sizeof(*syms));
527 if (new_syms == NULL) {
528 free(s);
529 free(syms);
530 free(strings);
531 return;
532 }
533 syms = new_syms;
blueswir184778502008-10-26 20:33:16 +0000534
535 qsort(syms, nsyms, sizeof(*syms), symcmp);
536
537 lseek(fd, strtab.sh_offset, SEEK_SET);
Stefan Weil29718712011-01-16 16:28:20 +0100538 if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
539 free(s);
540 free(syms);
541 free(strings);
blueswir184778502008-10-26 20:33:16 +0000542 return;
Stefan Weil29718712011-01-16 16:28:20 +0100543 }
blueswir184778502008-10-26 20:33:16 +0000544 s->disas_num_syms = nsyms;
545#if ELF_CLASS == ELFCLASS32
546 s->disas_symtab.elf32 = syms;
Blue Swirl032e51d2009-09-27 19:30:56 +0000547 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
blueswir184778502008-10-26 20:33:16 +0000548#else
549 s->disas_symtab.elf64 = syms;
Blue Swirl032e51d2009-09-27 19:30:56 +0000550 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
blueswir184778502008-10-26 20:33:16 +0000551#endif
552 s->next = syminfos;
553 syminfos = s;
554}
555
Warner Loshafcbcff2021-04-29 10:04:28 -0600556int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
Warner Loshb4bebee2021-04-23 09:05:57 -0600557 struct image_info *info)
blueswir184778502008-10-26 20:33:16 +0000558{
559 struct elfhdr elf_ex;
560 struct elfhdr interp_elf_ex;
blueswir184778502008-10-26 20:33:16 +0000561 int interpreter_fd = -1; /* avoid warning */
562 abi_ulong load_addr, load_bias;
563 int load_addr_set = 0;
blueswir184778502008-10-26 20:33:16 +0000564 int i;
blueswir184778502008-10-26 20:33:16 +0000565 struct elf_phdr * elf_ppnt;
566 struct elf_phdr *elf_phdata;
567 abi_ulong elf_bss, k, elf_brk;
568 int retval;
569 char * elf_interpreter;
570 abi_ulong elf_entry, interp_load_addr = 0;
blueswir184778502008-10-26 20:33:16 +0000571 abi_ulong start_code, end_code, start_data, end_data;
572 abi_ulong reloc_func_desc = 0;
blueswir184778502008-10-26 20:33:16 +0000573
blueswir184778502008-10-26 20:33:16 +0000574 load_addr = 0;
575 load_bias = 0;
576 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
blueswir184778502008-10-26 20:33:16 +0000577 bswap_ehdr(&elf_ex);
blueswir184778502008-10-26 20:33:16 +0000578
579 /* First of all, some simple consistency checks */
580 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
Warner Loshb4bebee2021-04-23 09:05:57 -0600581 (!elf_check_arch(elf_ex.e_machine))) {
blueswir184778502008-10-26 20:33:16 +0000582 return -ENOEXEC;
583 }
584
585 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
Warner Loshb4bebee2021-04-23 09:05:57 -0600586 bprm->p = copy_elf_strings(bprm->envc, bprm->envp, bprm->page,bprm->p);
587 bprm->p = copy_elf_strings(bprm->argc, bprm->argv, bprm->page,bprm->p);
blueswir184778502008-10-26 20:33:16 +0000588 if (!bprm->p) {
589 retval = -E2BIG;
590 }
591
592 /* Now read in all of the header information */
593 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
594 if (elf_phdata == NULL) {
595 return -ENOMEM;
596 }
597
598 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600599 if (retval > 0) {
600 retval = read(bprm->fd, (char *)elf_phdata,
blueswir184778502008-10-26 20:33:16 +0000601 elf_ex.e_phentsize * elf_ex.e_phnum);
602 }
603
604 if (retval < 0) {
605 perror("load_elf_binary");
606 exit(-1);
Warner Loshb4bebee2021-04-23 09:05:57 -0600607 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000608 return -errno;
609 }
610
Warner Loshb62f7902021-08-02 22:59:12 -0600611 bswap_phdr(elf_phdata, elf_ex.e_phnum);
612
blueswir184778502008-10-26 20:33:16 +0000613 elf_ppnt = elf_phdata;
614
615 elf_bss = 0;
616 elf_brk = 0;
617
618
blueswir184778502008-10-26 20:33:16 +0000619 elf_interpreter = NULL;
620 start_code = ~((abi_ulong)0UL);
621 end_code = 0;
622 start_data = 0;
623 end_data = 0;
blueswir184778502008-10-26 20:33:16 +0000624
Warner Loshb4bebee2021-04-23 09:05:57 -0600625 for (i = 0;i < elf_ex.e_phnum; i++) {
blueswir184778502008-10-26 20:33:16 +0000626 if (elf_ppnt->p_type == PT_INTERP) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600627 if (elf_interpreter != NULL)
blueswir184778502008-10-26 20:33:16 +0000628 {
Warner Loshb4bebee2021-04-23 09:05:57 -0600629 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000630 free(elf_interpreter);
631 close(bprm->fd);
632 return -EINVAL;
633 }
634
635 /* This is the program interpreter used for
636 * shared libraries - for now assume that this
637 * is an a.out format binary
638 */
639
640 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
641
642 if (elf_interpreter == NULL) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600643 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000644 close(bprm->fd);
645 return -ENOMEM;
646 }
647
648 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600649 if (retval >= 0) {
blueswir184778502008-10-26 20:33:16 +0000650 retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
651 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600652 if (retval < 0) {
blueswir184778502008-10-26 20:33:16 +0000653 perror("load_elf_binary2");
654 exit(-1);
655 }
656
blueswir184778502008-10-26 20:33:16 +0000657 if (retval >= 0) {
658 retval = open(path(elf_interpreter), O_RDONLY);
Warner Loshb4bebee2021-04-23 09:05:57 -0600659 if (retval >= 0) {
blueswir184778502008-10-26 20:33:16 +0000660 interpreter_fd = retval;
661 }
662 else {
663 perror(elf_interpreter);
664 exit(-1);
665 /* retval = -errno; */
666 }
667 }
668
669 if (retval >= 0) {
670 retval = lseek(interpreter_fd, 0, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600671 if (retval >= 0) {
672 retval = read(interpreter_fd, bprm->buf, 128);
blueswir184778502008-10-26 20:33:16 +0000673 }
674 }
675 if (retval >= 0) {
Michael S. Tsirkin6ece4df2009-09-30 19:43:38 +0200676 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
blueswir184778502008-10-26 20:33:16 +0000677 }
678 if (retval < 0) {
679 perror("load_elf_binary3");
680 exit(-1);
Warner Loshb4bebee2021-04-23 09:05:57 -0600681 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000682 free(elf_interpreter);
683 close(bprm->fd);
684 return retval;
685 }
686 }
687 elf_ppnt++;
688 }
689
690 /* Some simple consistency checks for the interpreter */
Warner Loshb4bebee2021-04-23 09:05:57 -0600691 if (elf_interpreter) {
blueswir184778502008-10-26 20:33:16 +0000692 if (interp_elf_ex.e_ident[0] != 0x7f ||
Warner Loshffa03662021-04-30 08:17:23 -0600693 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF", 3) != 0) {
blueswir184778502008-10-26 20:33:16 +0000694 free(elf_interpreter);
695 free(elf_phdata);
696 close(bprm->fd);
697 return -ELIBBAD;
698 }
699 }
700
701 /* OK, we are done with that, now set up the arg stuff,
702 and then start this sucker up */
703
Warner Loshffa03662021-04-30 08:17:23 -0600704 if (!bprm->p) {
705 free(elf_interpreter);
706 free(elf_phdata);
707 close(bprm->fd);
708 return -E2BIG;
blueswir184778502008-10-26 20:33:16 +0000709 }
710
711 /* OK, This is the point of no return */
712 info->end_data = 0;
713 info->end_code = 0;
714 info->start_mmap = (abi_ulong)ELF_START_MMAP;
715 info->mmap = 0;
716 elf_entry = (abi_ulong) elf_ex.e_entry;
717
718 /* Do this so that we can load the interpreter, if need be. We will
719 change some of these later */
720 info->rss = 0;
Warner Losh98b34d32021-08-04 17:13:24 -0600721 setup_arg_pages(bprm, info, &bprm->p, &bprm->stringp);
blueswir184778502008-10-26 20:33:16 +0000722 info->start_stack = bprm->p;
723
724 /* Now we do a little grungy work by mmaping the ELF image into
725 * the correct location in memory. At this point, we assume that
726 * the image should be loaded at fixed address, not at a variable
727 * address.
728 */
729
Warner Loshb4bebee2021-04-23 09:05:57 -0600730 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
blueswir184778502008-10-26 20:33:16 +0000731 int elf_prot = 0;
732 int elf_flags = 0;
733 abi_ulong error;
734
735 if (elf_ppnt->p_type != PT_LOAD)
736 continue;
737
738 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
739 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
740 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
741 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
742 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
743 elf_flags |= MAP_FIXED;
744 } else if (elf_ex.e_type == ET_DYN) {
745 /* Try and get dynamic programs out of the way of the default mmap
746 base, as well as whatever program they might try to exec. This
747 is because the brk will follow the loader, and is not movable. */
748 /* NOTE: for qemu, we do a big mmap to get enough space
749 without hardcoding any address */
750 error = target_mmap(0, ET_DYN_MAP_SIZE,
751 PROT_NONE, MAP_PRIVATE | MAP_ANON,
752 -1, 0);
753 if (error == -1) {
754 perror("mmap");
755 exit(-1);
756 }
757 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
758 }
759
760 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
761 (elf_ppnt->p_filesz +
762 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
763 elf_prot,
764 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
765 bprm->fd,
766 (elf_ppnt->p_offset -
767 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
768 if (error == -1) {
769 perror("mmap");
770 exit(-1);
771 }
772
blueswir184778502008-10-26 20:33:16 +0000773 if (!load_addr_set) {
774 load_addr_set = 1;
775 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
776 if (elf_ex.e_type == ET_DYN) {
777 load_bias += error -
778 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
779 load_addr += load_bias;
780 reloc_func_desc = load_bias;
781 }
782 }
783 k = elf_ppnt->p_vaddr;
784 if (k < start_code)
785 start_code = k;
786 if (start_data < k)
787 start_data = k;
788 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
789 if (k > elf_bss)
790 elf_bss = k;
791 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
792 end_code = k;
793 if (end_data < k)
794 end_data = k;
795 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
796 if (k > elf_brk) elf_brk = k;
797 }
798
799 elf_entry += load_bias;
800 elf_bss += load_bias;
801 elf_brk += load_bias;
802 start_code += load_bias;
803 end_code += load_bias;
804 start_data += load_bias;
805 end_data += load_bias;
806
807 if (elf_interpreter) {
Warner Loshffa03662021-04-30 08:17:23 -0600808 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
809 &interp_load_addr);
blueswir184778502008-10-26 20:33:16 +0000810 reloc_func_desc = interp_load_addr;
811
812 close(interpreter_fd);
813 free(elf_interpreter);
814
815 if (elf_entry == ~((abi_ulong)0UL)) {
816 printf("Unable to load interpreter\n");
817 free(elf_phdata);
818 exit(-1);
819 return 0;
820 }
821 }
822
823 free(elf_phdata);
824
aliguori93fcfe32009-01-15 22:34:14 +0000825 if (qemu_log_enabled())
blueswir184778502008-10-26 20:33:16 +0000826 load_symbols(&elf_ex, bprm->fd);
827
Warner Loshffa03662021-04-30 08:17:23 -0600828 close(bprm->fd);
blueswir184778502008-10-26 20:33:16 +0000829
Warner Losh98b34d32021-08-04 17:13:24 -0600830 bprm->p = target_create_elf_tables(bprm->p, bprm->argc, bprm->envc,
831 bprm->stringp, &elf_ex, load_addr,
832 load_bias, interp_load_addr, info);
blueswir184778502008-10-26 20:33:16 +0000833 info->load_addr = reloc_func_desc;
834 info->start_brk = info->brk = elf_brk;
835 info->end_code = end_code;
836 info->start_code = start_code;
837 info->start_data = start_data;
838 info->end_data = end_data;
839 info->start_stack = bprm->p;
840
841 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
842 sections */
843 set_brk(elf_bss, elf_brk);
844
845 padzero(elf_bss, elf_brk);
846
blueswir184778502008-10-26 20:33:16 +0000847 info->entry = elf_entry;
848
Warner Losh0475f8f2021-08-06 14:20:16 -0600849#ifdef USE_ELF_CORE_DUMP
850 bprm->core_dump = &elf_core_dump;
851#else
852 bprm->core_dump = NULL;
853#endif
854
blueswir184778502008-10-26 20:33:16 +0000855 return 0;
856}
857
blueswir184778502008-10-26 20:33:16 +0000858void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
859{
Warner Losha8fe6d52021-08-03 22:04:20 -0600860
861 target_thread_init(regs, infop);
blueswir184778502008-10-26 20:33:16 +0000862}