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