Commit 09bfb054fb4d7a72b4989141de157cdeda6704bd
1 parent
2677e107
first self virtualizable version
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@89 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
217 additions
and
105 deletions
Makefile
... | ... | @@ -105,7 +105,7 @@ qemu-doc.html: qemu-doc.texi |
105 | 105 | FILES= \ |
106 | 106 | README README.distrib COPYING COPYING.LIB TODO Changelog VERSION \ |
107 | 107 | dyngen.c ioctls.h ops_template.h op_string.h syscall_types.h\ |
108 | -Makefile elf.h linux_bin.h segment.h thunk.c\ | |
108 | +Makefile elf.h thunk.c\ | |
109 | 109 | elfload.c main.c signal.c thunk.h\ |
110 | 110 | cpu-i386.h qemu.h op-i386.c opc-i386.h syscall-i386.h translate-i386.c\ |
111 | 111 | dis-asm.h gen-i386.h syscall.c\ | ... | ... |
TODO
... | ... | @@ -7,5 +7,6 @@ |
7 | 7 | issues, fix 16 bit uid issues) |
8 | 8 | - finish signal handing (fp87 state, more siginfo conversions) |
9 | 9 | - verify thread support (clone() and various locks) |
10 | -- make it self runnable (use same trick as ld.so : include its own relocator and libc) | |
10 | +- make it self runnable (handle self modifying code, relocate stack | |
11 | + and dyn loader) | |
11 | 12 | - fix FPU exceptions (in particular: gen_op_fpush not before mem load) | ... | ... |
linux-user/elfload.c
... | ... | @@ -49,9 +49,78 @@ typedef struct user_i387_struct elf_fpregset_t; |
49 | 49 | |
50 | 50 | #endif |
51 | 51 | |
52 | -#include "linux_bin.h" | |
53 | 52 | #include "elf.h" |
54 | -#include "segment.h" | |
53 | + | |
54 | +/* | |
55 | + * MAX_ARG_PAGES defines the number of pages allocated for arguments | |
56 | + * and envelope for the new program. 32 should suffice, this gives | |
57 | + * a maximum env+arg of 128kB w/4KB pages! | |
58 | + */ | |
59 | +#define MAX_ARG_PAGES 32 | |
60 | + | |
61 | +/* | |
62 | + * This structure is used to hold the arguments that are | |
63 | + * used when loading binaries. | |
64 | + */ | |
65 | +struct linux_binprm { | |
66 | + char buf[128]; | |
67 | + unsigned long page[MAX_ARG_PAGES]; | |
68 | + unsigned long p; | |
69 | + int sh_bang; | |
70 | + int fd; | |
71 | + int e_uid, e_gid; | |
72 | + int argc, envc; | |
73 | + char * interp_prefix; /* prefix for interpreter */ | |
74 | + char * filename; /* Name of binary */ | |
75 | + unsigned long loader, exec; | |
76 | + int dont_iput; /* binfmt handler has put inode */ | |
77 | +}; | |
78 | + | |
79 | +struct exec | |
80 | +{ | |
81 | + unsigned int a_info; /* Use macros N_MAGIC, etc for access */ | |
82 | + unsigned int a_text; /* length of text, in bytes */ | |
83 | + unsigned int a_data; /* length of data, in bytes */ | |
84 | + unsigned int a_bss; /* length of uninitialized data area, in bytes */ | |
85 | + unsigned int a_syms; /* length of symbol table data in file, in bytes */ | |
86 | + unsigned int a_entry; /* start address */ | |
87 | + unsigned int a_trsize; /* length of relocation info for text, in bytes */ | |
88 | + unsigned int a_drsize; /* length of relocation info for data, in bytes */ | |
89 | +}; | |
90 | + | |
91 | + | |
92 | +#define N_MAGIC(exec) ((exec).a_info & 0xffff) | |
93 | +#define OMAGIC 0407 | |
94 | +#define NMAGIC 0410 | |
95 | +#define ZMAGIC 0413 | |
96 | +#define QMAGIC 0314 | |
97 | + | |
98 | +#define X86_STACK_TOP 0x7d000000 | |
99 | + | |
100 | +/* max code+data+bss space allocated to elf interpreter */ | |
101 | +#define INTERP_MAP_SIZE (32 * 1024 * 1024) | |
102 | + | |
103 | +/* max code+data+bss+brk space allocated to ET_DYN executables */ | |
104 | +#define ET_DYN_MAP_SIZE (128 * 1024 * 1024) | |
105 | + | |
106 | +/* from personality.h */ | |
107 | + | |
108 | +/* Flags for bug emulation. These occupy the top three bytes. */ | |
109 | +#define STICKY_TIMEOUTS 0x4000000 | |
110 | +#define WHOLE_SECONDS 0x2000000 | |
111 | + | |
112 | +/* Personality types. These go in the low byte. Avoid using the top bit, | |
113 | + * it will conflict with error returns. | |
114 | + */ | |
115 | +#define PER_MASK (0x00ff) | |
116 | +#define PER_LINUX (0x0000) | |
117 | +#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) | |
118 | +#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) | |
119 | +#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) | |
120 | +#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) | |
121 | +#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) | |
122 | +#define PER_BSD (0x0006) | |
123 | +#define PER_XENIX (0x0007 | STICKY_TIMEOUTS) | |
55 | 124 | |
56 | 125 | /* Necessary parameters */ |
57 | 126 | #define ALPHA_PAGE_SIZE 4096 |
... | ... | @@ -78,8 +147,18 @@ typedef struct user_i387_struct elf_fpregset_t; |
78 | 147 | |
79 | 148 | #define DLINFO_ITEMS 12 |
80 | 149 | |
81 | -/* Where we find X86 libraries... */ | |
150 | +#define put_user(x,ptr) (void)(*(ptr) = (typeof(*ptr))(x)) | |
151 | +#define get_user(ptr) (typeof(*ptr))(*(ptr)) | |
152 | + | |
153 | +static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) | |
154 | +{ | |
155 | + memcpy(to, from, n); | |
156 | +} | |
82 | 157 | |
158 | +static inline void memcpy_tofs(void * to, const void * from, unsigned long n) | |
159 | +{ | |
160 | + memcpy(to, from, n); | |
161 | +} | |
83 | 162 | |
84 | 163 | //extern void * mmap4k(); |
85 | 164 | #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f) |
... | ... | @@ -282,43 +361,35 @@ static int prepare_binprm(struct linux_binprm *bprm) |
282 | 361 | unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, |
283 | 362 | struct image_info * info) |
284 | 363 | { |
285 | - unsigned long stack_base; | |
364 | + unsigned long stack_base, size, error; | |
286 | 365 | int i; |
287 | - extern unsigned long stktop; | |
288 | 366 | |
289 | - stack_base = X86_STACK_TOP - MAX_ARG_PAGES*X86_PAGE_SIZE; | |
367 | + /* Create enough stack to hold everything. If we don't use | |
368 | + * it for args, we'll use it for something else... | |
369 | + */ | |
370 | + size = x86_stack_size; | |
371 | + if (size < MAX_ARG_PAGES*X86_PAGE_SIZE) | |
372 | + size = MAX_ARG_PAGES*X86_PAGE_SIZE; | |
373 | + error = (unsigned long)mmap4k(NULL, | |
374 | + size + X86_PAGE_SIZE, | |
375 | + PROT_READ | PROT_WRITE, | |
376 | + MAP_PRIVATE | MAP_ANONYMOUS, | |
377 | + -1, 0); | |
378 | + if (error == -1) { | |
379 | + perror("stk mmap"); | |
380 | + exit(-1); | |
381 | + } | |
382 | + /* we reserve one extra page at the top of the stack as guard */ | |
383 | + mprotect((void *)(error + size), X86_PAGE_SIZE, PROT_NONE); | |
290 | 384 | |
385 | + stack_base = error + size - MAX_ARG_PAGES*X86_PAGE_SIZE; | |
291 | 386 | p += stack_base; |
387 | + | |
292 | 388 | if (bprm->loader) { |
293 | 389 | bprm->loader += stack_base; |
294 | 390 | } |
295 | 391 | bprm->exec += stack_base; |
296 | 392 | |
297 | - /* Create enough stack to hold everything. If we don't use | |
298 | - * it for args, we'll use it for something else... | |
299 | - */ | |
300 | - /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so | |
301 | - we allocate a bigger stack. Need a better solution, for example | |
302 | - by remapping the process stack directly at the right place */ | |
303 | - if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) { | |
304 | - if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE, | |
305 | - PROT_READ | PROT_WRITE, | |
306 | - MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { | |
307 | - perror("stk mmap"); | |
308 | - exit(-1); | |
309 | - } | |
310 | - } | |
311 | - else { | |
312 | - if((long)mmap4k((void *)stack_base, (MAX_ARG_PAGES+1)*X86_PAGE_SIZE, | |
313 | - PROT_READ | PROT_WRITE, | |
314 | - MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { | |
315 | - perror("stk mmap"); | |
316 | - exit(-1); | |
317 | - } | |
318 | - } | |
319 | - | |
320 | - stktop = stack_base; | |
321 | - | |
322 | 393 | for (i = 0 ; i < MAX_ARG_PAGES ; i++) { |
323 | 394 | if (bprm->page[i]) { |
324 | 395 | info->rss++; |
... | ... | @@ -369,10 +440,11 @@ static void padzero(unsigned long elf_bss) |
369 | 440 | } |
370 | 441 | |
371 | 442 | static unsigned int * create_elf_tables(char *p, int argc, int envc, |
372 | - struct elfhdr * exec, | |
373 | - unsigned long load_addr, | |
374 | - unsigned long interp_load_addr, int ibcs, | |
375 | - struct image_info *info) | |
443 | + struct elfhdr * exec, | |
444 | + unsigned long load_addr, | |
445 | + unsigned long load_bias, | |
446 | + unsigned long interp_load_addr, int ibcs, | |
447 | + struct image_info *info) | |
376 | 448 | { |
377 | 449 | target_ulong *argv, *envp, *dlinfo; |
378 | 450 | target_ulong *sp; |
... | ... | @@ -397,17 +469,17 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, |
397 | 469 | put_user (tswapl(val), dlinfo++) |
398 | 470 | |
399 | 471 | if (exec) { /* Put this here for an ELF program interpreter */ |
400 | - NEW_AUX_ENT (AT_PHDR, (unsigned int)(load_addr + exec->e_phoff)); | |
401 | - NEW_AUX_ENT (AT_PHENT, (unsigned int)(sizeof (struct elf_phdr))); | |
402 | - NEW_AUX_ENT (AT_PHNUM, (unsigned int)(exec->e_phnum)); | |
403 | - NEW_AUX_ENT (AT_PAGESZ, (unsigned int)(ALPHA_PAGE_SIZE)); | |
404 | - NEW_AUX_ENT (AT_BASE, (unsigned int)(interp_load_addr)); | |
405 | - NEW_AUX_ENT (AT_FLAGS, (unsigned int)0); | |
406 | - NEW_AUX_ENT (AT_ENTRY, (unsigned int) exec->e_entry); | |
407 | - NEW_AUX_ENT (AT_UID, (unsigned int) getuid()); | |
408 | - NEW_AUX_ENT (AT_EUID, (unsigned int) geteuid()); | |
409 | - NEW_AUX_ENT (AT_GID, (unsigned int) getgid()); | |
410 | - NEW_AUX_ENT (AT_EGID, (unsigned int) getegid()); | |
472 | + NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff)); | |
473 | + NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr))); | |
474 | + NEW_AUX_ENT (AT_PHNUM, (target_ulong)(exec->e_phnum)); | |
475 | + NEW_AUX_ENT (AT_PAGESZ, (target_ulong)(ALPHA_PAGE_SIZE)); | |
476 | + NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr)); | |
477 | + NEW_AUX_ENT (AT_FLAGS, (target_ulong)0); | |
478 | + NEW_AUX_ENT (AT_ENTRY, load_bias + exec->e_entry); | |
479 | + NEW_AUX_ENT (AT_UID, (target_ulong) getuid()); | |
480 | + NEW_AUX_ENT (AT_EUID, (target_ulong) geteuid()); | |
481 | + NEW_AUX_ENT (AT_GID, (target_ulong) getgid()); | |
482 | + NEW_AUX_ENT (AT_EGID, (target_ulong) getegid()); | |
411 | 483 | } |
412 | 484 | NEW_AUX_ENT (AT_NULL, 0); |
413 | 485 | #undef NEW_AUX_ENT |
... | ... | @@ -436,7 +508,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
436 | 508 | { |
437 | 509 | struct elf_phdr *elf_phdata = NULL; |
438 | 510 | struct elf_phdr *eppnt; |
439 | - unsigned long load_addr; | |
511 | + unsigned long load_addr = 0; | |
440 | 512 | int load_addr_set = 0; |
441 | 513 | int retval; |
442 | 514 | unsigned long last_bss, elf_bss; |
... | ... | @@ -447,17 +519,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
447 | 519 | last_bss = 0; |
448 | 520 | error = 0; |
449 | 521 | |
450 | - /* We put this here so that mmap will search for the *first* | |
451 | - * available memory... | |
452 | - */ | |
453 | - load_addr = INTERP_LOADADDR; | |
454 | - | |
455 | 522 | #ifdef BSWAP_NEEDED |
456 | 523 | bswap_ehdr(interp_elf_ex); |
457 | 524 | #endif |
458 | 525 | /* First of all, some simple consistency checks */ |
459 | 526 | if ((interp_elf_ex->e_type != ET_EXEC && |
460 | - interp_elf_ex->e_type != ET_DYN) || | |
527 | + interp_elf_ex->e_type != ET_DYN) || | |
461 | 528 | !elf_check_arch(interp_elf_ex->e_machine)) { |
462 | 529 | return ~0UL; |
463 | 530 | } |
... | ... | @@ -478,11 +545,10 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
478 | 545 | * If the size of this structure has changed, then punt, since |
479 | 546 | * we will be doing the wrong thing. |
480 | 547 | */ |
481 | - if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) | |
482 | - { | |
548 | + if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { | |
483 | 549 | free(elf_phdata); |
484 | 550 | return ~0UL; |
485 | - } | |
551 | + } | |
486 | 552 | |
487 | 553 | retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); |
488 | 554 | if(retval >= 0) { |
... | ... | @@ -502,6 +568,21 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
502 | 568 | bswap_phdr(eppnt); |
503 | 569 | } |
504 | 570 | #endif |
571 | + | |
572 | + if (interp_elf_ex->e_type == ET_DYN) { | |
573 | + /* in order to avoid harcoding the interpreter load | |
574 | + address in qemu, we allocate a big enough memory zone */ | |
575 | + error = (unsigned long)mmap4k(NULL, INTERP_MAP_SIZE, | |
576 | + PROT_NONE, MAP_PRIVATE | MAP_ANON, | |
577 | + -1, 0); | |
578 | + if (error == -1) { | |
579 | + perror("mmap"); | |
580 | + exit(-1); | |
581 | + } | |
582 | + load_addr = error; | |
583 | + load_addr_set = 1; | |
584 | + } | |
585 | + | |
505 | 586 | eppnt = elf_phdata; |
506 | 587 | for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) |
507 | 588 | if (eppnt->p_type == PT_LOAD) { |
... | ... | @@ -585,7 +666,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
585 | 666 | struct elfhdr interp_elf_ex; |
586 | 667 | struct exec interp_ex; |
587 | 668 | int interpreter_fd = -1; /* avoid warning */ |
588 | - unsigned long load_addr; | |
669 | + unsigned long load_addr, load_bias; | |
589 | 670 | int load_addr_set = 0; |
590 | 671 | unsigned int interpreter_type = INTERPRETER_NONE; |
591 | 672 | unsigned char ibcs2_interpreter; |
... | ... | @@ -605,6 +686,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
605 | 686 | ibcs2_interpreter = 0; |
606 | 687 | status = 0; |
607 | 688 | load_addr = 0; |
689 | + load_bias = 0; | |
608 | 690 | elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ |
609 | 691 | #ifdef BSWAP_NEEDED |
610 | 692 | bswap_ehdr(&elf_ex); |
... | ... | @@ -810,56 +892,86 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
810 | 892 | * address. |
811 | 893 | */ |
812 | 894 | |
813 | - | |
814 | - | |
815 | 895 | for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { |
816 | - if (elf_ppnt->p_type == PT_LOAD) { | |
817 | - int elf_prot = 0; | |
818 | - if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; | |
819 | - if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | |
820 | - if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | |
821 | - | |
822 | - mapped_addr = mmap4k(X86_ELF_PAGESTART(elf_ppnt->p_vaddr), | |
823 | - (elf_ppnt->p_filesz + | |
824 | - X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), | |
825 | - elf_prot, | |
826 | - (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), | |
827 | - bprm->fd, | |
828 | - (elf_ppnt->p_offset - | |
829 | - X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); | |
830 | - | |
831 | - if((unsigned long)mapped_addr == 0xffffffffffffffff) { | |
832 | - perror("mmap"); | |
833 | - exit(-1); | |
834 | - } | |
835 | - | |
836 | - | |
896 | + int elf_prot = 0; | |
897 | + int elf_flags = 0; | |
898 | + unsigned long error; | |
899 | + | |
900 | + if (elf_ppnt->p_type != PT_LOAD) | |
901 | + continue; | |
902 | + | |
903 | + if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; | |
904 | + if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | |
905 | + if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | |
906 | + elf_flags = MAP_PRIVATE | MAP_DENYWRITE; | |
907 | + if (elf_ex.e_type == ET_EXEC || load_addr_set) { | |
908 | + elf_flags |= MAP_FIXED; | |
909 | + } else if (elf_ex.e_type == ET_DYN) { | |
910 | + /* Try and get dynamic programs out of the way of the default mmap | |
911 | + base, as well as whatever program they might try to exec. This | |
912 | + is because the brk will follow the loader, and is not movable. */ | |
913 | + /* NOTE: for qemu, we do a big mmap to get enough space | |
914 | + without harcoding any address */ | |
915 | + error = (unsigned long)mmap4k(NULL, ET_DYN_MAP_SIZE, | |
916 | + PROT_NONE, MAP_PRIVATE | MAP_ANON, | |
917 | + -1, 0); | |
918 | + if (error == -1) { | |
919 | + perror("mmap"); | |
920 | + exit(-1); | |
921 | + } | |
922 | + load_bias = X86_ELF_PAGESTART(error - elf_ppnt->p_vaddr); | |
923 | + } | |
924 | + | |
925 | + error = (unsigned long)mmap4k( | |
926 | + X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), | |
927 | + (elf_ppnt->p_filesz + | |
928 | + X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), | |
929 | + elf_prot, | |
930 | + (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), | |
931 | + bprm->fd, | |
932 | + (elf_ppnt->p_offset - | |
933 | + X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); | |
934 | + if (error == -1) { | |
935 | + perror("mmap"); | |
936 | + exit(-1); | |
937 | + } | |
837 | 938 | |
838 | 939 | #ifdef LOW_ELF_STACK |
839 | - if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) | |
840 | - elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr); | |
940 | + if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) | |
941 | + elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr); | |
841 | 942 | #endif |
842 | - | |
843 | - if (!load_addr_set) { | |
844 | - load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; | |
845 | - load_addr_set = 1; | |
846 | - } | |
847 | - k = elf_ppnt->p_vaddr; | |
848 | - if (k < start_code) start_code = k; | |
849 | - k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; | |
850 | - if (k > elf_bss) elf_bss = k; | |
851 | -#if 1 | |
852 | - if ((elf_ppnt->p_flags & PF_X) && end_code < k) | |
853 | -#else | |
854 | - if ( !(elf_ppnt->p_flags & PF_W) && end_code < k) | |
855 | -#endif | |
856 | - end_code = k; | |
857 | - if (end_data < k) end_data = k; | |
858 | - k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; | |
859 | - if (k > elf_brk) elf_brk = k; | |
860 | - } | |
943 | + | |
944 | + if (!load_addr_set) { | |
945 | + load_addr_set = 1; | |
946 | + load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; | |
947 | + if (elf_ex.e_type == ET_DYN) { | |
948 | + load_bias += error - | |
949 | + X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); | |
950 | + load_addr += load_bias; | |
951 | + } | |
952 | + } | |
953 | + k = elf_ppnt->p_vaddr; | |
954 | + if (k < start_code) | |
955 | + start_code = k; | |
956 | + k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; | |
957 | + if (k > elf_bss) | |
958 | + elf_bss = k; | |
959 | + if ((elf_ppnt->p_flags & PF_X) && end_code < k) | |
960 | + end_code = k; | |
961 | + if (end_data < k) | |
962 | + end_data = k; | |
963 | + k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; | |
964 | + if (k > elf_brk) elf_brk = k; | |
861 | 965 | } |
862 | 966 | |
967 | + elf_entry += load_bias; | |
968 | + elf_bss += load_bias; | |
969 | + elf_brk += load_bias; | |
970 | + start_code += load_bias; | |
971 | + end_code += load_bias; | |
972 | + // start_data += load_bias; | |
973 | + end_data += load_bias; | |
974 | + | |
863 | 975 | if (elf_interpreter) { |
864 | 976 | if (interpreter_type & 1) { |
865 | 977 | elf_entry = load_aout_interp(&interp_ex, interpreter_fd); |
... | ... | @@ -893,7 +1005,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
893 | 1005 | bprm->argc, |
894 | 1006 | bprm->envc, |
895 | 1007 | (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), |
896 | - load_addr, | |
1008 | + load_addr, load_bias, | |
897 | 1009 | interp_load_addr, |
898 | 1010 | (interpreter_type == INTERPRETER_AOUT ? 0 : 1), |
899 | 1011 | info); | ... | ... |
linux-user/main.c
... | ... | @@ -47,7 +47,6 @@ const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2"; |
47 | 47 | we allocate a bigger stack. Need a better solution, for example |
48 | 48 | by remapping the process stack directly at the right place */ |
49 | 49 | unsigned long x86_stack_size = 512 * 1024; |
50 | -unsigned long stktop; | |
51 | 50 | |
52 | 51 | void gemu_log(const char *fmt, ...) |
53 | 52 | { | ... | ... |