|
|
1.1 ! root 1: /* This is the Linux kernel elf-loading code, ported into user space */ ! 2: ! 3: #include <stdio.h> ! 4: #include <sys/types.h> ! 5: #include <fcntl.h> ! 6: #include <sys/stat.h> ! 7: #include <errno.h> ! 8: #include <unistd.h> ! 9: #include <sys/mman.h> ! 10: #include <stdlib.h> ! 11: #include <string.h> ! 12: ! 13: #include "qemu.h" ! 14: #include "disas.h" ! 15: ! 16: /* this flag is uneffective under linux too, should be deleted */ ! 17: #ifndef MAP_DENYWRITE ! 18: #define MAP_DENYWRITE 0 ! 19: #endif ! 20: ! 21: /* should probably go in elf.h */ ! 22: #ifndef ELIBBAD ! 23: #define ELIBBAD 80 ! 24: #endif ! 25: ! 26: #ifdef TARGET_I386 ! 27: ! 28: #define ELF_START_MMAP 0x80000000 ! 29: ! 30: /* ! 31: * This is used to ensure we don't load something for the wrong architecture. ! 32: */ ! 33: #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) ! 34: ! 35: /* ! 36: * These are used to set parameters in the core dumps. ! 37: */ ! 38: #define ELF_CLASS ELFCLASS32 ! 39: #define ELF_DATA ELFDATA2LSB ! 40: #define ELF_ARCH EM_386 ! 41: ! 42: /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program ! 43: starts %edx contains a pointer to a function which might be ! 44: registered using `atexit'. This provides a mean for the ! 45: dynamic linker to call DT_FINI functions for shared libraries ! 46: that have been loaded before the code runs. ! 47: ! 48: A value of 0 tells we have no such handler. */ ! 49: #define ELF_PLAT_INIT(_r) _r->edx = 0 ! 50: ! 51: static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) ! 52: { ! 53: regs->esp = infop->start_stack; ! 54: regs->eip = infop->entry; ! 55: } ! 56: ! 57: #define USE_ELF_CORE_DUMP ! 58: #define ELF_EXEC_PAGESIZE 4096 ! 59: ! 60: #endif ! 61: ! 62: #ifdef TARGET_ARM ! 63: ! 64: #define ELF_START_MMAP 0x80000000 ! 65: ! 66: #define elf_check_arch(x) ( (x) == EM_ARM ) ! 67: ! 68: #define ELF_CLASS ELFCLASS32 ! 69: #ifdef TARGET_WORDS_BIGENDIAN ! 70: #define ELF_DATA ELFDATA2MSB ! 71: #else ! 72: #define ELF_DATA ELFDATA2LSB ! 73: #endif ! 74: #define ELF_ARCH EM_ARM ! 75: ! 76: #define ELF_PLAT_INIT(_r) _r->ARM_r0 = 0 ! 77: ! 78: static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) ! 79: { ! 80: target_long *stack = (void *)infop->start_stack; ! 81: memset(regs, 0, sizeof(*regs)); ! 82: regs->ARM_cpsr = 0x10; ! 83: regs->ARM_pc = infop->entry; ! 84: regs->ARM_sp = infop->start_stack; ! 85: regs->ARM_r2 = tswapl(stack[2]); /* envp */ ! 86: regs->ARM_r1 = tswapl(stack[1]); /* argv */ ! 87: /* XXX: it seems that r0 is zeroed after ! */ ! 88: // regs->ARM_r0 = tswapl(stack[0]); /* argc */ ! 89: } ! 90: ! 91: #define USE_ELF_CORE_DUMP ! 92: #define ELF_EXEC_PAGESIZE 4096 ! 93: ! 94: #endif ! 95: ! 96: #ifdef TARGET_SPARC ! 97: #ifdef TARGET_SPARC64 ! 98: ! 99: #define ELF_START_MMAP 0x80000000 ! 100: ! 101: #define elf_check_arch(x) ( (x) == EM_SPARC ) ! 102: ! 103: #define ELF_CLASS ELFCLASS64 ! 104: #define ELF_DATA ELFDATA2MSB ! 105: #define ELF_ARCH EM_SPARC ! 106: ! 107: /*XXX*/ ! 108: #define ELF_PLAT_INIT(_r) ! 109: ! 110: static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) ! 111: { ! 112: regs->tstate = 0; ! 113: regs->pc = infop->entry; ! 114: regs->npc = regs->pc + 4; ! 115: regs->y = 0; ! 116: regs->u_regs[14] = infop->start_stack - 16 * 4; ! 117: } ! 118: ! 119: #else ! 120: #define ELF_START_MMAP 0x80000000 ! 121: ! 122: #define elf_check_arch(x) ( (x) == EM_SPARC ) ! 123: ! 124: #define ELF_CLASS ELFCLASS32 ! 125: #define ELF_DATA ELFDATA2MSB ! 126: #define ELF_ARCH EM_SPARC ! 127: ! 128: /*XXX*/ ! 129: #define ELF_PLAT_INIT(_r) ! 130: ! 131: static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) ! 132: { ! 133: regs->psr = 0; ! 134: regs->pc = infop->entry; ! 135: regs->npc = regs->pc + 4; ! 136: regs->y = 0; ! 137: regs->u_regs[14] = infop->start_stack - 16 * 4; ! 138: } ! 139: ! 140: #endif ! 141: #endif ! 142: ! 143: #ifdef TARGET_PPC ! 144: ! 145: #define ELF_START_MMAP 0x80000000 ! 146: ! 147: #define elf_check_arch(x) ( (x) == EM_PPC ) ! 148: ! 149: #define ELF_CLASS ELFCLASS32 ! 150: #ifdef TARGET_WORDS_BIGENDIAN ! 151: #define ELF_DATA ELFDATA2MSB ! 152: #else ! 153: #define ELF_DATA ELFDATA2LSB ! 154: #endif ! 155: #define ELF_ARCH EM_PPC ! 156: ! 157: /* Note that isn't exactly what regular kernel does ! 158: * but this is what the ABI wants and is needed to allow ! 159: * execution of PPC BSD programs. ! 160: */ ! 161: #define ELF_PLAT_INIT(_r) \ ! 162: do { \ ! 163: target_ulong *pos = (target_ulong *)bprm->p, tmp = 1; \ ! 164: _r->gpr[3] = bprm->argc; \ ! 165: _r->gpr[4] = (unsigned long)++pos; \ ! 166: for (; tmp != 0; pos++) \ ! 167: tmp = *pos; \ ! 168: _r->gpr[5] = (unsigned long)pos; \ ! 169: } while (0) ! 170: ! 171: /* ! 172: * We need to put in some extra aux table entries to tell glibc what ! 173: * the cache block size is, so it can use the dcbz instruction safely. ! 174: */ ! 175: #define AT_DCACHEBSIZE 19 ! 176: #define AT_ICACHEBSIZE 20 ! 177: #define AT_UCACHEBSIZE 21 ! 178: /* A special ignored type value for PPC, for glibc compatibility. */ ! 179: #define AT_IGNOREPPC 22 ! 180: /* ! 181: * The requirements here are: ! 182: * - keep the final alignment of sp (sp & 0xf) ! 183: * - make sure the 32-bit value at the first 16 byte aligned position of ! 184: * AUXV is greater than 16 for glibc compatibility. ! 185: * AT_IGNOREPPC is used for that. ! 186: * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, ! 187: * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. ! 188: */ ! 189: #define DLINFO_ARCH_ITEMS 5 ! 190: #define ARCH_DLINFO \ ! 191: do { \ ! 192: NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ ! 193: NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ ! 194: NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ ! 195: /* \ ! 196: * Now handle glibc compatibility. \ ! 197: */ \ ! 198: NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ ! 199: NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ ! 200: } while (0) ! 201: ! 202: static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) ! 203: { ! 204: _regs->msr = 1 << MSR_PR; /* Set user mode */ ! 205: _regs->gpr[1] = infop->start_stack; ! 206: _regs->nip = infop->entry; ! 207: } ! 208: ! 209: #define USE_ELF_CORE_DUMP ! 210: #define ELF_EXEC_PAGESIZE 4096 ! 211: ! 212: #endif ! 213: ! 214: #include "elf.h" ! 215: ! 216: /* ! 217: * MAX_ARG_PAGES defines the number of pages allocated for arguments ! 218: * and envelope for the new program. 32 should suffice, this gives ! 219: * a maximum env+arg of 128kB w/4KB pages! ! 220: */ ! 221: #define MAX_ARG_PAGES 32 ! 222: ! 223: /* ! 224: * This structure is used to hold the arguments that are ! 225: * used when loading binaries. ! 226: */ ! 227: struct linux_binprm { ! 228: char buf[128]; ! 229: unsigned long page[MAX_ARG_PAGES]; ! 230: unsigned long p; ! 231: int sh_bang; ! 232: int fd; ! 233: int e_uid, e_gid; ! 234: int argc, envc; ! 235: char * filename; /* Name of binary */ ! 236: unsigned long loader, exec; ! 237: int dont_iput; /* binfmt handler has put inode */ ! 238: }; ! 239: ! 240: struct exec ! 241: { ! 242: unsigned int a_info; /* Use macros N_MAGIC, etc for access */ ! 243: unsigned int a_text; /* length of text, in bytes */ ! 244: unsigned int a_data; /* length of data, in bytes */ ! 245: unsigned int a_bss; /* length of uninitialized data area, in bytes */ ! 246: unsigned int a_syms; /* length of symbol table data in file, in bytes */ ! 247: unsigned int a_entry; /* start address */ ! 248: unsigned int a_trsize; /* length of relocation info for text, in bytes */ ! 249: unsigned int a_drsize; /* length of relocation info for data, in bytes */ ! 250: }; ! 251: ! 252: ! 253: #define N_MAGIC(exec) ((exec).a_info & 0xffff) ! 254: #define OMAGIC 0407 ! 255: #define NMAGIC 0410 ! 256: #define ZMAGIC 0413 ! 257: #define QMAGIC 0314 ! 258: ! 259: /* max code+data+bss space allocated to elf interpreter */ ! 260: #define INTERP_MAP_SIZE (32 * 1024 * 1024) ! 261: ! 262: /* max code+data+bss+brk space allocated to ET_DYN executables */ ! 263: #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) ! 264: ! 265: /* from personality.h */ ! 266: ! 267: /* Flags for bug emulation. These occupy the top three bytes. */ ! 268: #define STICKY_TIMEOUTS 0x4000000 ! 269: #define WHOLE_SECONDS 0x2000000 ! 270: ! 271: /* Personality types. These go in the low byte. Avoid using the top bit, ! 272: * it will conflict with error returns. ! 273: */ ! 274: #define PER_MASK (0x00ff) ! 275: #define PER_LINUX (0x0000) ! 276: #define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) ! 277: #define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) ! 278: #define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) ! 279: #define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) ! 280: #define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) ! 281: #define PER_BSD (0x0006) ! 282: #define PER_XENIX (0x0007 | STICKY_TIMEOUTS) ! 283: ! 284: /* Necessary parameters */ ! 285: #define NGROUPS 32 ! 286: ! 287: #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE ! 288: #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) ! 289: #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) ! 290: ! 291: #define INTERPRETER_NONE 0 ! 292: #define INTERPRETER_AOUT 1 ! 293: #define INTERPRETER_ELF 2 ! 294: ! 295: #define DLINFO_ITEMS 11 ! 296: ! 297: static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) ! 298: { ! 299: memcpy(to, from, n); ! 300: } ! 301: ! 302: extern unsigned long x86_stack_size; ! 303: ! 304: static int load_aout_interp(void * exptr, int interp_fd); ! 305: ! 306: #ifdef BSWAP_NEEDED ! 307: static void bswap_ehdr(struct elfhdr *ehdr) ! 308: { ! 309: bswap16s(&ehdr->e_type); /* Object file type */ ! 310: bswap16s(&ehdr->e_machine); /* Architecture */ ! 311: bswap32s(&ehdr->e_version); /* Object file version */ ! 312: bswaptls(&ehdr->e_entry); /* Entry point virtual address */ ! 313: bswaptls(&ehdr->e_phoff); /* Program header table file offset */ ! 314: bswaptls(&ehdr->e_shoff); /* Section header table file offset */ ! 315: bswap32s(&ehdr->e_flags); /* Processor-specific flags */ ! 316: bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ ! 317: bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ ! 318: bswap16s(&ehdr->e_phnum); /* Program header table entry count */ ! 319: bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ ! 320: bswap16s(&ehdr->e_shnum); /* Section header table entry count */ ! 321: bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ ! 322: } ! 323: ! 324: static void bswap_phdr(struct elf_phdr *phdr) ! 325: { ! 326: bswap32s(&phdr->p_type); /* Segment type */ ! 327: bswaptls(&phdr->p_offset); /* Segment file offset */ ! 328: bswaptls(&phdr->p_vaddr); /* Segment virtual address */ ! 329: bswaptls(&phdr->p_paddr); /* Segment physical address */ ! 330: bswaptls(&phdr->p_filesz); /* Segment size in file */ ! 331: bswaptls(&phdr->p_memsz); /* Segment size in memory */ ! 332: bswap32s(&phdr->p_flags); /* Segment flags */ ! 333: bswaptls(&phdr->p_align); /* Segment alignment */ ! 334: } ! 335: ! 336: static void bswap_shdr(struct elf_shdr *shdr) ! 337: { ! 338: bswap32s(&shdr->sh_name); ! 339: bswap32s(&shdr->sh_type); ! 340: bswaptls(&shdr->sh_flags); ! 341: bswaptls(&shdr->sh_addr); ! 342: bswaptls(&shdr->sh_offset); ! 343: bswaptls(&shdr->sh_size); ! 344: bswap32s(&shdr->sh_link); ! 345: bswap32s(&shdr->sh_info); ! 346: bswaptls(&shdr->sh_addralign); ! 347: bswaptls(&shdr->sh_entsize); ! 348: } ! 349: ! 350: static void bswap_sym(Elf32_Sym *sym) ! 351: { ! 352: bswap32s(&sym->st_name); ! 353: bswap32s(&sym->st_value); ! 354: bswap32s(&sym->st_size); ! 355: bswap16s(&sym->st_shndx); ! 356: } ! 357: #endif ! 358: ! 359: static void * get_free_page(void) ! 360: { ! 361: void * retval; ! 362: ! 363: /* User-space version of kernel get_free_page. Returns a page-aligned ! 364: * page-sized chunk of memory. ! 365: */ ! 366: retval = (void *)target_mmap(0, qemu_host_page_size, PROT_READ|PROT_WRITE, ! 367: MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ! 368: ! 369: if((long)retval == -1) { ! 370: perror("get_free_page"); ! 371: exit(-1); ! 372: } ! 373: else { ! 374: return(retval); ! 375: } ! 376: } ! 377: ! 378: static void free_page(void * pageaddr) ! 379: { ! 380: target_munmap((unsigned long)pageaddr, qemu_host_page_size); ! 381: } ! 382: ! 383: /* ! 384: * 'copy_string()' copies argument/envelope strings from user ! 385: * memory to free pages in kernel mem. These are in a format ready ! 386: * to be put directly into the top of new user memory. ! 387: * ! 388: */ ! 389: static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, ! 390: unsigned long p) ! 391: { ! 392: char *tmp, *tmp1, *pag = NULL; ! 393: int len, offset = 0; ! 394: ! 395: if (!p) { ! 396: return 0; /* bullet-proofing */ ! 397: } ! 398: while (argc-- > 0) { ! 399: tmp = argv[argc]; ! 400: if (!tmp) { ! 401: fprintf(stderr, "VFS: argc is wrong"); ! 402: exit(-1); ! 403: } ! 404: tmp1 = tmp; ! 405: while (*tmp++); ! 406: len = tmp - tmp1; ! 407: if (p < len) { /* this shouldn't happen - 128kB */ ! 408: return 0; ! 409: } ! 410: while (len) { ! 411: --p; --tmp; --len; ! 412: if (--offset < 0) { ! 413: offset = p % TARGET_PAGE_SIZE; ! 414: pag = (char *) page[p/TARGET_PAGE_SIZE]; ! 415: if (!pag) { ! 416: pag = (char *)get_free_page(); ! 417: page[p/TARGET_PAGE_SIZE] = (unsigned long)pag; ! 418: if (!pag) ! 419: return 0; ! 420: } ! 421: } ! 422: if (len == 0 || offset == 0) { ! 423: *(pag + offset) = *tmp; ! 424: } ! 425: else { ! 426: int bytes_to_copy = (len > offset) ? offset : len; ! 427: tmp -= bytes_to_copy; ! 428: p -= bytes_to_copy; ! 429: offset -= bytes_to_copy; ! 430: len -= bytes_to_copy; ! 431: memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); ! 432: } ! 433: } ! 434: } ! 435: return p; ! 436: } ! 437: ! 438: static int in_group_p(gid_t g) ! 439: { ! 440: /* return TRUE if we're in the specified group, FALSE otherwise */ ! 441: int ngroup; ! 442: int i; ! 443: gid_t grouplist[NGROUPS]; ! 444: ! 445: ngroup = getgroups(NGROUPS, grouplist); ! 446: for(i = 0; i < ngroup; i++) { ! 447: if(grouplist[i] == g) { ! 448: return 1; ! 449: } ! 450: } ! 451: return 0; ! 452: } ! 453: ! 454: static int count(char ** vec) ! 455: { ! 456: int i; ! 457: ! 458: for(i = 0; *vec; i++) { ! 459: vec++; ! 460: } ! 461: ! 462: return(i); ! 463: } ! 464: ! 465: static int prepare_binprm(struct linux_binprm *bprm) ! 466: { ! 467: struct stat st; ! 468: int mode; ! 469: int retval, id_change; ! 470: ! 471: if(fstat(bprm->fd, &st) < 0) { ! 472: return(-errno); ! 473: } ! 474: ! 475: mode = st.st_mode; ! 476: if(!S_ISREG(mode)) { /* Must be regular file */ ! 477: return(-EACCES); ! 478: } ! 479: if(!(mode & 0111)) { /* Must have at least one execute bit set */ ! 480: return(-EACCES); ! 481: } ! 482: ! 483: bprm->e_uid = geteuid(); ! 484: bprm->e_gid = getegid(); ! 485: id_change = 0; ! 486: ! 487: /* Set-uid? */ ! 488: if(mode & S_ISUID) { ! 489: bprm->e_uid = st.st_uid; ! 490: if(bprm->e_uid != geteuid()) { ! 491: id_change = 1; ! 492: } ! 493: } ! 494: ! 495: /* Set-gid? */ ! 496: /* ! 497: * If setgid is set but no group execute bit then this ! 498: * is a candidate for mandatory locking, not a setgid ! 499: * executable. ! 500: */ ! 501: if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ! 502: bprm->e_gid = st.st_gid; ! 503: if (!in_group_p(bprm->e_gid)) { ! 504: id_change = 1; ! 505: } ! 506: } ! 507: ! 508: memset(bprm->buf, 0, sizeof(bprm->buf)); ! 509: retval = lseek(bprm->fd, 0L, SEEK_SET); ! 510: if(retval >= 0) { ! 511: retval = read(bprm->fd, bprm->buf, 128); ! 512: } ! 513: if(retval < 0) { ! 514: perror("prepare_binprm"); ! 515: exit(-1); ! 516: /* return(-errno); */ ! 517: } ! 518: else { ! 519: return(retval); ! 520: } ! 521: } ! 522: ! 523: unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, ! 524: struct image_info * info) ! 525: { ! 526: unsigned long stack_base, size, error; ! 527: int i; ! 528: ! 529: /* Create enough stack to hold everything. If we don't use ! 530: * it for args, we'll use it for something else... ! 531: */ ! 532: size = x86_stack_size; ! 533: if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ! 534: size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; ! 535: error = target_mmap(0, ! 536: size + qemu_host_page_size, ! 537: PROT_READ | PROT_WRITE, ! 538: MAP_PRIVATE | MAP_ANONYMOUS, ! 539: -1, 0); ! 540: if (error == -1) { ! 541: perror("stk mmap"); ! 542: exit(-1); ! 543: } ! 544: /* we reserve one extra page at the top of the stack as guard */ ! 545: target_mprotect(error + size, qemu_host_page_size, PROT_NONE); ! 546: ! 547: stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; ! 548: p += stack_base; ! 549: ! 550: if (bprm->loader) { ! 551: bprm->loader += stack_base; ! 552: } ! 553: bprm->exec += stack_base; ! 554: ! 555: for (i = 0 ; i < MAX_ARG_PAGES ; i++) { ! 556: if (bprm->page[i]) { ! 557: info->rss++; ! 558: ! 559: memcpy((void *)stack_base, (void *)bprm->page[i], TARGET_PAGE_SIZE); ! 560: free_page((void *)bprm->page[i]); ! 561: } ! 562: stack_base += TARGET_PAGE_SIZE; ! 563: } ! 564: return p; ! 565: } ! 566: ! 567: static void set_brk(unsigned long start, unsigned long end) ! 568: { ! 569: /* page-align the start and end addresses... */ ! 570: start = HOST_PAGE_ALIGN(start); ! 571: end = HOST_PAGE_ALIGN(end); ! 572: if (end <= start) ! 573: return; ! 574: if(target_mmap(start, end - start, ! 575: PROT_READ | PROT_WRITE | PROT_EXEC, ! 576: MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { ! 577: perror("cannot mmap brk"); ! 578: exit(-1); ! 579: } ! 580: } ! 581: ! 582: ! 583: /* We need to explicitly zero any fractional pages after the data ! 584: section (i.e. bss). This would contain the junk from the file that ! 585: should not be in memory. */ ! 586: static void padzero(unsigned long elf_bss) ! 587: { ! 588: unsigned long nbyte; ! 589: char * fpnt; ! 590: ! 591: /* XXX: this is really a hack : if the real host page size is ! 592: smaller than the target page size, some pages after the end ! 593: of the file may not be mapped. A better fix would be to ! 594: patch target_mmap(), but it is more complicated as the file ! 595: size must be known */ ! 596: if (qemu_real_host_page_size < qemu_host_page_size) { ! 597: unsigned long end_addr, end_addr1; ! 598: end_addr1 = (elf_bss + qemu_real_host_page_size - 1) & ! 599: ~(qemu_real_host_page_size - 1); ! 600: end_addr = HOST_PAGE_ALIGN(elf_bss); ! 601: if (end_addr1 < end_addr) { ! 602: mmap((void *)end_addr1, end_addr - end_addr1, ! 603: PROT_READ|PROT_WRITE|PROT_EXEC, ! 604: MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ! 605: } ! 606: } ! 607: ! 608: nbyte = elf_bss & (qemu_host_page_size-1); ! 609: if (nbyte) { ! 610: nbyte = qemu_host_page_size - nbyte; ! 611: fpnt = (char *) elf_bss; ! 612: do { ! 613: *fpnt++ = 0; ! 614: } while (--nbyte); ! 615: } ! 616: } ! 617: ! 618: static unsigned int * create_elf_tables(char *p, int argc, int envc, ! 619: struct elfhdr * exec, ! 620: unsigned long load_addr, ! 621: unsigned long load_bias, ! 622: unsigned long interp_load_addr, int ibcs, ! 623: struct image_info *info) ! 624: { ! 625: target_ulong *argv, *envp; ! 626: target_ulong *sp, *csp; ! 627: int v; ! 628: ! 629: /* ! 630: * Force 16 byte _final_ alignment here for generality. ! 631: */ ! 632: sp = (unsigned int *) (~15UL & (unsigned long) p); ! 633: csp = sp; ! 634: csp -= (DLINFO_ITEMS + 1) * 2; ! 635: #ifdef DLINFO_ARCH_ITEMS ! 636: csp -= DLINFO_ARCH_ITEMS*2; ! 637: #endif ! 638: csp -= envc+1; ! 639: csp -= argc+1; ! 640: csp -= (!ibcs ? 3 : 1); /* argc itself */ ! 641: if ((unsigned long)csp & 15UL) ! 642: sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); ! 643: ! 644: #define NEW_AUX_ENT(id, val) \ ! 645: sp -= 2; \ ! 646: put_user (id, sp); \ ! 647: put_user (val, sp + 1) ! 648: NEW_AUX_ENT (AT_NULL, 0); ! 649: ! 650: /* There must be exactly DLINFO_ITEMS entries here. */ ! 651: NEW_AUX_ENT(AT_PHDR, (target_ulong)(load_addr + exec->e_phoff)); ! 652: NEW_AUX_ENT(AT_PHENT, (target_ulong)(sizeof (struct elf_phdr))); ! 653: NEW_AUX_ENT(AT_PHNUM, (target_ulong)(exec->e_phnum)); ! 654: NEW_AUX_ENT(AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE)); ! 655: NEW_AUX_ENT(AT_BASE, (target_ulong)(interp_load_addr)); ! 656: NEW_AUX_ENT(AT_FLAGS, (target_ulong)0); ! 657: NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry); ! 658: NEW_AUX_ENT(AT_UID, (target_ulong) getuid()); ! 659: NEW_AUX_ENT(AT_EUID, (target_ulong) geteuid()); ! 660: NEW_AUX_ENT(AT_GID, (target_ulong) getgid()); ! 661: NEW_AUX_ENT(AT_EGID, (target_ulong) getegid()); ! 662: #ifdef ARCH_DLINFO ! 663: /* ! 664: * ARCH_DLINFO must come last so platform specific code can enforce ! 665: * special alignment requirements on the AUXV if necessary (eg. PPC). ! 666: */ ! 667: ARCH_DLINFO; ! 668: #endif ! 669: #undef NEW_AUX_ENT ! 670: ! 671: sp -= envc+1; ! 672: envp = sp; ! 673: sp -= argc+1; ! 674: argv = sp; ! 675: if (!ibcs) { ! 676: put_user((target_ulong)envp,--sp); ! 677: put_user((target_ulong)argv,--sp); ! 678: } ! 679: put_user(argc,--sp); ! 680: info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff); ! 681: while (argc-->0) { ! 682: put_user((target_ulong)p,argv++); ! 683: do { ! 684: get_user(v, p); ! 685: p++; ! 686: } while (v != 0); ! 687: } ! 688: put_user(0,argv); ! 689: info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff); ! 690: while (envc-->0) { ! 691: put_user((target_ulong)p,envp++); ! 692: do { ! 693: get_user(v, p); ! 694: p++; ! 695: } while (v != 0); ! 696: } ! 697: put_user(0,envp); ! 698: info->env_end = (unsigned int)((unsigned long)p & 0xffffffff); ! 699: return sp; ! 700: } ! 701: ! 702: ! 703: ! 704: static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, ! 705: int interpreter_fd, ! 706: unsigned long *interp_load_addr) ! 707: { ! 708: struct elf_phdr *elf_phdata = NULL; ! 709: struct elf_phdr *eppnt; ! 710: unsigned long load_addr = 0; ! 711: int load_addr_set = 0; ! 712: int retval; ! 713: unsigned long last_bss, elf_bss; ! 714: unsigned long error; ! 715: int i; ! 716: ! 717: elf_bss = 0; ! 718: last_bss = 0; ! 719: error = 0; ! 720: ! 721: #ifdef BSWAP_NEEDED ! 722: bswap_ehdr(interp_elf_ex); ! 723: #endif ! 724: /* First of all, some simple consistency checks */ ! 725: if ((interp_elf_ex->e_type != ET_EXEC && ! 726: interp_elf_ex->e_type != ET_DYN) || ! 727: !elf_check_arch(interp_elf_ex->e_machine)) { ! 728: return ~0UL; ! 729: } ! 730: ! 731: ! 732: /* Now read in all of the header information */ ! 733: ! 734: if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) ! 735: return ~0UL; ! 736: ! 737: elf_phdata = (struct elf_phdr *) ! 738: malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); ! 739: ! 740: if (!elf_phdata) ! 741: return ~0UL; ! 742: ! 743: /* ! 744: * If the size of this structure has changed, then punt, since ! 745: * we will be doing the wrong thing. ! 746: */ ! 747: if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { ! 748: free(elf_phdata); ! 749: return ~0UL; ! 750: } ! 751: ! 752: retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); ! 753: if(retval >= 0) { ! 754: retval = read(interpreter_fd, ! 755: (char *) elf_phdata, ! 756: sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); ! 757: } ! 758: if (retval < 0) { ! 759: perror("load_elf_interp"); ! 760: exit(-1); ! 761: free (elf_phdata); ! 762: return retval; ! 763: } ! 764: #ifdef BSWAP_NEEDED ! 765: eppnt = elf_phdata; ! 766: for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { ! 767: bswap_phdr(eppnt); ! 768: } ! 769: #endif ! 770: ! 771: if (interp_elf_ex->e_type == ET_DYN) { ! 772: /* in order to avoid harcoding the interpreter load ! 773: address in qemu, we allocate a big enough memory zone */ ! 774: error = target_mmap(0, INTERP_MAP_SIZE, ! 775: PROT_NONE, MAP_PRIVATE | MAP_ANON, ! 776: -1, 0); ! 777: if (error == -1) { ! 778: perror("mmap"); ! 779: exit(-1); ! 780: } ! 781: load_addr = error; ! 782: load_addr_set = 1; ! 783: } ! 784: ! 785: eppnt = elf_phdata; ! 786: for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) ! 787: if (eppnt->p_type == PT_LOAD) { ! 788: int elf_type = MAP_PRIVATE | MAP_DENYWRITE; ! 789: int elf_prot = 0; ! 790: unsigned long vaddr = 0; ! 791: unsigned long k; ! 792: ! 793: if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; ! 794: if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; ! 795: if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; ! 796: if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { ! 797: elf_type |= MAP_FIXED; ! 798: vaddr = eppnt->p_vaddr; ! 799: } ! 800: error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr), ! 801: eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr), ! 802: elf_prot, ! 803: elf_type, ! 804: interpreter_fd, ! 805: eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr)); ! 806: ! 807: if (error > -1024UL) { ! 808: /* Real error */ ! 809: close(interpreter_fd); ! 810: free(elf_phdata); ! 811: return ~0UL; ! 812: } ! 813: ! 814: if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { ! 815: load_addr = error; ! 816: load_addr_set = 1; ! 817: } ! 818: ! 819: /* ! 820: * Find the end of the file mapping for this phdr, and keep ! 821: * track of the largest address we see for this. ! 822: */ ! 823: k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; ! 824: if (k > elf_bss) elf_bss = k; ! 825: ! 826: /* ! 827: * Do the same thing for the memory mapping - between ! 828: * elf_bss and last_bss is the bss section. ! 829: */ ! 830: k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; ! 831: if (k > last_bss) last_bss = k; ! 832: } ! 833: ! 834: /* Now use mmap to map the library into memory. */ ! 835: ! 836: close(interpreter_fd); ! 837: ! 838: /* ! 839: * Now fill out the bss section. First pad the last page up ! 840: * to the page boundary, and then perform a mmap to make sure ! 841: * that there are zeromapped pages up to and including the last ! 842: * bss page. ! 843: */ ! 844: padzero(elf_bss); ! 845: elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */ ! 846: ! 847: /* Map the last of the bss segment */ ! 848: if (last_bss > elf_bss) { ! 849: target_mmap(elf_bss, last_bss-elf_bss, ! 850: PROT_READ|PROT_WRITE|PROT_EXEC, ! 851: MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ! 852: } ! 853: free(elf_phdata); ! 854: ! 855: *interp_load_addr = load_addr; ! 856: return ((unsigned long) interp_elf_ex->e_entry) + load_addr; ! 857: } ! 858: ! 859: /* Best attempt to load symbols from this ELF object. */ ! 860: static void load_symbols(struct elfhdr *hdr, int fd) ! 861: { ! 862: unsigned int i; ! 863: struct elf_shdr sechdr, symtab, strtab; ! 864: char *strings; ! 865: struct syminfo *s; ! 866: ! 867: lseek(fd, hdr->e_shoff, SEEK_SET); ! 868: for (i = 0; i < hdr->e_shnum; i++) { ! 869: if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) ! 870: return; ! 871: #ifdef BSWAP_NEEDED ! 872: bswap_shdr(&sechdr); ! 873: #endif ! 874: if (sechdr.sh_type == SHT_SYMTAB) { ! 875: symtab = sechdr; ! 876: lseek(fd, hdr->e_shoff ! 877: + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); ! 878: if (read(fd, &strtab, sizeof(strtab)) ! 879: != sizeof(strtab)) ! 880: return; ! 881: #ifdef BSWAP_NEEDED ! 882: bswap_shdr(&strtab); ! 883: #endif ! 884: goto found; ! 885: } ! 886: } ! 887: return; /* Shouldn't happen... */ ! 888: ! 889: found: ! 890: /* Now know where the strtab and symtab are. Snarf them. */ ! 891: s = malloc(sizeof(*s)); ! 892: s->disas_symtab = malloc(symtab.sh_size); ! 893: s->disas_strtab = strings = malloc(strtab.sh_size); ! 894: if (!s->disas_symtab || !s->disas_strtab) ! 895: return; ! 896: ! 897: lseek(fd, symtab.sh_offset, SEEK_SET); ! 898: if (read(fd, s->disas_symtab, symtab.sh_size) != symtab.sh_size) ! 899: return; ! 900: ! 901: #ifdef BSWAP_NEEDED ! 902: for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++) ! 903: bswap_sym(s->disas_symtab + sizeof(struct elf_sym)*i); ! 904: #endif ! 905: ! 906: lseek(fd, strtab.sh_offset, SEEK_SET); ! 907: if (read(fd, strings, strtab.sh_size) != strtab.sh_size) ! 908: return; ! 909: s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym); ! 910: s->next = syminfos; ! 911: syminfos = s; ! 912: } ! 913: ! 914: static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, ! 915: struct image_info * info) ! 916: { ! 917: struct elfhdr elf_ex; ! 918: struct elfhdr interp_elf_ex; ! 919: struct exec interp_ex; ! 920: int interpreter_fd = -1; /* avoid warning */ ! 921: unsigned long load_addr, load_bias; ! 922: int load_addr_set = 0; ! 923: unsigned int interpreter_type = INTERPRETER_NONE; ! 924: unsigned char ibcs2_interpreter; ! 925: int i; ! 926: unsigned long mapped_addr; ! 927: struct elf_phdr * elf_ppnt; ! 928: struct elf_phdr *elf_phdata; ! 929: unsigned long elf_bss, k, elf_brk; ! 930: int retval; ! 931: char * elf_interpreter; ! 932: unsigned long elf_entry, interp_load_addr = 0; ! 933: int status; ! 934: unsigned long start_code, end_code, end_data; ! 935: unsigned long elf_stack; ! 936: char passed_fileno[6]; ! 937: ! 938: ibcs2_interpreter = 0; ! 939: status = 0; ! 940: load_addr = 0; ! 941: load_bias = 0; ! 942: elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ ! 943: #ifdef BSWAP_NEEDED ! 944: bswap_ehdr(&elf_ex); ! 945: #endif ! 946: ! 947: if (elf_ex.e_ident[0] != 0x7f || ! 948: strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) { ! 949: return -ENOEXEC; ! 950: } ! 951: ! 952: /* First of all, some simple consistency checks */ ! 953: if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || ! 954: (! elf_check_arch(elf_ex.e_machine))) { ! 955: return -ENOEXEC; ! 956: } ! 957: ! 958: /* Now read in all of the header information */ ! 959: elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); ! 960: if (elf_phdata == NULL) { ! 961: return -ENOMEM; ! 962: } ! 963: ! 964: retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); ! 965: if(retval > 0) { ! 966: retval = read(bprm->fd, (char *) elf_phdata, ! 967: elf_ex.e_phentsize * elf_ex.e_phnum); ! 968: } ! 969: ! 970: if (retval < 0) { ! 971: perror("load_elf_binary"); ! 972: exit(-1); ! 973: free (elf_phdata); ! 974: return -errno; ! 975: } ! 976: ! 977: #ifdef BSWAP_NEEDED ! 978: elf_ppnt = elf_phdata; ! 979: for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { ! 980: bswap_phdr(elf_ppnt); ! 981: } ! 982: #endif ! 983: elf_ppnt = elf_phdata; ! 984: ! 985: elf_bss = 0; ! 986: elf_brk = 0; ! 987: ! 988: ! 989: elf_stack = ~0UL; ! 990: elf_interpreter = NULL; ! 991: start_code = ~0UL; ! 992: end_code = 0; ! 993: end_data = 0; ! 994: ! 995: for(i=0;i < elf_ex.e_phnum; i++) { ! 996: if (elf_ppnt->p_type == PT_INTERP) { ! 997: if ( elf_interpreter != NULL ) ! 998: { ! 999: free (elf_phdata); ! 1000: free(elf_interpreter); ! 1001: close(bprm->fd); ! 1002: return -EINVAL; ! 1003: } ! 1004: ! 1005: /* This is the program interpreter used for ! 1006: * shared libraries - for now assume that this ! 1007: * is an a.out format binary ! 1008: */ ! 1009: ! 1010: elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); ! 1011: ! 1012: if (elf_interpreter == NULL) { ! 1013: free (elf_phdata); ! 1014: close(bprm->fd); ! 1015: return -ENOMEM; ! 1016: } ! 1017: ! 1018: retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); ! 1019: if(retval >= 0) { ! 1020: retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); ! 1021: } ! 1022: if(retval < 0) { ! 1023: perror("load_elf_binary2"); ! 1024: exit(-1); ! 1025: } ! 1026: ! 1027: /* If the program interpreter is one of these two, ! 1028: then assume an iBCS2 image. Otherwise assume ! 1029: a native linux image. */ ! 1030: ! 1031: /* JRP - Need to add X86 lib dir stuff here... */ ! 1032: ! 1033: if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || ! 1034: strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { ! 1035: ibcs2_interpreter = 1; ! 1036: } ! 1037: ! 1038: #if 0 ! 1039: printf("Using ELF interpreter %s\n", elf_interpreter); ! 1040: #endif ! 1041: if (retval >= 0) { ! 1042: retval = open(path(elf_interpreter), O_RDONLY); ! 1043: if(retval >= 0) { ! 1044: interpreter_fd = retval; ! 1045: } ! 1046: else { ! 1047: perror(elf_interpreter); ! 1048: exit(-1); ! 1049: /* retval = -errno; */ ! 1050: } ! 1051: } ! 1052: ! 1053: if (retval >= 0) { ! 1054: retval = lseek(interpreter_fd, 0, SEEK_SET); ! 1055: if(retval >= 0) { ! 1056: retval = read(interpreter_fd,bprm->buf,128); ! 1057: } ! 1058: } ! 1059: if (retval >= 0) { ! 1060: interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ ! 1061: interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */ ! 1062: } ! 1063: if (retval < 0) { ! 1064: perror("load_elf_binary3"); ! 1065: exit(-1); ! 1066: free (elf_phdata); ! 1067: free(elf_interpreter); ! 1068: close(bprm->fd); ! 1069: return retval; ! 1070: } ! 1071: } ! 1072: elf_ppnt++; ! 1073: } ! 1074: ! 1075: /* Some simple consistency checks for the interpreter */ ! 1076: if (elf_interpreter){ ! 1077: interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; ! 1078: ! 1079: /* Now figure out which format our binary is */ ! 1080: if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && ! 1081: (N_MAGIC(interp_ex) != QMAGIC)) { ! 1082: interpreter_type = INTERPRETER_ELF; ! 1083: } ! 1084: ! 1085: if (interp_elf_ex.e_ident[0] != 0x7f || ! 1086: strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) { ! 1087: interpreter_type &= ~INTERPRETER_ELF; ! 1088: } ! 1089: ! 1090: if (!interpreter_type) { ! 1091: free(elf_interpreter); ! 1092: free(elf_phdata); ! 1093: close(bprm->fd); ! 1094: return -ELIBBAD; ! 1095: } ! 1096: } ! 1097: ! 1098: /* OK, we are done with that, now set up the arg stuff, ! 1099: and then start this sucker up */ ! 1100: ! 1101: if (!bprm->sh_bang) { ! 1102: char * passed_p; ! 1103: ! 1104: if (interpreter_type == INTERPRETER_AOUT) { ! 1105: snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); ! 1106: passed_p = passed_fileno; ! 1107: ! 1108: if (elf_interpreter) { ! 1109: bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p); ! 1110: bprm->argc++; ! 1111: } ! 1112: } ! 1113: if (!bprm->p) { ! 1114: if (elf_interpreter) { ! 1115: free(elf_interpreter); ! 1116: } ! 1117: free (elf_phdata); ! 1118: close(bprm->fd); ! 1119: return -E2BIG; ! 1120: } ! 1121: } ! 1122: ! 1123: /* OK, This is the point of no return */ ! 1124: info->end_data = 0; ! 1125: info->end_code = 0; ! 1126: info->start_mmap = (unsigned long)ELF_START_MMAP; ! 1127: info->mmap = 0; ! 1128: elf_entry = (unsigned long) elf_ex.e_entry; ! 1129: ! 1130: /* Do this so that we can load the interpreter, if need be. We will ! 1131: change some of these later */ ! 1132: info->rss = 0; ! 1133: bprm->p = setup_arg_pages(bprm->p, bprm, info); ! 1134: info->start_stack = bprm->p; ! 1135: ! 1136: /* Now we do a little grungy work by mmaping the ELF image into ! 1137: * the correct location in memory. At this point, we assume that ! 1138: * the image should be loaded at fixed address, not at a variable ! 1139: * address. ! 1140: */ ! 1141: ! 1142: for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { ! 1143: int elf_prot = 0; ! 1144: int elf_flags = 0; ! 1145: unsigned long error; ! 1146: ! 1147: if (elf_ppnt->p_type != PT_LOAD) ! 1148: continue; ! 1149: ! 1150: if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; ! 1151: if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; ! 1152: if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; ! 1153: elf_flags = MAP_PRIVATE | MAP_DENYWRITE; ! 1154: if (elf_ex.e_type == ET_EXEC || load_addr_set) { ! 1155: elf_flags |= MAP_FIXED; ! 1156: } else if (elf_ex.e_type == ET_DYN) { ! 1157: /* Try and get dynamic programs out of the way of the default mmap ! 1158: base, as well as whatever program they might try to exec. This ! 1159: is because the brk will follow the loader, and is not movable. */ ! 1160: /* NOTE: for qemu, we do a big mmap to get enough space ! 1161: without harcoding any address */ ! 1162: error = target_mmap(0, ET_DYN_MAP_SIZE, ! 1163: PROT_NONE, MAP_PRIVATE | MAP_ANON, ! 1164: -1, 0); ! 1165: if (error == -1) { ! 1166: perror("mmap"); ! 1167: exit(-1); ! 1168: } ! 1169: load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); ! 1170: } ! 1171: ! 1172: error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), ! 1173: (elf_ppnt->p_filesz + ! 1174: TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), ! 1175: elf_prot, ! 1176: (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), ! 1177: bprm->fd, ! 1178: (elf_ppnt->p_offset - ! 1179: TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); ! 1180: if (error == -1) { ! 1181: perror("mmap"); ! 1182: exit(-1); ! 1183: } ! 1184: ! 1185: #ifdef LOW_ELF_STACK ! 1186: if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) ! 1187: elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); ! 1188: #endif ! 1189: ! 1190: if (!load_addr_set) { ! 1191: load_addr_set = 1; ! 1192: load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; ! 1193: if (elf_ex.e_type == ET_DYN) { ! 1194: load_bias += error - ! 1195: TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); ! 1196: load_addr += load_bias; ! 1197: } ! 1198: } ! 1199: k = elf_ppnt->p_vaddr; ! 1200: if (k < start_code) ! 1201: start_code = k; ! 1202: k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; ! 1203: if (k > elf_bss) ! 1204: elf_bss = k; ! 1205: if ((elf_ppnt->p_flags & PF_X) && end_code < k) ! 1206: end_code = k; ! 1207: if (end_data < k) ! 1208: end_data = k; ! 1209: k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; ! 1210: if (k > elf_brk) elf_brk = k; ! 1211: } ! 1212: ! 1213: elf_entry += load_bias; ! 1214: elf_bss += load_bias; ! 1215: elf_brk += load_bias; ! 1216: start_code += load_bias; ! 1217: end_code += load_bias; ! 1218: // start_data += load_bias; ! 1219: end_data += load_bias; ! 1220: ! 1221: if (elf_interpreter) { ! 1222: if (interpreter_type & 1) { ! 1223: elf_entry = load_aout_interp(&interp_ex, interpreter_fd); ! 1224: } ! 1225: else if (interpreter_type & 2) { ! 1226: elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, ! 1227: &interp_load_addr); ! 1228: } ! 1229: ! 1230: close(interpreter_fd); ! 1231: free(elf_interpreter); ! 1232: ! 1233: if (elf_entry == ~0UL) { ! 1234: printf("Unable to load interpreter\n"); ! 1235: free(elf_phdata); ! 1236: exit(-1); ! 1237: return 0; ! 1238: } ! 1239: } ! 1240: ! 1241: free(elf_phdata); ! 1242: ! 1243: if (loglevel) ! 1244: load_symbols(&elf_ex, bprm->fd); ! 1245: ! 1246: if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); ! 1247: info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); ! 1248: ! 1249: #ifdef LOW_ELF_STACK ! 1250: info->start_stack = bprm->p = elf_stack - 4; ! 1251: #endif ! 1252: bprm->p = (unsigned long) ! 1253: create_elf_tables((char *)bprm->p, ! 1254: bprm->argc, ! 1255: bprm->envc, ! 1256: &elf_ex, ! 1257: load_addr, load_bias, ! 1258: interp_load_addr, ! 1259: (interpreter_type == INTERPRETER_AOUT ? 0 : 1), ! 1260: info); ! 1261: if (interpreter_type == INTERPRETER_AOUT) ! 1262: info->arg_start += strlen(passed_fileno) + 1; ! 1263: info->start_brk = info->brk = elf_brk; ! 1264: info->end_code = end_code; ! 1265: info->start_code = start_code; ! 1266: info->end_data = end_data; ! 1267: info->start_stack = bprm->p; ! 1268: ! 1269: /* Calling set_brk effectively mmaps the pages that we need for the bss and break ! 1270: sections */ ! 1271: set_brk(elf_bss, elf_brk); ! 1272: ! 1273: padzero(elf_bss); ! 1274: ! 1275: #if 0 ! 1276: printf("(start_brk) %x\n" , info->start_brk); ! 1277: printf("(end_code) %x\n" , info->end_code); ! 1278: printf("(start_code) %x\n" , info->start_code); ! 1279: printf("(end_data) %x\n" , info->end_data); ! 1280: printf("(start_stack) %x\n" , info->start_stack); ! 1281: printf("(brk) %x\n" , info->brk); ! 1282: #endif ! 1283: ! 1284: if ( info->personality == PER_SVR4 ) ! 1285: { ! 1286: /* Why this, you ask??? Well SVr4 maps page 0 as read-only, ! 1287: and some applications "depend" upon this behavior. ! 1288: Since we do not have the power to recompile these, we ! 1289: emulate the SVr4 behavior. Sigh. */ ! 1290: mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, ! 1291: MAP_FIXED | MAP_PRIVATE, -1, 0); ! 1292: } ! 1293: ! 1294: #ifdef ELF_PLAT_INIT ! 1295: /* ! 1296: * The ABI may specify that certain registers be set up in special ! 1297: * ways (on i386 %edx is the address of a DT_FINI function, for ! 1298: * example. This macro performs whatever initialization to ! 1299: * the regs structure is required. ! 1300: */ ! 1301: ELF_PLAT_INIT(regs); ! 1302: #endif ! 1303: ! 1304: ! 1305: info->entry = elf_entry; ! 1306: ! 1307: return 0; ! 1308: } ! 1309: ! 1310: ! 1311: ! 1312: int elf_exec(const char * filename, char ** argv, char ** envp, ! 1313: struct target_pt_regs * regs, struct image_info *infop) ! 1314: { ! 1315: struct linux_binprm bprm; ! 1316: int retval; ! 1317: int i; ! 1318: ! 1319: bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); ! 1320: for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ ! 1321: bprm.page[i] = 0; ! 1322: retval = open(filename, O_RDONLY); ! 1323: if (retval < 0) ! 1324: return retval; ! 1325: bprm.fd = retval; ! 1326: bprm.filename = (char *)filename; ! 1327: bprm.sh_bang = 0; ! 1328: bprm.loader = 0; ! 1329: bprm.exec = 0; ! 1330: bprm.dont_iput = 0; ! 1331: bprm.argc = count(argv); ! 1332: bprm.envc = count(envp); ! 1333: ! 1334: retval = prepare_binprm(&bprm); ! 1335: ! 1336: if(retval>=0) { ! 1337: bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p); ! 1338: bprm.exec = bprm.p; ! 1339: bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p); ! 1340: bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p); ! 1341: if (!bprm.p) { ! 1342: retval = -E2BIG; ! 1343: } ! 1344: } ! 1345: ! 1346: if(retval>=0) { ! 1347: retval = load_elf_binary(&bprm,regs,infop); ! 1348: } ! 1349: if(retval>=0) { ! 1350: /* success. Initialize important registers */ ! 1351: init_thread(regs, infop); ! 1352: return retval; ! 1353: } ! 1354: ! 1355: /* Something went wrong, return the inode and free the argument pages*/ ! 1356: for (i=0 ; i<MAX_ARG_PAGES ; i++) { ! 1357: free_page((void *)bprm.page[i]); ! 1358: } ! 1359: return(retval); ! 1360: } ! 1361: ! 1362: ! 1363: static int load_aout_interp(void * exptr, int interp_fd) ! 1364: { ! 1365: printf("a.out interpreter not yet supported\n"); ! 1366: return(0); ! 1367: } ! 1368:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.