blob: 59465b71d42951d267911152a87786a20fb444e2 [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 Losh66ef2522021-04-29 10:41:29 -060026#include "target_arch_elf.h"
Warner Losha8fe6d52021-08-03 22:04:20 -060027#include "target_os_thread.h"
Warner Losh66ef2522021-04-29 10:41:29 -060028
blueswir184778502008-10-26 20:33:16 +000029/* this flag is uneffective under linux too, should be deleted */
30#ifndef MAP_DENYWRITE
31#define MAP_DENYWRITE 0
32#endif
33
34/* should probably go in elf.h */
35#ifndef ELIBBAD
36#define ELIBBAD 80
37#endif
38
blueswir184778502008-10-26 20:33:16 +000039#ifndef ELF_PLATFORM
40#define ELF_PLATFORM (NULL)
41#endif
42
43#ifndef ELF_HWCAP
44#define ELF_HWCAP 0
45#endif
46
47#ifdef TARGET_ABI32
48#undef ELF_CLASS
49#define ELF_CLASS ELFCLASS32
50#undef bswaptls
51#define bswaptls(ptr) bswap32s(ptr)
52#endif
53
54#include "elf.h"
55
blueswir184778502008-10-26 20:33:16 +000056/* max code+data+bss space allocated to elf interpreter */
57#define INTERP_MAP_SIZE (32 * 1024 * 1024)
58
59/* max code+data+bss+brk space allocated to ET_DYN executables */
60#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
61
62/* Necessary parameters */
63#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
Warner Loshb4bebee2021-04-23 09:05:57 -060064#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE - 1))
65#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE - 1))
blueswir184778502008-10-26 20:33:16 +000066
blueswir184778502008-10-26 20:33:16 +000067#define DLINFO_ITEMS 12
68
Warner Loshb4bebee2021-04-23 09:05:57 -060069static inline void memcpy_fromfs(void *to, const void *from, unsigned long n)
blueswir184778502008-10-26 20:33:16 +000070{
Warner Loshb62f7902021-08-02 22:59:12 -060071 memcpy(to, from, n);
blueswir184778502008-10-26 20:33:16 +000072}
73
blueswir184778502008-10-26 20:33:16 +000074#ifdef BSWAP_NEEDED
75static void bswap_ehdr(struct elfhdr *ehdr)
76{
Warner Loshb62f7902021-08-02 22:59:12 -060077 bswap16s(&ehdr->e_type); /* Object file type */
blueswir184778502008-10-26 20:33:16 +000078 bswap16s(&ehdr->e_machine); /* Architecture */
79 bswap32s(&ehdr->e_version); /* Object file version */
80 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
81 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
82 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
83 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
84 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
Warner Loshb62f7902021-08-02 22:59:12 -060085 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
blueswir184778502008-10-26 20:33:16 +000086 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
Warner Loshb62f7902021-08-02 22:59:12 -060087 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
blueswir184778502008-10-26 20:33:16 +000088 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
Warner Loshb62f7902021-08-02 22:59:12 -060089 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
blueswir184778502008-10-26 20:33:16 +000090}
91
Warner Loshb62f7902021-08-02 22:59:12 -060092static void bswap_phdr(struct elf_phdr *phdr, int phnum)
blueswir184778502008-10-26 20:33:16 +000093{
Warner Loshb62f7902021-08-02 22:59:12 -060094 int i;
95
96 for (i = 0; i < phnum; i++, phdr++) {
97 bswap32s(&phdr->p_type); /* Segment type */
98 bswap32s(&phdr->p_flags); /* Segment flags */
99 bswaptls(&phdr->p_offset); /* Segment file offset */
100 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
101 bswaptls(&phdr->p_paddr); /* Segment physical address */
102 bswaptls(&phdr->p_filesz); /* Segment size in file */
103 bswaptls(&phdr->p_memsz); /* Segment size in memory */
104 bswaptls(&phdr->p_align); /* Segment alignment */
105 }
blueswir184778502008-10-26 20:33:16 +0000106}
107
Warner Loshb62f7902021-08-02 22:59:12 -0600108static void bswap_shdr(struct elf_shdr *shdr, int shnum)
blueswir184778502008-10-26 20:33:16 +0000109{
Warner Loshb62f7902021-08-02 22:59:12 -0600110 int i;
111
112 for (i = 0; i < shnum; i++, shdr++) {
113 bswap32s(&shdr->sh_name);
114 bswap32s(&shdr->sh_type);
115 bswaptls(&shdr->sh_flags);
116 bswaptls(&shdr->sh_addr);
117 bswaptls(&shdr->sh_offset);
118 bswaptls(&shdr->sh_size);
119 bswap32s(&shdr->sh_link);
120 bswap32s(&shdr->sh_info);
121 bswaptls(&shdr->sh_addralign);
122 bswaptls(&shdr->sh_entsize);
123 }
blueswir184778502008-10-26 20:33:16 +0000124}
125
126static void bswap_sym(struct elf_sym *sym)
127{
128 bswap32s(&sym->st_name);
129 bswaptls(&sym->st_value);
130 bswaptls(&sym->st_size);
131 bswap16s(&sym->st_shndx);
132}
Warner Loshb62f7902021-08-02 22:59:12 -0600133
134#else /* ! BSWAP_NEEDED */
135
136static void bswap_ehdr(struct elfhdr *ehdr) { }
137static void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
138static void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
139static void bswap_sym(struct elf_sym *sym) { }
140
141#endif /* ! BSWAP_NEEDED */
blueswir184778502008-10-26 20:33:16 +0000142
143/*
144 * 'copy_elf_strings()' copies argument/envelope strings from user
145 * memory to free pages in kernel mem. These are in a format ready
146 * to be put directly into the top of new user memory.
147 *
148 */
Warner Loshb4bebee2021-04-23 09:05:57 -0600149static abi_ulong copy_elf_strings(int argc, char **argv, void **page,
blueswir184778502008-10-26 20:33:16 +0000150 abi_ulong p)
151{
152 char *tmp, *tmp1, *pag = NULL;
153 int len, offset = 0;
154
155 if (!p) {
156 return 0; /* bullet-proofing */
157 }
158 while (argc-- > 0) {
159 tmp = argv[argc];
160 if (!tmp) {
Peter Maydell9bb93182014-06-02 13:24:37 +0100161 fprintf(stderr, "VFS: argc is wrong");
blueswir184778502008-10-26 20:33:16 +0000162 exit(-1);
163 }
164 tmp1 = tmp;
165 while (*tmp++);
166 len = tmp - tmp1;
167 if (p < len) { /* this shouldn't happen - 128kB */
168 return 0;
169 }
170 while (len) {
171 --p; --tmp; --len;
172 if (--offset < 0) {
173 offset = p % TARGET_PAGE_SIZE;
Warner Loshb4bebee2021-04-23 09:05:57 -0600174 pag = (char *)page[p / TARGET_PAGE_SIZE];
blueswir184778502008-10-26 20:33:16 +0000175 if (!pag) {
Stefan Weilc580dee2011-11-21 21:06:22 +0100176 pag = g_try_malloc0(TARGET_PAGE_SIZE);
Warner Loshb4bebee2021-04-23 09:05:57 -0600177 page[p / TARGET_PAGE_SIZE] = pag;
blueswir184778502008-10-26 20:33:16 +0000178 if (!pag)
179 return 0;
180 }
181 }
182 if (len == 0 || offset == 0) {
183 *(pag + offset) = *tmp;
184 }
185 else {
186 int bytes_to_copy = (len > offset) ? offset : len;
187 tmp -= bytes_to_copy;
188 p -= bytes_to_copy;
189 offset -= bytes_to_copy;
190 len -= bytes_to_copy;
191 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
192 }
193 }
194 }
195 return p;
196}
197
Warner Loshafcbcff2021-04-29 10:04:28 -0600198static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
blueswir184778502008-10-26 20:33:16 +0000199 struct image_info *info)
200{
201 abi_ulong stack_base, size, error;
202 int i;
203
204 /* Create enough stack to hold everything. If we don't use
205 * it for args, we'll use it for something else...
206 */
Warner Losh312a0b12021-08-06 18:48:37 -0600207 size = target_dflssiz;
Warner Loshb4bebee2021-04-23 09:05:57 -0600208 if (size < MAX_ARG_PAGES * TARGET_PAGE_SIZE)
209 size = MAX_ARG_PAGES * TARGET_PAGE_SIZE;
blueswir184778502008-10-26 20:33:16 +0000210 error = target_mmap(0,
211 size + qemu_host_page_size,
212 PROT_READ | PROT_WRITE,
213 MAP_PRIVATE | MAP_ANON,
214 -1, 0);
215 if (error == -1) {
216 perror("stk mmap");
217 exit(-1);
218 }
219 /* we reserve one extra page at the top of the stack as guard */
220 target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
221
Warner Loshb4bebee2021-04-23 09:05:57 -0600222 stack_base = error + size - MAX_ARG_PAGES * TARGET_PAGE_SIZE;
blueswir184778502008-10-26 20:33:16 +0000223 p += stack_base;
224
225 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
226 if (bprm->page[i]) {
227 info->rss++;
228 /* FIXME - check return value of memcpy_to_target() for failure */
229 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
Stefan Weilc580dee2011-11-21 21:06:22 +0100230 g_free(bprm->page[i]);
blueswir184778502008-10-26 20:33:16 +0000231 }
232 stack_base += TARGET_PAGE_SIZE;
233 }
234 return p;
235}
236
237static void set_brk(abi_ulong start, abi_ulong end)
238{
239 /* page-align the start and end addresses... */
240 start = HOST_PAGE_ALIGN(start);
241 end = HOST_PAGE_ALIGN(end);
242 if (end <= start)
243 return;
Warner Loshb4bebee2021-04-23 09:05:57 -0600244 if (target_mmap(start, end - start,
blueswir184778502008-10-26 20:33:16 +0000245 PROT_READ | PROT_WRITE | PROT_EXEC,
246 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) {
247 perror("cannot mmap brk");
248 exit(-1);
249 }
250}
251
252
253/* We need to explicitly zero any fractional pages after the data
254 section (i.e. bss). This would contain the junk from the file that
255 should not be in memory. */
256static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
257{
258 abi_ulong nbyte;
259
260 if (elf_bss >= last_bss)
261 return;
262
263 /* XXX: this is really a hack : if the real host page size is
264 smaller than the target page size, some pages after the end
265 of the file may not be mapped. A better fix would be to
266 patch target_mmap(), but it is more complicated as the file
267 size must be known */
268 if (qemu_real_host_page_size < qemu_host_page_size) {
269 abi_ulong end_addr, end_addr1;
Paolo Bonzini0c2d70c2015-12-02 13:00:54 +0100270 end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
blueswir184778502008-10-26 20:33:16 +0000271 end_addr = HOST_PAGE_ALIGN(elf_bss);
272 if (end_addr1 < end_addr) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800273 mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
Warner Loshb4bebee2021-04-23 09:05:57 -0600274 PROT_READ | PROT_WRITE | PROT_EXEC,
275 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
blueswir184778502008-10-26 20:33:16 +0000276 }
277 }
278
Warner Loshb4bebee2021-04-23 09:05:57 -0600279 nbyte = elf_bss & (qemu_host_page_size - 1);
blueswir184778502008-10-26 20:33:16 +0000280 if (nbyte) {
281 nbyte = qemu_host_page_size - nbyte;
282 do {
283 /* FIXME - what to do if put_user() fails? */
284 put_user_u8(0, elf_bss);
285 elf_bss++;
286 } while (--nbyte);
287 }
288}
289
290
291static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
292 struct elfhdr * exec,
293 abi_ulong load_addr,
294 abi_ulong load_bias,
Warner Loshffa03662021-04-30 08:17:23 -0600295 abi_ulong interp_load_addr,
blueswir184778502008-10-26 20:33:16 +0000296 struct image_info *info)
297{
298 abi_ulong sp;
299 int size;
300 abi_ulong u_platform;
301 const char *k_platform;
302 const int n = sizeof(elf_addr_t);
303
304 sp = p;
305 u_platform = 0;
306 k_platform = ELF_PLATFORM;
307 if (k_platform) {
308 size_t len = strlen(k_platform) + 1;
309 sp -= (len + n - 1) & ~(n - 1);
310 u_platform = sp;
311 /* FIXME - check return value of memcpy_to_target() for failure */
312 memcpy_to_target(sp, k_platform, len);
313 }
314 /*
315 * Force 16 byte _final_ alignment here for generality.
316 */
Warner Loshb4bebee2021-04-23 09:05:57 -0600317 sp = sp & ~(abi_ulong)15;
blueswir184778502008-10-26 20:33:16 +0000318 size = (DLINFO_ITEMS + 1) * 2;
319 if (k_platform)
Warner Loshb4bebee2021-04-23 09:05:57 -0600320 size += 2;
blueswir184778502008-10-26 20:33:16 +0000321#ifdef DLINFO_ARCH_ITEMS
322 size += DLINFO_ARCH_ITEMS * 2;
323#endif
324 size += envc + argc + 2;
Warner Loshffa03662021-04-30 08:17:23 -0600325 size += 1; /* argc itself */
blueswir184778502008-10-26 20:33:16 +0000326 size *= n;
327 if (size & 15)
Warner Loshb4bebee2021-04-23 09:05:57 -0600328 sp -= 16 - (size & 15);
blueswir184778502008-10-26 20:33:16 +0000329
330 /* This is correct because Linux defines
331 * elf_addr_t as Elf32_Off / Elf64_Off
332 */
333#define NEW_AUX_ENT(id, val) do { \
334 sp -= n; put_user_ual(val, sp); \
335 sp -= n; put_user_ual(id, sp); \
Warner Loshb4bebee2021-04-23 09:05:57 -0600336 } while (0)
blueswir184778502008-10-26 20:33:16 +0000337
Warner Loshb4bebee2021-04-23 09:05:57 -0600338 NEW_AUX_ENT(AT_NULL, 0);
blueswir184778502008-10-26 20:33:16 +0000339
340 /* There must be exactly DLINFO_ITEMS entries here. */
341 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
Warner Loshb4bebee2021-04-23 09:05:57 -0600342 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof(struct elf_phdr)));
blueswir184778502008-10-26 20:33:16 +0000343 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
344 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
345 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
346 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
347 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
348 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
349 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
350 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
351 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
352 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
353 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
354 if (k_platform)
355 NEW_AUX_ENT(AT_PLATFORM, u_platform);
356#ifdef ARCH_DLINFO
357 /*
358 * ARCH_DLINFO must come last so platform specific code can enforce
359 * special alignment requirements on the AUXV if necessary (eg. PPC).
360 */
361 ARCH_DLINFO;
362#endif
363#undef NEW_AUX_ENT
364
Warner Loshffa03662021-04-30 08:17:23 -0600365 sp = loader_build_argptr(envc, argc, sp, p);
blueswir184778502008-10-26 20:33:16 +0000366 return sp;
367}
368
369
Warner Loshb4bebee2021-04-23 09:05:57 -0600370static abi_ulong load_elf_interp(struct elfhdr *interp_elf_ex,
blueswir184778502008-10-26 20:33:16 +0000371 int interpreter_fd,
372 abi_ulong *interp_load_addr)
373{
Warner Loshb4bebee2021-04-23 09:05:57 -0600374 struct elf_phdr *elf_phdata = NULL;
375 struct elf_phdr *eppnt;
376 abi_ulong load_addr = 0;
377 int load_addr_set = 0;
378 int retval;
379 abi_ulong last_bss, elf_bss;
380 abi_ulong error;
381 int i;
blueswir184778502008-10-26 20:33:16 +0000382
Warner Loshb4bebee2021-04-23 09:05:57 -0600383 elf_bss = 0;
384 last_bss = 0;
385 error = 0;
blueswir184778502008-10-26 20:33:16 +0000386
Warner Loshb4bebee2021-04-23 09:05:57 -0600387 bswap_ehdr(interp_elf_ex);
Warner Loshb4bebee2021-04-23 09:05:57 -0600388 /* First of all, some simple consistency checks */
389 if ((interp_elf_ex->e_type != ET_EXEC &&
390 interp_elf_ex->e_type != ET_DYN) ||
391 !elf_check_arch(interp_elf_ex->e_machine)) {
392 return ~((abi_ulong)0UL);
393 }
blueswir184778502008-10-26 20:33:16 +0000394
395
Warner Loshb4bebee2021-04-23 09:05:57 -0600396 /* Now read in all of the header information */
blueswir184778502008-10-26 20:33:16 +0000397
Warner Loshb4bebee2021-04-23 09:05:57 -0600398 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
399 return ~(abi_ulong)0UL;
blueswir184778502008-10-26 20:33:16 +0000400
Warner Loshb4bebee2021-04-23 09:05:57 -0600401 elf_phdata = (struct elf_phdr *)
402 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
blueswir184778502008-10-26 20:33:16 +0000403
Warner Loshb4bebee2021-04-23 09:05:57 -0600404 if (!elf_phdata)
405 return ~((abi_ulong)0UL);
blueswir184778502008-10-26 20:33:16 +0000406
Warner Loshb4bebee2021-04-23 09:05:57 -0600407 /*
408 * If the size of this structure has changed, then punt, since
409 * we will be doing the wrong thing.
410 */
411 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
412 free(elf_phdata);
413 return ~((abi_ulong)0UL);
414 }
blueswir184778502008-10-26 20:33:16 +0000415
Warner Loshb4bebee2021-04-23 09:05:57 -0600416 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
417 if (retval >= 0) {
418 retval = read(interpreter_fd,
419 (char *) elf_phdata,
420 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
421 }
422 if (retval < 0) {
423 perror("load_elf_interp");
424 exit(-1);
Warner Loshffa03662021-04-30 08:17:23 -0600425 free(elf_phdata);
Warner Loshb4bebee2021-04-23 09:05:57 -0600426 return retval;
427 }
Warner Loshb62f7902021-08-02 22:59:12 -0600428 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
blueswir184778502008-10-26 20:33:16 +0000429
Warner Loshb4bebee2021-04-23 09:05:57 -0600430 if (interp_elf_ex->e_type == ET_DYN) {
431 /* in order to avoid hardcoding the interpreter load
432 address in qemu, we allocate a big enough memory zone */
433 error = target_mmap(0, INTERP_MAP_SIZE,
434 PROT_NONE, MAP_PRIVATE | MAP_ANON,
435 -1, 0);
436 if (error == -1) {
437 perror("mmap");
438 exit(-1);
blueswir184778502008-10-26 20:33:16 +0000439 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600440 load_addr = error;
441 load_addr_set = 1;
442 }
blueswir184778502008-10-26 20:33:16 +0000443
Warner Loshb4bebee2021-04-23 09:05:57 -0600444 eppnt = elf_phdata;
445 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++)
446 if (eppnt->p_type == PT_LOAD) {
blueswir184778502008-10-26 20:33:16 +0000447 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
448 int elf_prot = 0;
449 abi_ulong vaddr = 0;
450 abi_ulong k;
451
452 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
453 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
454 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
455 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
456 elf_type |= MAP_FIXED;
457 vaddr = eppnt->p_vaddr;
458 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600459 error = target_mmap(load_addr + TARGET_ELF_PAGESTART(vaddr),
460 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
461 elf_prot,
462 elf_type,
463 interpreter_fd,
464 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
blueswir184778502008-10-26 20:33:16 +0000465
466 if (error == -1) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600467 /* Real error */
468 close(interpreter_fd);
469 free(elf_phdata);
470 return ~((abi_ulong)0UL);
blueswir184778502008-10-26 20:33:16 +0000471 }
472
473 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600474 load_addr = error;
475 load_addr_set = 1;
blueswir184778502008-10-26 20:33:16 +0000476 }
477
478 /*
479 * Find the end of the file mapping for this phdr, and keep
480 * track of the largest address we see for this.
481 */
482 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
483 if (k > elf_bss) elf_bss = k;
484
485 /*
486 * Do the same thing for the memory mapping - between
487 * elf_bss and last_bss is the bss section.
488 */
489 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
490 if (k > last_bss) last_bss = k;
blueswir184778502008-10-26 20:33:16 +0000491 }
blueswir184778502008-10-26 20:33:16 +0000492
Warner Loshb4bebee2021-04-23 09:05:57 -0600493 /* Now use mmap to map the library into memory. */
494
495 close(interpreter_fd);
496
497 /*
498 * Now fill out the bss section. First pad the last page up
499 * to the page boundary, and then perform a mmap to make sure
500 * that there are zeromapped pages up to and including the last
501 * bss page.
502 */
503 padzero(elf_bss, last_bss);
504 elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
505
506 /* Map the last of the bss segment */
507 if (last_bss > elf_bss) {
508 target_mmap(elf_bss, last_bss - elf_bss,
509 PROT_READ | PROT_WRITE | PROT_EXEC,
510 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
511 }
512 free(elf_phdata);
513
514 *interp_load_addr = load_addr;
515 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
blueswir184778502008-10-26 20:33:16 +0000516}
517
518static int symfind(const void *s0, const void *s1)
519{
Stefan Weilc7c530c2012-01-05 15:39:39 +0100520 target_ulong addr = *(target_ulong *)s0;
blueswir184778502008-10-26 20:33:16 +0000521 struct elf_sym *sym = (struct elf_sym *)s1;
522 int result = 0;
Stefan Weilc7c530c2012-01-05 15:39:39 +0100523 if (addr < sym->st_value) {
blueswir184778502008-10-26 20:33:16 +0000524 result = -1;
Stefan Weilc7c530c2012-01-05 15:39:39 +0100525 } else if (addr >= sym->st_value + sym->st_size) {
blueswir184778502008-10-26 20:33:16 +0000526 result = 1;
527 }
528 return result;
529}
530
531static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
532{
533#if ELF_CLASS == ELFCLASS32
534 struct elf_sym *syms = s->disas_symtab.elf32;
535#else
536 struct elf_sym *syms = s->disas_symtab.elf64;
537#endif
538
539 // binary search
blueswir184778502008-10-26 20:33:16 +0000540 struct elf_sym *sym;
541
Stefan Weilc7c530c2012-01-05 15:39:39 +0100542 sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +0000543 if (sym != NULL) {
blueswir184778502008-10-26 20:33:16 +0000544 return s->disas_strtab + sym->st_name;
545 }
546
547 return "";
548}
549
550/* FIXME: This should use elf_ops.h */
551static int symcmp(const void *s0, const void *s1)
552{
553 struct elf_sym *sym0 = (struct elf_sym *)s0;
554 struct elf_sym *sym1 = (struct elf_sym *)s1;
555 return (sym0->st_value < sym1->st_value)
556 ? -1
557 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
558}
559
560/* Best attempt to load symbols from this ELF object. */
561static void load_symbols(struct elfhdr *hdr, int fd)
562{
563 unsigned int i, nsyms;
564 struct elf_shdr sechdr, symtab, strtab;
565 char *strings;
566 struct syminfo *s;
Stefan Weil29718712011-01-16 16:28:20 +0100567 struct elf_sym *syms, *new_syms;
blueswir184778502008-10-26 20:33:16 +0000568
569 lseek(fd, hdr->e_shoff, SEEK_SET);
570 for (i = 0; i < hdr->e_shnum; i++) {
571 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
572 return;
Warner Loshb62f7902021-08-02 22:59:12 -0600573 bswap_shdr(&sechdr, 1);
blueswir184778502008-10-26 20:33:16 +0000574 if (sechdr.sh_type == SHT_SYMTAB) {
575 symtab = sechdr;
576 lseek(fd, hdr->e_shoff
577 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
578 if (read(fd, &strtab, sizeof(strtab))
579 != sizeof(strtab))
580 return;
Warner Loshb62f7902021-08-02 22:59:12 -0600581 bswap_shdr(&strtab, 1);
blueswir184778502008-10-26 20:33:16 +0000582 goto found;
583 }
584 }
585 return; /* Shouldn't happen... */
586
587 found:
588 /* Now know where the strtab and symtab are. Snarf them. */
589 s = malloc(sizeof(*s));
590 syms = malloc(symtab.sh_size);
Stefan Weil29718712011-01-16 16:28:20 +0100591 if (!syms) {
592 free(s);
blueswir184778502008-10-26 20:33:16 +0000593 return;
Stefan Weil29718712011-01-16 16:28:20 +0100594 }
blueswir184778502008-10-26 20:33:16 +0000595 s->disas_strtab = strings = malloc(strtab.sh_size);
Stefan Weil29718712011-01-16 16:28:20 +0100596 if (!s->disas_strtab) {
597 free(s);
598 free(syms);
blueswir184778502008-10-26 20:33:16 +0000599 return;
Stefan Weil29718712011-01-16 16:28:20 +0100600 }
blueswir184778502008-10-26 20:33:16 +0000601
602 lseek(fd, symtab.sh_offset, SEEK_SET);
Stefan Weil29718712011-01-16 16:28:20 +0100603 if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
604 free(s);
605 free(syms);
606 free(strings);
blueswir184778502008-10-26 20:33:16 +0000607 return;
Stefan Weil29718712011-01-16 16:28:20 +0100608 }
blueswir184778502008-10-26 20:33:16 +0000609
610 nsyms = symtab.sh_size / sizeof(struct elf_sym);
611
612 i = 0;
613 while (i < nsyms) {
blueswir184778502008-10-26 20:33:16 +0000614 bswap_sym(syms + i);
blueswir184778502008-10-26 20:33:16 +0000615 // Throw away entries which we do not need.
616 if (syms[i].st_shndx == SHN_UNDEF ||
617 syms[i].st_shndx >= SHN_LORESERVE ||
618 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
619 nsyms--;
620 if (i < nsyms) {
621 syms[i] = syms[nsyms];
622 }
623 continue;
624 }
blueswir184778502008-10-26 20:33:16 +0000625 i++;
626 }
Stefan Weil29718712011-01-16 16:28:20 +0100627
628 /* Attempt to free the storage associated with the local symbols
629 that we threw away. Whether or not this has any effect on the
630 memory allocation depends on the malloc implementation and how
631 many symbols we managed to discard. */
632 new_syms = realloc(syms, nsyms * sizeof(*syms));
633 if (new_syms == NULL) {
634 free(s);
635 free(syms);
636 free(strings);
637 return;
638 }
639 syms = new_syms;
blueswir184778502008-10-26 20:33:16 +0000640
641 qsort(syms, nsyms, sizeof(*syms), symcmp);
642
643 lseek(fd, strtab.sh_offset, SEEK_SET);
Stefan Weil29718712011-01-16 16:28:20 +0100644 if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
645 free(s);
646 free(syms);
647 free(strings);
blueswir184778502008-10-26 20:33:16 +0000648 return;
Stefan Weil29718712011-01-16 16:28:20 +0100649 }
blueswir184778502008-10-26 20:33:16 +0000650 s->disas_num_syms = nsyms;
651#if ELF_CLASS == ELFCLASS32
652 s->disas_symtab.elf32 = syms;
Blue Swirl032e51d2009-09-27 19:30:56 +0000653 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
blueswir184778502008-10-26 20:33:16 +0000654#else
655 s->disas_symtab.elf64 = syms;
Blue Swirl032e51d2009-09-27 19:30:56 +0000656 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
blueswir184778502008-10-26 20:33:16 +0000657#endif
658 s->next = syminfos;
659 syminfos = s;
660}
661
Warner Loshafcbcff2021-04-29 10:04:28 -0600662int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
Warner Loshb4bebee2021-04-23 09:05:57 -0600663 struct image_info *info)
blueswir184778502008-10-26 20:33:16 +0000664{
665 struct elfhdr elf_ex;
666 struct elfhdr interp_elf_ex;
blueswir184778502008-10-26 20:33:16 +0000667 int interpreter_fd = -1; /* avoid warning */
668 abi_ulong load_addr, load_bias;
669 int load_addr_set = 0;
blueswir184778502008-10-26 20:33:16 +0000670 int i;
blueswir184778502008-10-26 20:33:16 +0000671 struct elf_phdr * elf_ppnt;
672 struct elf_phdr *elf_phdata;
673 abi_ulong elf_bss, k, elf_brk;
674 int retval;
675 char * elf_interpreter;
676 abi_ulong elf_entry, interp_load_addr = 0;
blueswir184778502008-10-26 20:33:16 +0000677 abi_ulong start_code, end_code, start_data, end_data;
678 abi_ulong reloc_func_desc = 0;
Peter Maydell71025952017-07-18 17:26:32 +0100679#ifdef LOW_ELF_STACK
680 abi_ulong elf_stack = ~((abi_ulong)0UL);
681#endif
blueswir184778502008-10-26 20:33:16 +0000682
blueswir184778502008-10-26 20:33:16 +0000683 load_addr = 0;
684 load_bias = 0;
685 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
blueswir184778502008-10-26 20:33:16 +0000686 bswap_ehdr(&elf_ex);
blueswir184778502008-10-26 20:33:16 +0000687
688 /* First of all, some simple consistency checks */
689 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
Warner Loshb4bebee2021-04-23 09:05:57 -0600690 (!elf_check_arch(elf_ex.e_machine))) {
blueswir184778502008-10-26 20:33:16 +0000691 return -ENOEXEC;
692 }
693
694 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
Warner Loshb4bebee2021-04-23 09:05:57 -0600695 bprm->p = copy_elf_strings(bprm->envc, bprm->envp, bprm->page,bprm->p);
696 bprm->p = copy_elf_strings(bprm->argc, bprm->argv, bprm->page,bprm->p);
blueswir184778502008-10-26 20:33:16 +0000697 if (!bprm->p) {
698 retval = -E2BIG;
699 }
700
701 /* Now read in all of the header information */
702 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
703 if (elf_phdata == NULL) {
704 return -ENOMEM;
705 }
706
707 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600708 if (retval > 0) {
709 retval = read(bprm->fd, (char *)elf_phdata,
blueswir184778502008-10-26 20:33:16 +0000710 elf_ex.e_phentsize * elf_ex.e_phnum);
711 }
712
713 if (retval < 0) {
714 perror("load_elf_binary");
715 exit(-1);
Warner Loshb4bebee2021-04-23 09:05:57 -0600716 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000717 return -errno;
718 }
719
Warner Loshb62f7902021-08-02 22:59:12 -0600720 bswap_phdr(elf_phdata, elf_ex.e_phnum);
721
blueswir184778502008-10-26 20:33:16 +0000722 elf_ppnt = elf_phdata;
723
724 elf_bss = 0;
725 elf_brk = 0;
726
727
blueswir184778502008-10-26 20:33:16 +0000728 elf_interpreter = NULL;
729 start_code = ~((abi_ulong)0UL);
730 end_code = 0;
731 start_data = 0;
732 end_data = 0;
blueswir184778502008-10-26 20:33:16 +0000733
Warner Loshb4bebee2021-04-23 09:05:57 -0600734 for (i = 0;i < elf_ex.e_phnum; i++) {
blueswir184778502008-10-26 20:33:16 +0000735 if (elf_ppnt->p_type == PT_INTERP) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600736 if (elf_interpreter != NULL)
blueswir184778502008-10-26 20:33:16 +0000737 {
Warner Loshb4bebee2021-04-23 09:05:57 -0600738 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000739 free(elf_interpreter);
740 close(bprm->fd);
741 return -EINVAL;
742 }
743
744 /* This is the program interpreter used for
745 * shared libraries - for now assume that this
746 * is an a.out format binary
747 */
748
749 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
750
751 if (elf_interpreter == NULL) {
Warner Loshb4bebee2021-04-23 09:05:57 -0600752 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000753 close(bprm->fd);
754 return -ENOMEM;
755 }
756
757 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600758 if (retval >= 0) {
blueswir184778502008-10-26 20:33:16 +0000759 retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
760 }
Warner Loshb4bebee2021-04-23 09:05:57 -0600761 if (retval < 0) {
blueswir184778502008-10-26 20:33:16 +0000762 perror("load_elf_binary2");
763 exit(-1);
764 }
765
blueswir184778502008-10-26 20:33:16 +0000766 if (retval >= 0) {
767 retval = open(path(elf_interpreter), O_RDONLY);
Warner Loshb4bebee2021-04-23 09:05:57 -0600768 if (retval >= 0) {
blueswir184778502008-10-26 20:33:16 +0000769 interpreter_fd = retval;
770 }
771 else {
772 perror(elf_interpreter);
773 exit(-1);
774 /* retval = -errno; */
775 }
776 }
777
778 if (retval >= 0) {
779 retval = lseek(interpreter_fd, 0, SEEK_SET);
Warner Loshb4bebee2021-04-23 09:05:57 -0600780 if (retval >= 0) {
781 retval = read(interpreter_fd, bprm->buf, 128);
blueswir184778502008-10-26 20:33:16 +0000782 }
783 }
784 if (retval >= 0) {
Michael S. Tsirkin6ece4df2009-09-30 19:43:38 +0200785 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
blueswir184778502008-10-26 20:33:16 +0000786 }
787 if (retval < 0) {
788 perror("load_elf_binary3");
789 exit(-1);
Warner Loshb4bebee2021-04-23 09:05:57 -0600790 free(elf_phdata);
blueswir184778502008-10-26 20:33:16 +0000791 free(elf_interpreter);
792 close(bprm->fd);
793 return retval;
794 }
795 }
796 elf_ppnt++;
797 }
798
799 /* Some simple consistency checks for the interpreter */
Warner Loshb4bebee2021-04-23 09:05:57 -0600800 if (elf_interpreter) {
blueswir184778502008-10-26 20:33:16 +0000801 if (interp_elf_ex.e_ident[0] != 0x7f ||
Warner Loshffa03662021-04-30 08:17:23 -0600802 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF", 3) != 0) {
blueswir184778502008-10-26 20:33:16 +0000803 free(elf_interpreter);
804 free(elf_phdata);
805 close(bprm->fd);
806 return -ELIBBAD;
807 }
808 }
809
810 /* OK, we are done with that, now set up the arg stuff,
811 and then start this sucker up */
812
Warner Loshffa03662021-04-30 08:17:23 -0600813 if (!bprm->p) {
814 free(elf_interpreter);
815 free(elf_phdata);
816 close(bprm->fd);
817 return -E2BIG;
blueswir184778502008-10-26 20:33:16 +0000818 }
819
820 /* OK, This is the point of no return */
821 info->end_data = 0;
822 info->end_code = 0;
823 info->start_mmap = (abi_ulong)ELF_START_MMAP;
824 info->mmap = 0;
825 elf_entry = (abi_ulong) elf_ex.e_entry;
826
Blue Swirl2fa5d9b2009-09-27 19:30:51 +0000827 /*
828 * In case where user has not explicitly set the guest_base, we
829 * probe here that should we set it automatically.
830 */
831 if (!have_guest_base) {
832 /*
833 * Go through ELF program header table and find out whether
Paolo Bonzini7d374352018-12-13 23:37:37 +0100834 * any of the segments drop below our current mmap_min_addr and
Blue Swirl2fa5d9b2009-09-27 19:30:51 +0000835 * in that case set guest_base to corresponding address.
836 */
837 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
838 i++, elf_ppnt++) {
839 if (elf_ppnt->p_type != PT_LOAD)
840 continue;
841 if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
842 guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
843 break;
844 }
845 }
846 }
Blue Swirl2fa5d9b2009-09-27 19:30:51 +0000847
blueswir184778502008-10-26 20:33:16 +0000848 /* Do this so that we can load the interpreter, if need be. We will
849 change some of these later */
850 info->rss = 0;
851 bprm->p = setup_arg_pages(bprm->p, bprm, info);
852 info->start_stack = bprm->p;
853
854 /* Now we do a little grungy work by mmaping the ELF image into
855 * the correct location in memory. At this point, we assume that
856 * the image should be loaded at fixed address, not at a variable
857 * address.
858 */
859
Warner Loshb4bebee2021-04-23 09:05:57 -0600860 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
blueswir184778502008-10-26 20:33:16 +0000861 int elf_prot = 0;
862 int elf_flags = 0;
863 abi_ulong error;
864
865 if (elf_ppnt->p_type != PT_LOAD)
866 continue;
867
868 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
869 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
870 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
871 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
872 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
873 elf_flags |= MAP_FIXED;
874 } else if (elf_ex.e_type == ET_DYN) {
875 /* Try and get dynamic programs out of the way of the default mmap
876 base, as well as whatever program they might try to exec. This
877 is because the brk will follow the loader, and is not movable. */
878 /* NOTE: for qemu, we do a big mmap to get enough space
879 without hardcoding any address */
880 error = target_mmap(0, ET_DYN_MAP_SIZE,
881 PROT_NONE, MAP_PRIVATE | MAP_ANON,
882 -1, 0);
883 if (error == -1) {
884 perror("mmap");
885 exit(-1);
886 }
887 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
888 }
889
890 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
891 (elf_ppnt->p_filesz +
892 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
893 elf_prot,
894 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
895 bprm->fd,
896 (elf_ppnt->p_offset -
897 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
898 if (error == -1) {
899 perror("mmap");
900 exit(-1);
901 }
902
903#ifdef LOW_ELF_STACK
904 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
905 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
906#endif
907
908 if (!load_addr_set) {
909 load_addr_set = 1;
910 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
911 if (elf_ex.e_type == ET_DYN) {
912 load_bias += error -
913 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
914 load_addr += load_bias;
915 reloc_func_desc = load_bias;
916 }
917 }
918 k = elf_ppnt->p_vaddr;
919 if (k < start_code)
920 start_code = k;
921 if (start_data < k)
922 start_data = k;
923 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
924 if (k > elf_bss)
925 elf_bss = k;
926 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
927 end_code = k;
928 if (end_data < k)
929 end_data = k;
930 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
931 if (k > elf_brk) elf_brk = k;
932 }
933
934 elf_entry += load_bias;
935 elf_bss += load_bias;
936 elf_brk += load_bias;
937 start_code += load_bias;
938 end_code += load_bias;
939 start_data += load_bias;
940 end_data += load_bias;
941
942 if (elf_interpreter) {
Warner Loshffa03662021-04-30 08:17:23 -0600943 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
944 &interp_load_addr);
blueswir184778502008-10-26 20:33:16 +0000945 reloc_func_desc = interp_load_addr;
946
947 close(interpreter_fd);
948 free(elf_interpreter);
949
950 if (elf_entry == ~((abi_ulong)0UL)) {
951 printf("Unable to load interpreter\n");
952 free(elf_phdata);
953 exit(-1);
954 return 0;
955 }
956 }
957
958 free(elf_phdata);
959
aliguori93fcfe32009-01-15 22:34:14 +0000960 if (qemu_log_enabled())
blueswir184778502008-10-26 20:33:16 +0000961 load_symbols(&elf_ex, bprm->fd);
962
Warner Loshffa03662021-04-30 08:17:23 -0600963 close(bprm->fd);
blueswir184778502008-10-26 20:33:16 +0000964
965#ifdef LOW_ELF_STACK
966 info->start_stack = bprm->p = elf_stack - 4;
967#endif
968 bprm->p = create_elf_tables(bprm->p,
Warner Loshffa03662021-04-30 08:17:23 -0600969 bprm->argc,
970 bprm->envc,
971 &elf_ex,
972 load_addr, load_bias,
973 interp_load_addr,
974 info);
blueswir184778502008-10-26 20:33:16 +0000975 info->load_addr = reloc_func_desc;
976 info->start_brk = info->brk = elf_brk;
977 info->end_code = end_code;
978 info->start_code = start_code;
979 info->start_data = start_data;
980 info->end_data = end_data;
981 info->start_stack = bprm->p;
982
983 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
984 sections */
985 set_brk(elf_bss, elf_brk);
986
987 padzero(elf_bss, elf_brk);
988
989#if 0
990 printf("(start_brk) %x\n" , info->start_brk);
991 printf("(end_code) %x\n" , info->end_code);
992 printf("(start_code) %x\n" , info->start_code);
993 printf("(end_data) %x\n" , info->end_data);
994 printf("(start_stack) %x\n" , info->start_stack);
995 printf("(brk) %x\n" , info->brk);
996#endif
997
blueswir184778502008-10-26 20:33:16 +0000998 info->entry = elf_entry;
999
1000 return 0;
1001}
1002
blueswir184778502008-10-26 20:33:16 +00001003void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
1004{
Warner Losha8fe6d52021-08-03 22:04:20 -06001005
1006 target_thread_init(regs, infop);
blueswir184778502008-10-26 20:33:16 +00001007}