Revision 863cf0b7 linux-user/elfload.c
b/linux-user/elfload.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
|
Also available in: Unified diff