Commit 863cf0b72cee98e42aa03403c38d5cac7fa535ca
1 parent
f2e63a42
Fix confusions between host and target long types.
Fix start_data computation. Fix auxiliary infos setup. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3344 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
61 additions
and
47 deletions
linux-user/elfload.c
... | ... | @@ -124,6 +124,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i |
124 | 124 | /* XXX: it seems that r0 is zeroed after ! */ |
125 | 125 | regs->ARM_r0 = 0; |
126 | 126 | /* For uClinux PIC binaries. */ |
127 | + /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ | |
127 | 128 | regs->ARM_r10 = infop->start_data; |
128 | 129 | } |
129 | 130 | |
... | ... | @@ -516,8 +517,8 @@ static void bswap_sym(struct elf_sym *sym) |
516 | 517 | * to be put directly into the top of new user memory. |
517 | 518 | * |
518 | 519 | */ |
519 | -static unsigned long copy_elf_strings(int argc,char ** argv, void **page, | |
520 | - target_ulong p) | |
520 | +static target_ulong copy_elf_strings(int argc,char ** argv, void **page, | |
521 | + target_ulong p) | |
521 | 522 | { |
522 | 523 | char *tmp, *tmp1, *pag = NULL; |
523 | 524 | int len, offset = 0; |
... | ... | @@ -566,8 +567,8 @@ static unsigned long copy_elf_strings(int argc,char ** argv, void **page, |
566 | 567 | return p; |
567 | 568 | } |
568 | 569 | |
569 | -unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm, | |
570 | - struct image_info * info) | |
570 | +target_ulong setup_arg_pages(target_ulong p, struct linux_binprm * bprm, | |
571 | + struct image_info * info) | |
571 | 572 | { |
572 | 573 | target_ulong stack_base, size, error; |
573 | 574 | int i; |
... | ... | @@ -605,7 +606,7 @@ unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm, |
605 | 606 | return p; |
606 | 607 | } |
607 | 608 | |
608 | -static void set_brk(unsigned long start, unsigned long end) | |
609 | +static void set_brk(target_ulong start, target_ulong end) | |
609 | 610 | { |
610 | 611 | /* page-align the start and end addresses... */ |
611 | 612 | start = HOST_PAGE_ALIGN(start); |
... | ... | @@ -624,9 +625,9 @@ static void set_brk(unsigned long start, unsigned long end) |
624 | 625 | /* We need to explicitly zero any fractional pages after the data |
625 | 626 | section (i.e. bss). This would contain the junk from the file that |
626 | 627 | should not be in memory. */ |
627 | -static void padzero(unsigned long elf_bss, unsigned long last_bss) | |
628 | +static void padzero(target_ulong elf_bss, target_ulong last_bss) | |
628 | 629 | { |
629 | - unsigned long nbyte; | |
630 | + target_ulong nbyte; | |
630 | 631 | |
631 | 632 | if (elf_bss >= last_bss) |
632 | 633 | return; |
... | ... | @@ -637,12 +638,12 @@ static void padzero(unsigned long elf_bss, unsigned long last_bss) |
637 | 638 | patch target_mmap(), but it is more complicated as the file |
638 | 639 | size must be known */ |
639 | 640 | if (qemu_real_host_page_size < qemu_host_page_size) { |
640 | - unsigned long end_addr, end_addr1; | |
641 | + target_ulong end_addr, end_addr1; | |
641 | 642 | end_addr1 = (elf_bss + qemu_real_host_page_size - 1) & |
642 | 643 | ~(qemu_real_host_page_size - 1); |
643 | 644 | end_addr = HOST_PAGE_ALIGN(elf_bss); |
644 | 645 | if (end_addr1 < end_addr) { |
645 | - mmap((void *)end_addr1, end_addr - end_addr1, | |
646 | + mmap((void *)g2h(end_addr1), end_addr - end_addr1, | |
646 | 647 | PROT_READ|PROT_WRITE|PROT_EXEC, |
647 | 648 | MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); |
648 | 649 | } |
... | ... | @@ -659,18 +660,18 @@ static void padzero(unsigned long elf_bss, unsigned long last_bss) |
659 | 660 | } |
660 | 661 | |
661 | 662 | |
662 | -static unsigned long create_elf_tables(target_ulong p, int argc, int envc, | |
663 | - struct elfhdr * exec, | |
664 | - unsigned long load_addr, | |
665 | - unsigned long load_bias, | |
666 | - unsigned long interp_load_addr, int ibcs, | |
667 | - struct image_info *info) | |
663 | +static target_ulong create_elf_tables(target_ulong p, int argc, int envc, | |
664 | + struct elfhdr * exec, | |
665 | + target_ulong load_addr, | |
666 | + target_ulong load_bias, | |
667 | + target_ulong interp_load_addr, int ibcs, | |
668 | + struct image_info *info) | |
668 | 669 | { |
669 | 670 | target_ulong sp; |
670 | 671 | int size; |
671 | 672 | target_ulong u_platform; |
672 | 673 | const char *k_platform; |
673 | - const int n = sizeof(target_ulong); | |
674 | + const int n = sizeof(elf_addr_t); | |
674 | 675 | |
675 | 676 | sp = p; |
676 | 677 | u_platform = 0; |
... | ... | @@ -697,10 +698,20 @@ static unsigned long create_elf_tables(target_ulong p, int argc, int envc, |
697 | 698 | if (size & 15) |
698 | 699 | sp -= 16 - (size & 15); |
699 | 700 | |
701 | + /* This is correct because Linux defines | |
702 | + * elf_addr_t as Elf32_Off / Elf64_Off | |
703 | + */ | |
704 | +#if ELF_CLASS == ELFCLASS32 | |
700 | 705 | #define NEW_AUX_ENT(id, val) do { \ |
701 | - sp -= n; tputl(sp, val); \ | |
702 | - sp -= n; tputl(sp, id); \ | |
706 | + sp -= n; tput32(sp, val); \ | |
707 | + sp -= n; tput32(sp, id); \ | |
703 | 708 | } while(0) |
709 | +#else | |
710 | +#define NEW_AUX_ENT(id, val) do { \ | |
711 | + sp -= n; tput64(sp, val); \ | |
712 | + sp -= n; tput64(sp, id); \ | |
713 | + } while(0) | |
714 | +#endif | |
704 | 715 | NEW_AUX_ENT (AT_NULL, 0); |
705 | 716 | |
706 | 717 | /* There must be exactly DLINFO_ITEMS entries here. */ |
... | ... | @@ -732,17 +743,17 @@ static unsigned long create_elf_tables(target_ulong p, int argc, int envc, |
732 | 743 | } |
733 | 744 | |
734 | 745 | |
735 | -static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |
736 | - int interpreter_fd, | |
737 | - unsigned long *interp_load_addr) | |
746 | +static target_ulong load_elf_interp(struct elfhdr * interp_elf_ex, | |
747 | + int interpreter_fd, | |
748 | + target_ulong *interp_load_addr) | |
738 | 749 | { |
739 | 750 | struct elf_phdr *elf_phdata = NULL; |
740 | 751 | struct elf_phdr *eppnt; |
741 | - unsigned long load_addr = 0; | |
752 | + target_ulong load_addr = 0; | |
742 | 753 | int load_addr_set = 0; |
743 | 754 | int retval; |
744 | - unsigned long last_bss, elf_bss; | |
745 | - unsigned long error; | |
755 | + target_ulong last_bss, elf_bss; | |
756 | + target_ulong error; | |
746 | 757 | int i; |
747 | 758 | |
748 | 759 | elf_bss = 0; |
... | ... | @@ -756,20 +767,20 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
756 | 767 | if ((interp_elf_ex->e_type != ET_EXEC && |
757 | 768 | interp_elf_ex->e_type != ET_DYN) || |
758 | 769 | !elf_check_arch(interp_elf_ex->e_machine)) { |
759 | - return ~0UL; | |
770 | + return ~((target_ulong)0UL); | |
760 | 771 | } |
761 | 772 | |
762 | 773 | |
763 | 774 | /* Now read in all of the header information */ |
764 | 775 | |
765 | 776 | if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) |
766 | - return ~0UL; | |
777 | + return ~(target_ulong)0UL; | |
767 | 778 | |
768 | 779 | elf_phdata = (struct elf_phdr *) |
769 | 780 | malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); |
770 | 781 | |
771 | 782 | if (!elf_phdata) |
772 | - return ~0UL; | |
783 | + return ~((target_ulong)0UL); | |
773 | 784 | |
774 | 785 | /* |
775 | 786 | * If the size of this structure has changed, then punt, since |
... | ... | @@ -777,7 +788,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
777 | 788 | */ |
778 | 789 | if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { |
779 | 790 | free(elf_phdata); |
780 | - return ~0UL; | |
791 | + return ~((target_ulong)0UL); | |
781 | 792 | } |
782 | 793 | |
783 | 794 | retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); |
... | ... | @@ -818,8 +829,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
818 | 829 | if (eppnt->p_type == PT_LOAD) { |
819 | 830 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; |
820 | 831 | int elf_prot = 0; |
821 | - unsigned long vaddr = 0; | |
822 | - unsigned long k; | |
832 | + target_ulong vaddr = 0; | |
833 | + target_ulong k; | |
823 | 834 | |
824 | 835 | if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; |
825 | 836 | if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; |
... | ... | @@ -839,7 +850,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
839 | 850 | /* Real error */ |
840 | 851 | close(interpreter_fd); |
841 | 852 | free(elf_phdata); |
842 | - return ~0UL; | |
853 | + return ~((target_ulong)0UL); | |
843 | 854 | } |
844 | 855 | |
845 | 856 | if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { |
... | ... | @@ -884,7 +895,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
884 | 895 | free(elf_phdata); |
885 | 896 | |
886 | 897 | *interp_load_addr = load_addr; |
887 | - return ((unsigned long) interp_elf_ex->e_entry) + load_addr; | |
898 | + return ((target_ulong) interp_elf_ex->e_entry) + load_addr; | |
888 | 899 | } |
889 | 900 | |
890 | 901 | /* Best attempt to load symbols from this ELF object. */ |
... | ... | @@ -972,22 +983,22 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
972 | 983 | struct elfhdr interp_elf_ex; |
973 | 984 | struct exec interp_ex; |
974 | 985 | int interpreter_fd = -1; /* avoid warning */ |
975 | - unsigned long load_addr, load_bias; | |
986 | + target_ulong load_addr, load_bias; | |
976 | 987 | int load_addr_set = 0; |
977 | 988 | unsigned int interpreter_type = INTERPRETER_NONE; |
978 | 989 | unsigned char ibcs2_interpreter; |
979 | 990 | int i; |
980 | - unsigned long mapped_addr; | |
991 | + target_ulong mapped_addr; | |
981 | 992 | struct elf_phdr * elf_ppnt; |
982 | 993 | struct elf_phdr *elf_phdata; |
983 | - unsigned long elf_bss, k, elf_brk; | |
994 | + target_ulong elf_bss, k, elf_brk; | |
984 | 995 | int retval; |
985 | 996 | char * elf_interpreter; |
986 | - unsigned long elf_entry, interp_load_addr = 0; | |
997 | + target_ulong elf_entry, interp_load_addr = 0; | |
987 | 998 | int status; |
988 | - unsigned long start_code, end_code, end_data; | |
989 | - unsigned long reloc_func_desc = 0; | |
990 | - unsigned long elf_stack; | |
999 | + target_ulong start_code, end_code, start_data, end_data; | |
1000 | + target_ulong reloc_func_desc = 0; | |
1001 | + target_ulong elf_stack; | |
991 | 1002 | char passed_fileno[6]; |
992 | 1003 | |
993 | 1004 | ibcs2_interpreter = 0; |
... | ... | @@ -1043,10 +1054,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1043 | 1054 | elf_brk = 0; |
1044 | 1055 | |
1045 | 1056 | |
1046 | - elf_stack = ~0UL; | |
1057 | + elf_stack = ~((target_ulong)0UL); | |
1047 | 1058 | elf_interpreter = NULL; |
1048 | - start_code = ~0UL; | |
1059 | + start_code = ~((target_ulong)0UL); | |
1049 | 1060 | end_code = 0; |
1061 | + start_data = 0; | |
1050 | 1062 | end_data = 0; |
1051 | 1063 | |
1052 | 1064 | for(i=0;i < elf_ex.e_phnum; i++) { |
... | ... | @@ -1180,9 +1192,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1180 | 1192 | /* OK, This is the point of no return */ |
1181 | 1193 | info->end_data = 0; |
1182 | 1194 | info->end_code = 0; |
1183 | - info->start_mmap = (unsigned long)ELF_START_MMAP; | |
1195 | + info->start_mmap = (target_ulong)ELF_START_MMAP; | |
1184 | 1196 | info->mmap = 0; |
1185 | - elf_entry = (unsigned long) elf_ex.e_entry; | |
1197 | + elf_entry = (target_ulong) elf_ex.e_entry; | |
1186 | 1198 | |
1187 | 1199 | /* Do this so that we can load the interpreter, if need be. We will |
1188 | 1200 | change some of these later */ |
... | ... | @@ -1199,7 +1211,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1199 | 1211 | for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { |
1200 | 1212 | int elf_prot = 0; |
1201 | 1213 | int elf_flags = 0; |
1202 | - unsigned long error; | |
1214 | + target_ulong error; | |
1203 | 1215 | |
1204 | 1216 | if (elf_ppnt->p_type != PT_LOAD) |
1205 | 1217 | continue; |
... | ... | @@ -1257,6 +1269,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1257 | 1269 | k = elf_ppnt->p_vaddr; |
1258 | 1270 | if (k < start_code) |
1259 | 1271 | start_code = k; |
1272 | + if (start_data < k) | |
1273 | + start_data = k; | |
1260 | 1274 | k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; |
1261 | 1275 | if (k > elf_bss) |
1262 | 1276 | elf_bss = k; |
... | ... | @@ -1273,7 +1287,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1273 | 1287 | elf_brk += load_bias; |
1274 | 1288 | start_code += load_bias; |
1275 | 1289 | end_code += load_bias; |
1276 | - // start_data += load_bias; | |
1290 | + start_data += load_bias; | |
1277 | 1291 | end_data += load_bias; |
1278 | 1292 | |
1279 | 1293 | if (elf_interpreter) { |
... | ... | @@ -1289,7 +1303,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1289 | 1303 | close(interpreter_fd); |
1290 | 1304 | free(elf_interpreter); |
1291 | 1305 | |
1292 | - if (elf_entry == ~0UL) { | |
1306 | + if (elf_entry == ~((target_ulong)0UL)) { | |
1293 | 1307 | printf("Unable to load interpreter\n"); |
1294 | 1308 | free(elf_phdata); |
1295 | 1309 | exit(-1); |
... | ... | @@ -1320,7 +1334,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
1320 | 1334 | info->start_brk = info->brk = elf_brk; |
1321 | 1335 | info->end_code = end_code; |
1322 | 1336 | info->start_code = start_code; |
1323 | - info->start_data = end_code; | |
1337 | + info->start_data = start_data; | |
1324 | 1338 | info->end_data = end_data; |
1325 | 1339 | info->start_stack = bprm->p; |
1326 | 1340 | ... | ... |