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 | { | ... | ... |