|
|
1.1 ! root 1: /****************************************************************************/ ! 2: /* ! 3: * QEMU bFLT binary loader. Based on linux/fs/binfmt_flat.c ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify ! 6: * it under the terms of the GNU General Public License as published by ! 7: * the Free Software Foundation; either version 2 of the License, or ! 8: * (at your option) any later version. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, ! 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: * GNU General Public License for more details. ! 14: * ! 15: * You should have received a copy of the GNU General Public License ! 16: * along with this program; if not, write to the Free Software ! 17: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 18: * ! 19: * Copyright (C) 2006 CodeSourcery. ! 20: * Copyright (C) 2000-2003 David McCullough <[email protected]> ! 21: * Copyright (C) 2002 Greg Ungerer <[email protected]> ! 22: * Copyright (C) 2002 SnapGear, by Paul Dale <[email protected]> ! 23: * Copyright (C) 2000, 2001 Lineo, by David McCullough <[email protected]> ! 24: * based heavily on: ! 25: * ! 26: * linux/fs/binfmt_aout.c: ! 27: * Copyright (C) 1991, 1992, 1996 Linus Torvalds ! 28: * linux/fs/binfmt_flat.c for 2.0 kernel ! 29: * Copyright (C) 1998 Kenneth Albanowski <[email protected]> ! 30: * JAN/99 -- coded full program relocation ([email protected]) ! 31: */ ! 32: ! 33: /* ??? ZFLAT and shared library support is currently disabled. */ ! 34: ! 35: /****************************************************************************/ ! 36: ! 37: #include <stdio.h> ! 38: #include <stdlib.h> ! 39: #include <errno.h> ! 40: #include <sys/mman.h> ! 41: #include <unistd.h> ! 42: ! 43: #include "qemu.h" ! 44: #include "flat.h" ! 45: ! 46: //#define DEBUG ! 47: ! 48: #ifdef DEBUG ! 49: #define DBG_FLT(a...) printf(a) ! 50: #else ! 51: #define DBG_FLT(a...) ! 52: #endif ! 53: ! 54: #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) ! 55: #define flat_old_ram_flag(flag) (flag) ! 56: #ifdef TARGET_WORDS_BIGENDIAN ! 57: #define flat_get_relocate_addr(relval) (relval) ! 58: #else ! 59: #define flat_get_relocate_addr(relval) bswap32(relval) ! 60: #endif ! 61: ! 62: #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ ! 63: #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ ! 64: ! 65: struct lib_info { ! 66: target_ulong start_code; /* Start of text segment */ ! 67: target_ulong start_data; /* Start of data segment */ ! 68: target_ulong end_data; /* Start of bss section */ ! 69: target_ulong start_brk; /* End of data segment */ ! 70: target_ulong text_len; /* Length of text segment */ ! 71: target_ulong entry; /* Start address for this module */ ! 72: target_ulong build_date; /* When this one was compiled */ ! 73: short loaded; /* Has this library been loaded? */ ! 74: }; ! 75: ! 76: #ifdef CONFIG_BINFMT_SHARED_FLAT ! 77: static int load_flat_shared_library(int id, struct lib_info *p); ! 78: #endif ! 79: ! 80: struct linux_binprm; ! 81: ! 82: #define ntohl(x) be32_to_cpu(x) ! 83: ! 84: /****************************************************************************/ ! 85: /* ! 86: * create_flat_tables() parses the env- and arg-strings in new user ! 87: * memory and creates the pointer tables from them, and puts their ! 88: * addresses on the "stack", returning the new stack pointer value. ! 89: */ ! 90: ! 91: /* Push a block of strings onto the guest stack. */ ! 92: static target_ulong copy_strings(target_ulong p, int n, char **s) ! 93: { ! 94: int len; ! 95: ! 96: while (n-- > 0) { ! 97: len = strlen(s[n]) + 1; ! 98: p -= len; ! 99: memcpy_to_target(p, s[n], len); ! 100: } ! 101: ! 102: return p; ! 103: } ! 104: ! 105: int target_pread(int fd, target_ulong ptr, target_ulong len, ! 106: target_ulong offset) ! 107: { ! 108: void *buf; ! 109: int ret; ! 110: ! 111: buf = lock_user(ptr, len, 0); ! 112: ret = pread(fd, buf, len, offset); ! 113: unlock_user(buf, ptr, len); ! 114: return ret; ! 115: } ! 116: /****************************************************************************/ ! 117: ! 118: #ifdef CONFIG_BINFMT_ZFLAT ! 119: ! 120: #include <linux/zlib.h> ! 121: ! 122: #define LBUFSIZE 4000 ! 123: ! 124: /* gzip flag byte */ ! 125: #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ ! 126: #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ ! 127: #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ ! 128: #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ ! 129: #define COMMENT 0x10 /* bit 4 set: file comment present */ ! 130: #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ ! 131: #define RESERVED 0xC0 /* bit 6,7: reserved */ ! 132: ! 133: static int decompress_exec( ! 134: struct linux_binprm *bprm, ! 135: unsigned long offset, ! 136: char *dst, ! 137: long len, ! 138: int fd) ! 139: { ! 140: unsigned char *buf; ! 141: z_stream strm; ! 142: loff_t fpos; ! 143: int ret, retval; ! 144: ! 145: DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len); ! 146: ! 147: memset(&strm, 0, sizeof(strm)); ! 148: strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); ! 149: if (strm.workspace == NULL) { ! 150: DBG_FLT("binfmt_flat: no memory for decompress workspace\n"); ! 151: return -ENOMEM; ! 152: } ! 153: buf = kmalloc(LBUFSIZE, GFP_KERNEL); ! 154: if (buf == NULL) { ! 155: DBG_FLT("binfmt_flat: no memory for read buffer\n"); ! 156: retval = -ENOMEM; ! 157: goto out_free; ! 158: } ! 159: ! 160: /* Read in first chunk of data and parse gzip header. */ ! 161: fpos = offset; ! 162: ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); ! 163: ! 164: strm.next_in = buf; ! 165: strm.avail_in = ret; ! 166: strm.total_in = 0; ! 167: ! 168: retval = -ENOEXEC; ! 169: ! 170: /* Check minimum size -- gzip header */ ! 171: if (ret < 10) { ! 172: DBG_FLT("binfmt_flat: file too small?\n"); ! 173: goto out_free_buf; ! 174: } ! 175: ! 176: /* Check gzip magic number */ ! 177: if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) { ! 178: DBG_FLT("binfmt_flat: unknown compression magic?\n"); ! 179: goto out_free_buf; ! 180: } ! 181: ! 182: /* Check gzip method */ ! 183: if (buf[2] != 8) { ! 184: DBG_FLT("binfmt_flat: unknown compression method?\n"); ! 185: goto out_free_buf; ! 186: } ! 187: /* Check gzip flags */ ! 188: if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) || ! 189: (buf[3] & RESERVED)) { ! 190: DBG_FLT("binfmt_flat: unknown flags?\n"); ! 191: goto out_free_buf; ! 192: } ! 193: ! 194: ret = 10; ! 195: if (buf[3] & EXTRA_FIELD) { ! 196: ret += 2 + buf[10] + (buf[11] << 8); ! 197: if (unlikely(LBUFSIZE == ret)) { ! 198: DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n"); ! 199: goto out_free_buf; ! 200: } ! 201: } ! 202: if (buf[3] & ORIG_NAME) { ! 203: for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) ! 204: ; ! 205: if (unlikely(LBUFSIZE == ret)) { ! 206: DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n"); ! 207: goto out_free_buf; ! 208: } ! 209: } ! 210: if (buf[3] & COMMENT) { ! 211: for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) ! 212: ; ! 213: if (unlikely(LBUFSIZE == ret)) { ! 214: DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n"); ! 215: goto out_free_buf; ! 216: } ! 217: } ! 218: ! 219: strm.next_in += ret; ! 220: strm.avail_in -= ret; ! 221: ! 222: strm.next_out = dst; ! 223: strm.avail_out = len; ! 224: strm.total_out = 0; ! 225: ! 226: if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) { ! 227: DBG_FLT("binfmt_flat: zlib init failed?\n"); ! 228: goto out_free_buf; ! 229: } ! 230: ! 231: while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { ! 232: ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); ! 233: if (ret <= 0) ! 234: break; ! 235: if (ret >= (unsigned long) -4096) ! 236: break; ! 237: len -= ret; ! 238: ! 239: strm.next_in = buf; ! 240: strm.avail_in = ret; ! 241: strm.total_in = 0; ! 242: } ! 243: ! 244: if (ret < 0) { ! 245: DBG_FLT("binfmt_flat: decompression failed (%d), %s\n", ! 246: ret, strm.msg); ! 247: goto out_zlib; ! 248: } ! 249: ! 250: retval = 0; ! 251: out_zlib: ! 252: zlib_inflateEnd(&strm); ! 253: out_free_buf: ! 254: kfree(buf); ! 255: out_free: ! 256: kfree(strm.workspace); ! 257: out: ! 258: return retval; ! 259: } ! 260: ! 261: #endif /* CONFIG_BINFMT_ZFLAT */ ! 262: ! 263: /****************************************************************************/ ! 264: ! 265: static target_ulong ! 266: calc_reloc(target_ulong r, struct lib_info *p, int curid, int internalp) ! 267: { ! 268: target_ulong addr; ! 269: int id; ! 270: target_ulong start_brk; ! 271: target_ulong start_data; ! 272: target_ulong text_len; ! 273: target_ulong start_code; ! 274: ! 275: #ifdef CONFIG_BINFMT_SHARED_FLAT ! 276: #error needs checking ! 277: if (r == 0) ! 278: id = curid; /* Relocs of 0 are always self referring */ ! 279: else { ! 280: id = (r >> 24) & 0xff; /* Find ID for this reloc */ ! 281: r &= 0x00ffffff; /* Trim ID off here */ ! 282: } ! 283: if (id >= MAX_SHARED_LIBS) { ! 284: fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n", ! 285: (unsigned) r, id); ! 286: goto failed; ! 287: } ! 288: if (curid != id) { ! 289: if (internalp) { ! 290: fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not " ! 291: "in same module (%d != %d)\n", ! 292: (unsigned) r, curid, id); ! 293: goto failed; ! 294: } else if ( ! p[id].loaded && ! 295: load_flat_shared_library(id, p) > (unsigned long) -4096) { ! 296: fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id); ! 297: goto failed; ! 298: } ! 299: /* Check versioning information (i.e. time stamps) */ ! 300: if (p[id].build_date && p[curid].build_date ! 301: && p[curid].build_date < p[id].build_date) { ! 302: fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n", ! 303: id, curid); ! 304: goto failed; ! 305: } ! 306: } ! 307: #else ! 308: id = 0; ! 309: #endif ! 310: ! 311: start_brk = p[id].start_brk; ! 312: start_data = p[id].start_data; ! 313: start_code = p[id].start_code; ! 314: text_len = p[id].text_len; ! 315: ! 316: if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { ! 317: fprintf(stderr, "BINFMT_FLAT: reloc outside program 0x%x " ! 318: "(0 - 0x%x/0x%x)\n", ! 319: (int) r,(int)(start_brk-start_code),(int)text_len); ! 320: goto failed; ! 321: } ! 322: ! 323: if (r < text_len) /* In text segment */ ! 324: addr = r + start_code; ! 325: else /* In data segment */ ! 326: addr = r - text_len + start_data; ! 327: ! 328: /* Range checked already above so doing the range tests is redundant...*/ ! 329: return(addr); ! 330: ! 331: failed: ! 332: abort(); ! 333: return RELOC_FAILED; ! 334: } ! 335: ! 336: /****************************************************************************/ ! 337: ! 338: /* ??? This does not handle endianness correctly. */ ! 339: void old_reloc(struct lib_info *libinfo, uint32_t rl) ! 340: { ! 341: #ifdef DEBUG ! 342: char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; ! 343: #endif ! 344: uint32_t *ptr; ! 345: uint32_t offset; ! 346: int reloc_type; ! 347: ! 348: offset = rl & 0x3fffffff; ! 349: reloc_type = rl >> 30; ! 350: /* ??? How to handle this? */ ! 351: #if defined(CONFIG_COLDFIRE) ! 352: ptr = (uint32_t *) (libinfo->start_code + offset); ! 353: #else ! 354: ptr = (uint32_t *) (libinfo->start_data + offset); ! 355: #endif ! 356: ! 357: #ifdef DEBUG ! 358: fprintf(stderr, "Relocation of variable at DATASEG+%x " ! 359: "(address %p, currently %x) into segment %s\n", ! 360: offset, ptr, (int)*ptr, segment[reloc_type]); ! 361: #endif ! 362: ! 363: switch (reloc_type) { ! 364: case OLD_FLAT_RELOC_TYPE_TEXT: ! 365: *ptr += libinfo->start_code; ! 366: break; ! 367: case OLD_FLAT_RELOC_TYPE_DATA: ! 368: *ptr += libinfo->start_data; ! 369: break; ! 370: case OLD_FLAT_RELOC_TYPE_BSS: ! 371: *ptr += libinfo->end_data; ! 372: break; ! 373: default: ! 374: fprintf(stderr, "BINFMT_FLAT: Unknown relocation type=%x\n", ! 375: reloc_type); ! 376: break; ! 377: } ! 378: DBG_FLT("Relocation became %x\n", (int)*ptr); ! 379: } ! 380: ! 381: /****************************************************************************/ ! 382: ! 383: static int load_flat_file(struct linux_binprm * bprm, ! 384: struct lib_info *libinfo, int id, target_ulong *extra_stack) ! 385: { ! 386: struct flat_hdr * hdr; ! 387: target_ulong textpos = 0, datapos = 0, result; ! 388: target_ulong realdatastart = 0; ! 389: target_ulong text_len, data_len, bss_len, stack_len, flags; ! 390: target_ulong memp = 0; /* for finding the brk area */ ! 391: target_ulong extra; ! 392: target_ulong reloc = 0, rp; ! 393: int i, rev, relocs = 0; ! 394: target_ulong fpos; ! 395: target_ulong start_code, end_code; ! 396: ! 397: hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ ! 398: ! 399: text_len = ntohl(hdr->data_start); ! 400: data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start); ! 401: bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end); ! 402: stack_len = ntohl(hdr->stack_size); ! 403: if (extra_stack) { ! 404: stack_len += *extra_stack; ! 405: *extra_stack = stack_len; ! 406: } ! 407: relocs = ntohl(hdr->reloc_count); ! 408: flags = ntohl(hdr->flags); ! 409: rev = ntohl(hdr->rev); ! 410: ! 411: DBG_FLT("BINFMT_FLAT: Loading file: %s\n", bprm->filename); ! 412: ! 413: if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { ! 414: fprintf(stderr, "BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n", ! 415: rev, (int) FLAT_VERSION); ! 416: return -ENOEXEC; ! 417: } ! 418: ! 419: /* Don't allow old format executables to use shared libraries */ ! 420: if (rev == OLD_FLAT_VERSION && id != 0) { ! 421: fprintf(stderr, "BINFMT_FLAT: shared libraries are not available\n"); ! 422: return -ENOEXEC; ! 423: } ! 424: ! 425: /* ! 426: * fix up the flags for the older format, there were all kinds ! 427: * of endian hacks, this only works for the simple cases ! 428: */ ! 429: if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) ! 430: flags = FLAT_FLAG_RAM; ! 431: ! 432: #ifndef CONFIG_BINFMT_ZFLAT ! 433: if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { ! 434: fprintf(stderr, "Support for ZFLAT executables is not enabled\n"); ! 435: return -ENOEXEC; ! 436: } ! 437: #endif ! 438: ! 439: /* ! 440: * calculate the extra space we need to map in ! 441: */ ! 442: extra = relocs * sizeof(target_ulong); ! 443: if (extra < bss_len + stack_len) ! 444: extra = bss_len + stack_len; ! 445: ! 446: /* ! 447: * there are a couple of cases here, the separate code/data ! 448: * case, and then the fully copied to RAM case which lumps ! 449: * it all together. ! 450: */ ! 451: if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) { ! 452: /* ! 453: * this should give us a ROM ptr, but if it doesn't we don't ! 454: * really care ! 455: */ ! 456: DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); ! 457: ! 458: textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC, ! 459: MAP_PRIVATE, bprm->fd, 0); ! 460: if (textpos == -1) { ! 461: fprintf(stderr, "Unable to mmap process text\n"); ! 462: return -1; ! 463: } ! 464: ! 465: realdatastart = target_mmap(0, data_len + extra + ! 466: MAX_SHARED_LIBS * sizeof(target_ulong), ! 467: PROT_READ|PROT_WRITE|PROT_EXEC, ! 468: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 469: ! 470: if (realdatastart == -1) { ! 471: fprintf(stderr, "Unable to allocate RAM for process data\n"); ! 472: return realdatastart; ! 473: } ! 474: datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong); ! 475: ! 476: DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", ! 477: (int)(data_len + bss_len + stack_len), (int)datapos); ! 478: ! 479: fpos = ntohl(hdr->data_start); ! 480: #ifdef CONFIG_BINFMT_ZFLAT ! 481: if (flags & FLAT_FLAG_GZDATA) { ! 482: result = decompress_exec(bprm, fpos, (char *) datapos, ! 483: data_len + (relocs * sizeof(target_ulong))) ! 484: } else ! 485: #endif ! 486: { ! 487: result = target_pread(bprm->fd, datapos, ! 488: data_len + (relocs * sizeof(target_ulong)), ! 489: fpos); ! 490: } ! 491: if (result < 0) { ! 492: fprintf(stderr, "Unable to read data+bss\n"); ! 493: return result; ! 494: } ! 495: ! 496: reloc = datapos + (ntohl(hdr->reloc_start) - text_len); ! 497: memp = realdatastart; ! 498: ! 499: } else { ! 500: ! 501: textpos = target_mmap(0, text_len + data_len + extra + ! 502: MAX_SHARED_LIBS * sizeof(target_ulong), ! 503: PROT_READ | PROT_EXEC | PROT_WRITE, ! 504: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 505: if (textpos == -1 ) { ! 506: fprintf(stderr, "Unable to allocate RAM for process text/data\n"); ! 507: return -1; ! 508: } ! 509: ! 510: realdatastart = textpos + ntohl(hdr->data_start); ! 511: datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong); ! 512: reloc = (textpos + ntohl(hdr->reloc_start) + ! 513: MAX_SHARED_LIBS * sizeof(target_ulong)); ! 514: memp = textpos; ! 515: ! 516: #ifdef CONFIG_BINFMT_ZFLAT ! 517: #error code needs checking ! 518: /* ! 519: * load it all in and treat it like a RAM load from now on ! 520: */ ! 521: if (flags & FLAT_FLAG_GZIP) { ! 522: result = decompress_exec(bprm, sizeof (struct flat_hdr), ! 523: (((char *) textpos) + sizeof (struct flat_hdr)), ! 524: (text_len + data_len + (relocs * sizeof(unsigned long)) ! 525: - sizeof (struct flat_hdr)), ! 526: 0); ! 527: memmove((void *) datapos, (void *) realdatastart, ! 528: data_len + (relocs * sizeof(unsigned long))); ! 529: } else if (flags & FLAT_FLAG_GZDATA) { ! 530: fpos = 0; ! 531: result = bprm->file->f_op->read(bprm->file, ! 532: (char *) textpos, text_len, &fpos); ! 533: if (result < (unsigned long) -4096) ! 534: result = decompress_exec(bprm, text_len, (char *) datapos, ! 535: data_len + (relocs * sizeof(unsigned long)), 0); ! 536: } ! 537: else ! 538: #endif ! 539: { ! 540: result = target_pread(bprm->fd, textpos, ! 541: text_len, 0); ! 542: if (result >= 0) { ! 543: result = target_pread(bprm->fd, datapos, ! 544: data_len + (relocs * sizeof(target_ulong)), ! 545: ntohl(hdr->data_start)); ! 546: } ! 547: } ! 548: if (result < 0) { ! 549: fprintf(stderr, "Unable to read code+data+bss\n"); ! 550: return result; ! 551: } ! 552: } ! 553: ! 554: DBG_FLT("Mapping is 0x%x, Entry point is 0x%x, data_start is 0x%x\n", ! 555: (int)textpos, 0x00ffffff&ntohl(hdr->entry), ! 556: ntohl(hdr->data_start)); ! 557: ! 558: /* The main program needs a little extra setup in the task structure */ ! 559: start_code = textpos + sizeof (struct flat_hdr); ! 560: end_code = textpos + text_len; ! 561: ! 562: DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n", ! 563: id ? "Lib" : "Load", bprm->filename, ! 564: (int) start_code, (int) end_code, ! 565: (int) datapos, ! 566: (int) (datapos + data_len), ! 567: (int) (datapos + data_len), ! 568: (int) (((datapos + data_len + bss_len) + 3) & ~3)); ! 569: ! 570: text_len -= sizeof(struct flat_hdr); /* the real code len */ ! 571: ! 572: /* Store the current module values into the global library structure */ ! 573: libinfo[id].start_code = start_code; ! 574: libinfo[id].start_data = datapos; ! 575: libinfo[id].end_data = datapos + data_len; ! 576: libinfo[id].start_brk = datapos + data_len + bss_len; ! 577: libinfo[id].text_len = text_len; ! 578: libinfo[id].loaded = 1; ! 579: libinfo[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos; ! 580: libinfo[id].build_date = ntohl(hdr->build_date); ! 581: ! 582: /* ! 583: * We just load the allocations into some temporary memory to ! 584: * help simplify all this mumbo jumbo ! 585: * ! 586: * We've got two different sections of relocation entries. ! 587: * The first is the GOT which resides at the begining of the data segment ! 588: * and is terminated with a -1. This one can be relocated in place. ! 589: * The second is the extra relocation entries tacked after the image's ! 590: * data segment. These require a little more processing as the entry is ! 591: * really an offset into the image which contains an offset into the ! 592: * image. ! 593: */ ! 594: if (flags & FLAT_FLAG_GOTPIC) { ! 595: rp = datapos; ! 596: while (1) { ! 597: target_ulong addr; ! 598: addr = tgetl(rp); ! 599: if (addr == -1) ! 600: break; ! 601: if (addr) { ! 602: addr = calc_reloc(addr, libinfo, id, 0); ! 603: if (addr == RELOC_FAILED) ! 604: return -ENOEXEC; ! 605: tputl(rp, addr); ! 606: } ! 607: rp += sizeof(target_ulong); ! 608: } ! 609: } ! 610: ! 611: /* ! 612: * Now run through the relocation entries. ! 613: * We've got to be careful here as C++ produces relocatable zero ! 614: * entries in the constructor and destructor tables which are then ! 615: * tested for being not zero (which will always occur unless we're ! 616: * based from address zero). This causes an endless loop as __start ! 617: * is at zero. The solution used is to not relocate zero addresses. ! 618: * This has the negative side effect of not allowing a global data ! 619: * reference to be statically initialised to _stext (I've moved ! 620: * __start to address 4 so that is okay). ! 621: */ ! 622: if (rev > OLD_FLAT_VERSION) { ! 623: for (i = 0; i < relocs; i++) { ! 624: target_ulong addr, relval; ! 625: ! 626: /* Get the address of the pointer to be ! 627: relocated (of course, the address has to be ! 628: relocated first). */ ! 629: relval = tgetl(reloc + i * sizeof (target_ulong)); ! 630: addr = flat_get_relocate_addr(relval); ! 631: rp = calc_reloc(addr, libinfo, id, 1); ! 632: if (rp == RELOC_FAILED) ! 633: return -ENOEXEC; ! 634: ! 635: /* Get the pointer's value. */ ! 636: addr = tgetl(rp); ! 637: if (addr != 0) { ! 638: /* ! 639: * Do the relocation. PIC relocs in the data section are ! 640: * already in target order ! 641: */ ! 642: ! 643: #ifndef TARGET_WORDS_BIGENDIAN ! 644: if ((flags & FLAT_FLAG_GOTPIC) == 0) ! 645: addr = bswap32(addr); ! 646: #endif ! 647: addr = calc_reloc(addr, libinfo, id, 0); ! 648: if (addr == RELOC_FAILED) ! 649: return -ENOEXEC; ! 650: ! 651: /* Write back the relocated pointer. */ ! 652: tputl(rp, addr); ! 653: } ! 654: } ! 655: } else { ! 656: for (i = 0; i < relocs; i++) { ! 657: target_ulong relval; ! 658: relval = tgetl(reloc + i * sizeof (target_ulong)); ! 659: old_reloc(&libinfo[0], relval); ! 660: } ! 661: } ! 662: ! 663: /* zero the BSS. */ ! 664: memset((void*)(datapos + data_len), 0, bss_len); ! 665: ! 666: return 0; ! 667: } ! 668: ! 669: ! 670: /****************************************************************************/ ! 671: #ifdef CONFIG_BINFMT_SHARED_FLAT ! 672: ! 673: /* ! 674: * Load a shared library into memory. The library gets its own data ! 675: * segment (including bss) but not argv/argc/environ. ! 676: */ ! 677: ! 678: static int load_flat_shared_library(int id, struct lib_info *libs) ! 679: { ! 680: struct linux_binprm bprm; ! 681: int res; ! 682: char buf[16]; ! 683: ! 684: /* Create the file name */ ! 685: sprintf(buf, "/lib/lib%d.so", id); ! 686: ! 687: /* Open the file up */ ! 688: bprm.filename = buf; ! 689: bprm.file = open_exec(bprm.filename); ! 690: res = PTR_ERR(bprm.file); ! 691: if (IS_ERR(bprm.file)) ! 692: return res; ! 693: ! 694: res = prepare_binprm(&bprm); ! 695: ! 696: if (res <= (unsigned long)-4096) ! 697: res = load_flat_file(&bprm, libs, id, NULL); ! 698: if (bprm.file) { ! 699: allow_write_access(bprm.file); ! 700: fput(bprm.file); ! 701: bprm.file = NULL; ! 702: } ! 703: return(res); ! 704: } ! 705: ! 706: #endif /* CONFIG_BINFMT_SHARED_FLAT */ ! 707: ! 708: int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, ! 709: struct image_info * info) ! 710: { ! 711: struct lib_info libinfo[MAX_SHARED_LIBS]; ! 712: target_ulong p = bprm->p; ! 713: target_ulong stack_len; ! 714: target_ulong start_addr; ! 715: target_ulong sp; ! 716: int res; ! 717: int i, j; ! 718: ! 719: memset(libinfo, 0, sizeof(libinfo)); ! 720: /* ! 721: * We have to add the size of our arguments to our stack size ! 722: * otherwise it's too easy for users to create stack overflows ! 723: * by passing in a huge argument list. And yes, we have to be ! 724: * pedantic and include space for the argv/envp array as it may have ! 725: * a lot of entries. ! 726: */ ! 727: #define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *)) ! 728: stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ ! 729: stack_len += (bprm->argc + 1) * 4; /* the argv array */ ! 730: stack_len += (bprm->envc + 1) * 4; /* the envp array */ ! 731: ! 732: ! 733: res = load_flat_file(bprm, libinfo, 0, &stack_len); ! 734: if (res > (unsigned long)-4096) ! 735: return res; ! 736: ! 737: /* Update data segment pointers for all libraries */ ! 738: for (i=0; i<MAX_SHARED_LIBS; i++) { ! 739: if (libinfo[i].loaded) { ! 740: target_ulong p; ! 741: p = libinfo[i].start_data; ! 742: for (j=0; j<MAX_SHARED_LIBS; j++) { ! 743: p -= 4; ! 744: tput32(p, libinfo[j].loaded ! 745: ? libinfo[j].start_data ! 746: : UNLOADED_LIB); ! 747: } ! 748: } ! 749: } ! 750: ! 751: p = ((libinfo[0].start_brk + stack_len + 3) & ~3) - 4; ! 752: DBG_FLT("p=%x\n", (int)p); ! 753: ! 754: /* Copy argv/envp. */ ! 755: p = copy_strings(p, bprm->argc, bprm->argv); ! 756: p = copy_strings(p, bprm->envc, bprm->envp); ! 757: /* Align stack. */ ! 758: sp = p & ~(target_ulong)(sizeof(target_ulong) - 1); ! 759: sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1); ! 760: ! 761: /* Fake some return addresses to ensure the call chain will ! 762: * initialise library in order for us. We are required to call ! 763: * lib 1 first, then 2, ... and finally the main program (id 0). ! 764: */ ! 765: start_addr = libinfo[0].entry; ! 766: ! 767: #ifdef CONFIG_BINFMT_SHARED_FLAT ! 768: #error here ! 769: for (i = MAX_SHARED_LIBS-1; i>0; i--) { ! 770: if (libinfo[i].loaded) { ! 771: /* Push previos first to call address */ ! 772: --sp; put_user(start_addr, sp); ! 773: start_addr = libinfo[i].entry; ! 774: } ! 775: } ! 776: #endif ! 777: ! 778: /* Stash our initial stack pointer into the mm structure */ ! 779: info->start_code = libinfo[0].start_code; ! 780: info->end_code = libinfo[0].start_code = libinfo[0].text_len; ! 781: info->start_data = libinfo[0].start_data; ! 782: info->end_data = libinfo[0].end_data; ! 783: info->start_brk = libinfo[0].start_brk; ! 784: info->start_stack = sp; ! 785: info->entry = start_addr; ! 786: info->code_offset = info->start_code; ! 787: info->data_offset = info->start_data - libinfo[0].text_len; ! 788: ! 789: DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n", ! 790: (int)info->entry, (int)info->start_stack); ! 791: ! 792: return 0; ! 793: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.