import source from 0.14.1
[external/qemu.git] / packaging / fix-glibc-install-locales.patch
1 From bf858897b76926b56e948dbe7a1a491b68dccda7 Mon Sep 17 00:00:00 2001
2 From: Richard Henderson <rth@twiddle.net>
3 Date: Tue, 27 Jul 2010 17:25:38 +0000
4 Subject: linux-user: Re-use load_elf_image for the main binary.
5
6 This requires moving the PT_INTERP extraction and GUEST_BASE
7 handling into load_elf_image.  Key this off a non-null pointer
8 argument to receive the interpreter name.
9
10 Signed-off-by: Richard Henderson <rth@twiddle.net>
11 Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
12 ---
13 diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14 index 0a3d084..a53285a 100644
15 --- a/linux-user/elfload.c
16 +++ b/linux-user/elfload.c
17 @@ -829,9 +829,6 @@ struct exec
18  #define ZMAGIC 0413
19  #define QMAGIC 0314
20  
21 -/* max code+data+bss+brk space allocated to ET_DYN executables */
22 -#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
23 -
24  /* Necessary parameters */
25  #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
26  #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
27 @@ -1169,7 +1166,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
28     On return: INFO values will be filled in, as necessary or available.  */
29  
30  static void load_elf_image(const char *image_name, int image_fd,
31 -                           struct image_info *info,
32 +                           struct image_info *info, char **pinterp_name,
33                             char bprm_buf[BPRM_BUF_SIZE])
34  {
35      struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
36 @@ -1229,6 +1226,67 @@ static void load_elf_image(const char *image_name, int image_fd,
37          if (load_addr == -1) {
38              goto exit_perror;
39          }
40 +    } else if (pinterp_name != NULL) {
41 +        /* This is the main executable.  Make sure that the low
42 +           address does not conflict with MMAP_MIN_ADDR or the
43 +           QEMU application itself.  */
44 +#if defined(CONFIG_USE_GUEST_BASE)
45 +        /*
46 +         * In case where user has not explicitly set the guest_base, we
47 +         * probe here that should we set it automatically.
48 +         */
49 +        if (!have_guest_base && !reserved_va) {
50 +            unsigned long host_start, real_start, host_size;
51 +
52 +            /* Round addresses to page boundaries.  */
53 +            loaddr &= qemu_host_page_mask;
54 +            hiaddr = HOST_PAGE_ALIGN(hiaddr);
55 +
56 +            if (loaddr < mmap_min_addr) {
57 +                host_start = HOST_PAGE_ALIGN(mmap_min_addr);
58 +            } else {
59 +                host_start = loaddr;
60 +                if (host_start != loaddr) {
61 +                    errmsg = "Address overflow loading ELF binary";
62 +                    goto exit_errmsg;
63 +                }
64 +            }
65 +            host_size = hiaddr - loaddr;
66 +            while (1) {
67 +                /* Do not use mmap_find_vma here because that is limited to the
68 +                   guest address space.  We are going to make the
69 +                   guest address space fit whatever we're given.  */
70 +                real_start = (unsigned long)
71 +                    mmap((void *)host_start, host_size, PROT_NONE,
72 +                         MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
73 +                if (real_start == (unsigned long)-1) {
74 +                    goto exit_perror;
75 +                }
76 +                if (real_start == host_start) {
77 +                    break;
78 +                }
79 +                /* That address didn't work.  Unmap and try a different one.
80 +                   The address the host picked because is typically right at
81 +                   the top of the host address space and leaves the guest with
82 +                   no usable address space.  Resort to a linear search.  We
83 +                   already compensated for mmap_min_addr, so this should not
84 +                   happen often.  Probably means we got unlucky and host
85 +                   address space randomization put a shared library somewhere
86 +                   inconvenient.  */
87 +                munmap((void *)real_start, host_size);
88 +                host_start += qemu_host_page_size;
89 +                if (host_start == loaddr) {
90 +                    /* Theoretically possible if host doesn't have any suitably
91 +                       aligned areas.  Normally the first mmap will fail.  */
92 +                    errmsg = "Unable to find space for application";
93 +                    goto exit_errmsg;
94 +                }
95 +            }
96 +            qemu_log("Relocating guest address space from 0x"
97 +                     TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start);
98 +            guest_base = real_start - loaddr;
99 +        }
100 +#endif
101      }
102      load_bias = load_addr - loaddr;
103  
104 @@ -1290,6 +1348,33 @@ static void load_elf_image(const char *image_name, int image_fd,
105                      info->brk = vaddr_em;
106                  }
107              }
108 +        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
109 +            char *interp_name;
110 +
111 +            if (*pinterp_name) {
112 +                errmsg = "Multiple PT_INTERP entries";
113 +                goto exit_errmsg;
114 +            }
115 +            interp_name = malloc(eppnt->p_filesz);
116 +            if (!interp_name) {
117 +                goto exit_perror;
118 +            }
119 +
120 +            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
121 +                memcpy(interp_name, bprm_buf + eppnt->p_offset,
122 +                       eppnt->p_filesz);
123 +            } else {
124 +                retval = pread(image_fd, interp_name, eppnt->p_filesz,
125 +                               eppnt->p_offset);
126 +                if (retval != eppnt->p_filesz) {
127 +                    goto exit_perror;
128 +                }
129 +            }
130 +            if (interp_name[eppnt->p_filesz - 1] != 0) {
131 +                errmsg = "Invalid PT_INTERP entry";
132 +                goto exit_errmsg;
133 +            }
134 +            *pinterp_name = interp_name;
135          }
136      }
137  
138 @@ -1336,7 +1421,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
139          memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
140      }
141  
142 -    load_elf_image(filename, fd, info, bprm_buf);
143 +    load_elf_image(filename, fd, info, NULL, bprm_buf);
144      return;
145  
146   exit_perror:
147 @@ -1480,291 +1565,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
148  {
149      struct image_info interp_info;
150      struct elfhdr elf_ex;
151 -    abi_ulong load_addr, load_bias;
152 -    int load_addr_set = 0;
153 -    int i;
154 -    struct elf_phdr * elf_ppnt;
155 -    struct elf_phdr *elf_phdata;
156 -    abi_ulong k, elf_brk;
157 -    int retval;
158      char *elf_interpreter = NULL;
159 -    abi_ulong elf_entry;
160 -    int status;
161 -    abi_ulong start_code, end_code, start_data, end_data;
162 -    abi_ulong elf_stack;
163  
164 -    status = 0;
165 -    load_addr = 0;
166 -    load_bias = 0;
167 -    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
168 +    info->start_mmap = (abi_ulong)ELF_START_MMAP;
169 +    info->mmap = 0;
170 +    info->rss = 0;
171  
172 -    /* First of all, some simple consistency checks */
173 -    if (!elf_check_ident(&elf_ex)) {
174 -        return -ENOEXEC;
175 -    }
176 -    bswap_ehdr(&elf_ex);
177 -    if (!elf_check_ehdr(&elf_ex)) {
178 -        return -ENOEXEC;
179 -    }
180 +    load_elf_image(bprm->filename, bprm->fd, info,
181 +                   &elf_interpreter, bprm->buf);
182 +
183 +    /* ??? We need a copy of the elf header for passing to create_elf_tables.
184 +       If we do nothing, we'll have overwritten this when we re-use bprm->buf
185 +       when we load the interpreter.  */
186 +    elf_ex = *(struct elfhdr *)bprm->buf;
187  
188      bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
189      bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
190      bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
191      if (!bprm->p) {
192 -        retval = -E2BIG;
193 -    }
194 -
195 -    /* Now read in all of the header information */
196 -    elf_phdata = (struct elf_phdr *)
197 -        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
198 -    if (elf_phdata == NULL) {
199 -        return -ENOMEM;
200 -    }
201 -
202 -    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
203 -    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
204 -        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
205 -    } else {
206 -        retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
207 -        if (retval != i) {
208 -            perror("load_elf_binary");
209 -            exit(-1);
210 -        }
211 -    }
212 -    bswap_phdr(elf_phdata, elf_ex.e_phnum);
213 -
214 -    elf_brk = 0;
215 -    elf_stack = ~((abi_ulong)0UL);
216 -    start_code = ~((abi_ulong)0UL);
217 -    end_code = 0;
218 -    start_data = 0;
219 -    end_data = 0;
220 -
221 -    elf_ppnt = elf_phdata;
222 -    for(i=0;i < elf_ex.e_phnum; i++) {
223 -        if (elf_ppnt->p_type == PT_INTERP) {
224 -            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
225 -                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
226 -            } else {
227 -                elf_interpreter = alloca(elf_ppnt->p_filesz);
228 -                retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
229 -                               elf_ppnt->p_offset);
230 -                if (retval != elf_ppnt->p_filesz) {
231 -                    perror("load_elf_binary");
232 -                    exit(-1);
233 -                }
234 -            }
235 -        }
236 -        elf_ppnt++;
237 -    }
238 -
239 -    /* OK, This is the point of no return */
240 -    info->end_data = 0;
241 -    info->end_code = 0;
242 -    info->start_mmap = (abi_ulong)ELF_START_MMAP;
243 -    info->mmap = 0;
244 -    elf_entry = (abi_ulong) elf_ex.e_entry;
245 -
246 -#if defined(CONFIG_USE_GUEST_BASE)
247 -    /*
248 -     * In case where user has not explicitly set the guest_base, we
249 -     * probe here that should we set it automatically.
250 -     */
251 -    if (!(have_guest_base || reserved_va)) {
252 -        /*
253 -         * Go through ELF program header table and find the address
254 -         * range used by loadable segments.  Check that this is available on
255 -         * the host, and if not find a suitable value for guest_base.  */
256 -        abi_ulong app_start = ~0;
257 -        abi_ulong app_end = 0;
258 -        abi_ulong addr;
259 -        unsigned long host_start;
260 -        unsigned long real_start;
261 -        unsigned long host_size;
262 -        for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
263 -             i++, elf_ppnt++) {
264 -            if (elf_ppnt->p_type != PT_LOAD)
265 -                continue;
266 -            addr = elf_ppnt->p_vaddr;
267 -            if (addr < app_start) {
268 -                app_start = addr;
269 -            }
270 -            addr += elf_ppnt->p_memsz;
271 -            if (addr > app_end) {
272 -                app_end = addr;
273 -            }
274 -        }
275 -
276 -        /* If we don't have any loadable segments then something
277 -           is very wrong.  */
278 -        assert(app_start < app_end);
279 -
280 -        /* Round addresses to page boundaries.  */
281 -        app_start = app_start & qemu_host_page_mask;
282 -        app_end = HOST_PAGE_ALIGN(app_end);
283 -        if (app_start < mmap_min_addr) {
284 -            host_start = HOST_PAGE_ALIGN(mmap_min_addr);
285 -        } else {
286 -            host_start = app_start;
287 -            if (host_start != app_start) {
288 -                fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
289 -                abort();
290 -            }
291 -        }
292 -        host_size = app_end - app_start;
293 -        while (1) {
294 -            /* Do not use mmap_find_vma here because that is limited to the
295 -               guest address space.  We are going to make the
296 -               guest address space fit whatever we're given.  */
297 -            real_start = (unsigned long)mmap((void *)host_start, host_size,
298 -                PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
299 -            if (real_start == (unsigned long)-1) {
300 -                fprintf(stderr, "qemu: Virtual memory exausted\n");
301 -                abort();
302 -            }
303 -            if (real_start == host_start) {
304 -                break;
305 -            }
306 -            /* That address didn't work.  Unmap and try a different one.
307 -               The address the host picked because is typically
308 -               right at the top of the host address space and leaves the
309 -               guest with no usable address space.  Resort to a linear search.
310 -               We already compensated for mmap_min_addr, so this should not
311 -               happen often.  Probably means we got unlucky and host address
312 -               space randomization put a shared library somewhere
313 -               inconvenient.  */
314 -            munmap((void *)real_start, host_size);
315 -            host_start += qemu_host_page_size;
316 -            if (host_start == app_start) {
317 -                /* Theoretically possible if host doesn't have any
318 -                   suitably aligned areas.  Normally the first mmap will
319 -                   fail.  */
320 -                fprintf(stderr, "qemu: Unable to find space for application\n");
321 -                abort();
322 -            }
323 -        }
324 -        qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
325 -                 " to 0x%lx\n", app_start, real_start);
326 -        guest_base = real_start - app_start;
327 +        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
328 +        exit(-1);
329      }
330 -#endif /* CONFIG_USE_GUEST_BASE */
331  
332      /* Do this so that we can load the interpreter, if need be.  We will
333         change some of these later */
334 -    info->rss = 0;
335      bprm->p = setup_arg_pages(bprm->p, bprm, info);
336 -    info->start_stack = bprm->p;
337 -
338 -    /* Now we do a little grungy work by mmaping the ELF image into
339 -     * the correct location in memory.  At this point, we assume that
340 -     * the image should be loaded at fixed address, not at a variable
341 -     * address.
342 -     */
343 -
344 -    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
345 -        int elf_prot = 0;
346 -        int elf_flags = 0;
347 -        abi_ulong error;
348 -
349 -        if (elf_ppnt->p_type != PT_LOAD)
350 -            continue;
351 -
352 -        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
353 -        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
354 -        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
355 -        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
356 -        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
357 -            elf_flags |= MAP_FIXED;
358 -        } else if (elf_ex.e_type == ET_DYN) {
359 -            /* Try and get dynamic programs out of the way of the default mmap
360 -               base, as well as whatever program they might try to exec.  This
361 -               is because the brk will follow the loader, and is not movable.  */
362 -            /* NOTE: for qemu, we do a big mmap to get enough space
363 -               without hardcoding any address */
364 -            error = target_mmap(0, ET_DYN_MAP_SIZE,
365 -                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
366 -                                -1, 0);
367 -            if (error == -1) {
368 -                perror("mmap");
369 -                exit(-1);
370 -            }
371 -            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
372 -        }
373 -
374 -        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
375 -                            (elf_ppnt->p_filesz +
376 -                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
377 -                            elf_prot,
378 -                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
379 -                            bprm->fd,
380 -                            (elf_ppnt->p_offset -
381 -                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
382 -        if (error == -1) {
383 -            perror("mmap");
384 -            exit(-1);
385 -        }
386 -
387 -#ifdef LOW_ELF_STACK
388 -        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
389 -            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
390 -#endif
391 -
392 -        if (!load_addr_set) {
393 -            load_addr_set = 1;
394 -            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
395 -            if (elf_ex.e_type == ET_DYN) {
396 -                load_bias += error -
397 -                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
398 -                load_addr += load_bias;
399 -            }
400 -        }
401 -        k = elf_ppnt->p_vaddr;
402 -        if (k < start_code)
403 -            start_code = k;
404 -        if (start_data < k)
405 -            start_data = k;
406 -        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
407 -        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
408 -            end_code = k;
409 -        if (end_data < k)
410 -            end_data = k;
411 -        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
412 -        if (k > elf_brk) {
413 -            elf_brk = TARGET_PAGE_ALIGN(k);
414 -        }
415 -
416 -        /* If the load segment requests extra zeros (e.g. bss), map it.  */
417 -        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
418 -            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
419 -            zero_bss(base + elf_ppnt->p_filesz,
420 -                     base + elf_ppnt->p_memsz, elf_prot);
421 -        }
422 -    }
423 -
424 -    elf_entry += load_bias;
425 -    elf_brk += load_bias;
426 -    start_code += load_bias;
427 -    end_code += load_bias;
428 -    start_data += load_bias;
429 -    end_data += load_bias;
430 -
431 -    info->load_bias = load_bias;
432 -    info->load_addr = load_addr;
433 -    info->entry = elf_entry;
434 -    info->start_brk = info->brk = elf_brk;
435 -    info->end_code = end_code;
436 -    info->start_code = start_code;
437 -    info->start_data = start_data;
438 -    info->end_data = end_data;
439 -    info->personality = PER_LINUX;
440 -
441 -    free(elf_phdata);
442 -
443 -    if (qemu_log_enabled()) {
444 -        load_symbols(&elf_ex, bprm->fd, load_bias);
445 -    }
446 -
447 -    close(bprm->fd);
448  
449      if (elf_interpreter) {
450          load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
451 @@ -1796,6 +1621,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
452      if (elf_interpreter) {
453          info->load_addr = interp_info.load_addr;
454          info->entry = interp_info.entry;
455 +        free(elf_interpreter);
456      }
457  
458  #ifdef USE_ELF_CORE_DUMP
459 --
460 cgit v0.8.3.4