1 /* $OpenBSD: file.c,v 1.13 2009/10/27 23:59:52 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1995-96 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "os.h" 28 #include "common/common.h" 29 #include "common/mopdef.h" 30 31 #define INFO_PRINT 1 32 33 #ifndef NOAOUT 34 #if defined(__NetBSD__) || defined(__OpenBSD__) 35 #include <sys/exec_aout.h> 36 #endif 37 #if defined(__bsdi__) 38 #define NOAOUT 39 #endif 40 #if defined(__FreeBSD__) 41 #include <sys/imgact_aout.h> 42 #endif 43 #if !defined(MID_I386) 44 #define MID_I386 134 45 #endif 46 #if !defined(MID_SPARC) 47 #define MID_SPARC 138 48 #endif 49 #if !defined(MID_VAX) 50 #define MID_VAX 140 51 #endif 52 #endif 53 54 void 55 mopFilePutLX(u_char *buf, int idx, u_long value, int cnt) 56 { 57 int i; 58 for (i = 0; i < cnt; i++) { 59 buf[idx+i] = (u_char)(value % 256); 60 value = (u_char)(value / 256); 61 } 62 } 63 64 void 65 mopFilePutBX(u_char *buf, int idx, u_long value, int cnt) 66 { 67 int i; 68 for (i = 0; i < cnt; i++) { 69 buf[idx+cnt-1-i] = (u_char)(value % 256); 70 value = value / 256; 71 } 72 } 73 74 u_long 75 mopFileGetLX(void *buffer, int idx, int cnt) 76 { 77 u_long ret = 0; 78 int i; 79 u_char *buf = (u_char *)buffer; 80 81 for (i = 0; i < cnt; i++) 82 ret = ret*256 + buf[idx+cnt-1-i]; 83 84 return (ret); 85 } 86 87 u_long 88 mopFileGetBX(void *buffer, int idx, int cnt) 89 { 90 u_long ret = 0; 91 int i; 92 u_char *buf = (u_char *)buffer; 93 94 for (i = 0; i < cnt; i++) 95 ret = ret*256 + buf[idx+i]; 96 97 return (ret); 98 } 99 100 void 101 mopFileSwapX(void *buffer, int idx, int cnt) 102 { 103 int i; 104 u_char c; 105 u_char *buf = (u_char *)buffer; 106 107 for (i = 0; i < (cnt / 2); i++) { 108 c = buf[idx+i]; 109 buf[idx+i] = buf[idx+cnt-1-i]; 110 buf[idx+cnt-1-i] = c; 111 } 112 113 } 114 115 int 116 CheckMopFile(int fd) 117 { 118 u_char header[512]; 119 short image_type; 120 121 if (read(fd, header, 512) != 512) 122 return (-1); 123 124 lseek(fd, 0, SEEK_SET); 125 126 image_type = (short)mopFileGetLX(header,IHD_W_ALIAS,2); 127 128 switch (image_type) { 129 case IHD_C_NATIVE: /* Native mode image (VAX) */ 130 case IHD_C_RSX: /* RSX image produced by TKB */ 131 case IHD_C_BPA: /* BASIC plus analog */ 132 case IHD_C_ALIAS: /* Alias */ 133 case IHD_C_CLI: /* Image is CLI */ 134 case IHD_C_PMAX: /* PMAX system image */ 135 case IHD_C_ALPHA: /* ALPHA system image */ 136 break; 137 default: 138 return (-1); 139 } 140 141 return (0); 142 } 143 144 int 145 GetMopFileInfo(int fd, u_long *load, u_long *xfr, int info) 146 { 147 u_char header[512]; 148 short image_type, isd, iha; 149 u_long load_addr, xfr_addr, isize, hbcnt; 150 151 if (read(fd, header, 512) != 512) 152 return (-1); 153 154 image_type = (short)mopFileGetLX(header,IHD_W_ALIAS,2); 155 156 switch (image_type) { 157 case IHD_C_NATIVE: /* Native mode image (VAX) */ 158 isd = (short)mopFileGetLX(header,IHD_W_SIZE,2); 159 iha = (short)mopFileGetLX(header,IHD_W_ACTIVOFF,2); 160 hbcnt = header[IHD_B_HDRBLKCNT]; 161 isize = mopFileGetLX(header,isd+ISD_W_PAGCNT,2) * 512; 162 load_addr = (mopFileGetLX(header,isd+ISD_V_VPN,2) & 163 ISD_M_VPN) * 512; 164 xfr_addr = mopFileGetLX(header,iha+IHA_L_TFRADR1,4) & 165 0x7fffffff; 166 if (info == INFO_PRINT) { 167 printf("Native Image (VAX)\n"); 168 printf("Header Block Count: %lu\n", hbcnt); 169 printf("Image Size: %08lx\n", isize); 170 printf("Load Address: %08lx\n", load_addr); 171 printf("Transfer Address: %08lx\n", xfr_addr); 172 } 173 break; 174 case IHD_C_RSX: /* RSX image produced by TKB */ 175 hbcnt = mopFileGetLX(header,L_BBLK,2); 176 isize = mopFileGetLX(header,L_BLDZ,2) * 64; 177 load_addr = mopFileGetLX(header,L_BSA,2); 178 xfr_addr = mopFileGetLX(header,L_BXFR,2); 179 if (info == INFO_PRINT) { 180 printf("RSX Image\n"); 181 printf("Header Block Count: %lu\n",hbcnt); 182 printf("Image Size: %08lx\n", isize); 183 printf("Load Address: %08lx\n", load_addr); 184 printf("Transfer Address: %08lx\n", xfr_addr); 185 } 186 break; 187 case IHD_C_BPA: /* BASIC plus analog */ 188 if (info == INFO_PRINT) { 189 printf("BASIC-Plus Image, not supported\n"); 190 } 191 return (-1); 192 case IHD_C_ALIAS: /* Alias */ 193 if (info == INFO_PRINT) { 194 printf("Alias, not supported\n"); 195 } 196 return (-1); 197 case IHD_C_CLI: /* Image is CLI */ 198 if (info == INFO_PRINT) { 199 printf("CLI, not supported\n"); 200 } 201 return (-1); 202 case IHD_C_PMAX: /* PMAX system image */ 203 isd = (short)mopFileGetLX(header,IHD_W_SIZE,2); 204 iha = (short)mopFileGetLX(header,IHD_W_ACTIVOFF,2); 205 hbcnt = header[IHD_B_HDRBLKCNT]; 206 isize = mopFileGetLX(header,isd+ISD_W_PAGCNT,2) * 512; 207 load_addr = mopFileGetLX(header,isd+ISD_V_VPN,2) * 512; 208 xfr_addr = mopFileGetLX(header,iha+IHA_L_TFRADR1,4); 209 if (info == INFO_PRINT) { 210 printf("PMAX Image \n"); 211 printf("Header Block Count: %lu\n", hbcnt); 212 printf("Image Size: %08lx\n", isize); 213 printf("Load Address: %08lx\n", load_addr); 214 printf("Transfer Address: %08lx\n", xfr_addr); 215 } 216 break; 217 case IHD_C_ALPHA: /* ALPHA system image */ 218 isd = (short)mopFileGetLX(header,EIHD_L_ISDOFF,4); 219 hbcnt = mopFileGetLX(header,EIHD_L_HDRBLKCNT,4); 220 isize = mopFileGetLX(header,isd+EISD_L_SECSIZE,4); 221 load_addr = 0; 222 xfr_addr = 0; 223 if (info == INFO_PRINT) { 224 printf("Alpha Image \n"); 225 printf("Header Block Count: %lu\n", hbcnt); 226 printf("Image Size: %08lx\n", isize); 227 printf("Load Address: %08lx\n", load_addr); 228 printf("Transfer Address: %08lx\n", xfr_addr); 229 } 230 break; 231 default: 232 if (info == INFO_PRINT) { 233 printf("Unknown Image (%d)\n", image_type); 234 } 235 return (-1); 236 } 237 238 if (load != NULL) 239 *load = load_addr; 240 241 if (xfr != NULL) 242 *xfr = xfr_addr; 243 244 return (0); 245 } 246 247 #ifndef NOAOUT 248 int 249 getMID(int old_mid, int new_mid) 250 { 251 int mid; 252 253 mid = old_mid; 254 255 switch (new_mid) { 256 case MID_I386: 257 mid = MID_I386; 258 break; 259 #ifdef MID_M68K 260 case MID_M68K: 261 mid = MID_M68K; 262 break; 263 #endif 264 #ifdef MID_M68K4K 265 case MID_M68K4K: 266 mid = MID_M68K4K; 267 break; 268 #endif 269 #ifdef MID_NS32532 270 case MID_NS32532: 271 mid = MID_NS32532; 272 break; 273 #endif 274 case MID_SPARC: 275 mid = MID_SPARC; 276 break; 277 #ifdef MID_PMAX 278 case MID_PMAX: 279 mid = MID_PMAX; 280 break; 281 #endif 282 #ifdef MID_VAX 283 case MID_VAX: 284 mid = MID_VAX; 285 break; 286 #endif 287 #ifdef MID_ALPHA 288 case MID_ALPHA: 289 mid = MID_ALPHA; 290 break; 291 #endif 292 #ifdef MID_MIPS 293 case MID_MIPS: 294 mid = MID_MIPS; 295 break; 296 #endif 297 #ifdef MID_ARM6 298 case MID_ARM6: 299 mid = MID_ARM6; 300 break; 301 #endif 302 default: 303 break; 304 } 305 306 return (mid); 307 } 308 309 u_int 310 getCLBYTES(int mid) 311 { 312 u_int clbytes; 313 314 switch (mid) { 315 #ifdef MID_VAX 316 case MID_VAX: 317 clbytes = 1024; 318 break; 319 #endif 320 case MID_I386: 321 #ifdef MID_M68K4K 322 case MID_M68K4K: 323 #endif 324 #ifdef MID_NS32532 325 case MID_NS32532: 326 #endif 327 case MID_SPARC: /* It might be 8192 */ 328 #ifdef MID_PMAX 329 case MID_PMAX: 330 #endif 331 #ifdef MID_MIPS 332 case MID_MIPS: 333 #endif 334 #ifdef MID_ARM6 335 case MID_ARM6: 336 #endif 337 clbytes = 4096; 338 break; 339 #ifdef MID_M68K 340 case MID_M68K: 341 #endif 342 #ifdef MID_ALPHA 343 case MID_ALPHA: 344 #endif 345 #if defined(MID_M68K) || defined(MID_ALPHA) 346 clbytes = 8192; 347 break; 348 #endif 349 default: 350 clbytes = 0; 351 } 352 353 return (clbytes); 354 } 355 #endif 356 357 int 358 CheckAOutFile(int fd) 359 { 360 #ifdef NOAOUT 361 return (-1); 362 #else 363 struct exec ex, ex_swap; 364 int mid = -1; 365 366 if (read(fd, &ex, sizeof(ex)) != (ssize_t)sizeof(ex)) 367 return (-1); 368 369 lseek(fd, 0, SEEK_SET); 370 371 if (read(fd, &ex_swap, sizeof(ex_swap)) != (ssize_t)sizeof(ex_swap)) 372 return (-1); 373 374 lseek(fd, 0, SEEK_SET); 375 376 mid = getMID(mid, (int)N_GETMID(ex)); 377 378 if (mid == -1) 379 mid = getMID(mid, (int)N_GETMID(ex_swap)); 380 381 if (mid != -1) 382 return (0); 383 else 384 return (-1); 385 #endif /* NOAOUT */ 386 } 387 388 int 389 GetAOutFileInfo(int fd, u_long *load, u_long *xfr, u_long *a_text, 390 u_long *a_text_fill, u_long *a_data, u_long *a_data_fill, u_long *a_bss, 391 u_long *a_bss_fill, int *aout, int info) 392 { 393 #ifdef NOAOUT 394 return (-1); 395 #else 396 struct exec ex, ex_swap; 397 int mid = -1; 398 u_long magic, clbytes, clofset; 399 400 if (read(fd, &ex, sizeof(ex)) != (ssize_t)sizeof(ex)) 401 return (-1); 402 403 lseek(fd, 0, SEEK_SET); 404 405 if (read(fd, &ex_swap, sizeof(ex_swap)) != (ssize_t)sizeof(ex_swap)) 406 return (-1); 407 408 mopFileSwapX(&ex_swap, 0, 4); 409 410 mid = getMID(mid, (int)N_GETMID(ex)); 411 412 if (mid == -1) { 413 mid = getMID(mid, (int)N_GETMID(ex_swap)); 414 if (mid != -1) 415 mopFileSwapX(&ex, 0, 4); 416 } 417 418 if (mid == -1) 419 return (-1); 420 421 if (N_BADMAG(ex)) 422 return (-1); 423 424 switch (mid) { 425 case MID_I386: 426 #ifdef MID_NS32532 427 case MID_NS32532: 428 #endif 429 #ifdef MID_PMAX 430 case MID_PMAX: 431 #endif 432 #ifdef MID_VAX 433 case MID_VAX: 434 #endif 435 #ifdef MID_ALPHA 436 case MID_ALPHA: 437 #endif 438 #ifdef MID_ARM6 439 case MID_ARM6: 440 #endif 441 ex.a_text = (u_int)mopFileGetLX(&ex_swap, 4, 4); 442 ex.a_data = (u_int)mopFileGetLX(&ex_swap, 8, 4); 443 ex.a_bss = (u_int)mopFileGetLX(&ex_swap, 12, 4); 444 ex.a_syms = (u_int)mopFileGetLX(&ex_swap, 16, 4); 445 ex.a_entry = (u_int)mopFileGetLX(&ex_swap, 20, 4); 446 ex.a_trsize = (u_int)mopFileGetLX(&ex_swap, 24, 4); 447 ex.a_drsize = (u_int)mopFileGetLX(&ex_swap, 28, 4); 448 break; 449 #ifdef MID_M68K 450 case MID_M68K: 451 #endif 452 #ifdef MID_M68K4K 453 case MID_M68K4K: 454 #endif 455 case MID_SPARC: 456 #ifdef MID_MIPS 457 case MID_MIPS: 458 #endif 459 ex.a_text = (u_int)mopFileGetBX(&ex_swap, 4, 4); 460 ex.a_data = (u_int)mopFileGetBX(&ex_swap, 8, 4); 461 ex.a_bss = (u_int)mopFileGetBX(&ex_swap, 12, 4); 462 ex.a_syms = (u_int)mopFileGetBX(&ex_swap, 16, 4); 463 ex.a_entry = (u_int)mopFileGetBX(&ex_swap, 20, 4); 464 ex.a_trsize = (u_int)mopFileGetBX(&ex_swap, 24, 4); 465 ex.a_drsize = (u_int)mopFileGetBX(&ex_swap, 28, 4); 466 break; 467 default: 468 break; 469 } 470 471 if (info == INFO_PRINT) { 472 printf("a.out image ("); 473 switch (N_GETMID(ex)) { 474 case MID_I386: 475 printf("i386"); 476 break; 477 #ifdef MID_M68K 478 case MID_M68K: 479 printf("m68k"); 480 break; 481 #endif 482 #ifdef MID_M68K4K 483 case MID_M68K4K: 484 printf("m68k 4k"); 485 break; 486 #endif 487 #ifdef MID_NS32532 488 case MID_NS32532: 489 printf("pc532"); 490 break; 491 #endif 492 case MID_SPARC: 493 printf("sparc"); 494 break; 495 #ifdef MID_PMAX 496 case MID_PMAX: 497 printf("pmax"); 498 break; 499 #endif 500 #ifdef MID_VAX 501 case MID_VAX: 502 printf("vax"); 503 break; 504 #endif 505 #ifdef MID_ALPHA 506 case MID_ALPHA: 507 printf("alpha"); 508 break; 509 #endif 510 #ifdef MID_MIPS 511 case MID_MIPS: 512 printf("mips"); 513 break; 514 #endif 515 #ifdef MID_ARM6 516 case MID_ARM6: 517 printf("arm32"); 518 break; 519 #endif 520 default: 521 break; 522 } 523 printf(") Magic: "); 524 switch (N_GETMAGIC (ex)) { 525 case OMAGIC: 526 printf("OMAGIC"); 527 break; 528 case NMAGIC: 529 printf("NMAGIC"); 530 break; 531 case ZMAGIC: 532 printf("ZMAGIC"); 533 break; 534 case QMAGIC: 535 printf("QMAGIC"); 536 break; 537 default: 538 printf("Unknown %d",N_GETMAGIC (ex)); 539 } 540 printf("\n"); 541 printf("Size of text: %08x\n", ex.a_text); 542 printf("Size of data: %08x\n", ex.a_data); 543 printf("Size of bss: %08x\n", ex.a_bss); 544 printf("Size of symbol tab: %08x\n", ex.a_syms); 545 printf("Transfer Address: %08x\n", ex.a_entry); 546 printf("Size of reloc text: %08x\n", ex.a_trsize); 547 printf("Size of reloc data: %08x\n", ex.a_drsize); 548 } 549 magic = N_GETMAGIC(ex); 550 clbytes = getCLBYTES(mid); 551 clofset = clbytes - 1; 552 553 if (load != NULL) 554 *load = 0; 555 556 if (xfr != NULL) 557 *xfr = ex.a_entry; 558 559 if (a_text != NULL) 560 *a_text = ex.a_text; 561 562 if (a_text_fill != NULL) { 563 if (magic == ZMAGIC || magic == NMAGIC) { 564 *a_text_fill = clbytes - (ex.a_text & clofset); 565 if (*a_text_fill == clbytes) 566 *a_text_fill = 0; 567 } else 568 *a_text_fill = 0; 569 } 570 571 if (a_data != NULL) 572 *a_data = ex.a_data; 573 574 if (a_data_fill != NULL) { 575 if (magic == ZMAGIC || magic == NMAGIC) { 576 *a_data_fill = clbytes - (ex.a_data & clofset); 577 if (*a_data_fill == clbytes) 578 *a_data_fill = 0; 579 } else 580 *a_data_fill = 0; 581 } 582 583 if (a_bss != NULL) 584 *a_bss = ex.a_bss; 585 586 if (a_bss_fill != NULL) { 587 if (magic == ZMAGIC || magic == NMAGIC) { 588 *a_bss_fill = clbytes - (ex.a_bss & clofset); 589 if (*a_bss_fill == clbytes) 590 *a_bss_fill = 0; 591 } else { 592 *a_bss_fill = clbytes - 593 ((ex.a_text + ex.a_data + ex.a_bss) & clofset); 594 if (*a_text_fill == clbytes) 595 *a_text_fill = 0; 596 } 597 } 598 599 if (aout != NULL) 600 *aout = mid; 601 602 return (0); 603 #endif /* NOAOUT */ 604 } 605 606 int 607 GetFileInfo(int fd, u_long *load, u_long *xfr, int *aout, u_long *a_text, 608 u_long *a_text_fill, u_long *a_data, u_long *a_data_fill, u_long *a_bss, 609 u_long *a_bss_fill, int info) 610 { 611 int err; 612 613 err = CheckAOutFile(fd); 614 615 if (err == 0) { 616 err = GetAOutFileInfo(fd, load, xfr, a_text, a_text_fill, 617 a_data, a_data_fill, a_bss, a_bss_fill, aout, info); 618 if (err != 0) 619 return (-1); 620 } else { 621 err = CheckMopFile(fd); 622 623 if (err == 0) { 624 err = GetMopFileInfo(fd, load, xfr, info); 625 if (err != 0) 626 return (-1); 627 *aout = -1; 628 } else 629 return (-1); 630 } 631 632 return (0); 633 } 634 635 ssize_t 636 mopFileRead(struct dllist *dlslot, u_char *buf) 637 { 638 ssize_t len, outlen; 639 u_long bsz, total, notdone; 640 off_t pos; 641 642 if (dlslot->aout == -1) 643 len = read(dlslot->ldfd,buf,dlslot->dl_bsz); 644 else { 645 bsz = dlslot->dl_bsz; 646 pos = dlslot->a_lseek; 647 len = 0; 648 649 total = dlslot->a_text; 650 651 if (pos < (off_t)total) { 652 notdone = total - (u_long)pos; 653 if (notdone <= bsz) 654 outlen = read(dlslot->ldfd,&buf[len],notdone); 655 else 656 outlen = read(dlslot->ldfd,&buf[len],bsz); 657 len = len + outlen; 658 pos = pos + outlen; 659 bsz = bsz - (u_long)outlen; 660 } 661 662 total = total + dlslot->a_text_fill; 663 664 if ((bsz > 0) && (pos < (off_t)total)) { 665 notdone = total - (u_long)pos; 666 if (notdone <= bsz) 667 outlen = (ssize_t)notdone; 668 else 669 outlen = (ssize_t)bsz; 670 bzero(&buf[len],(u_long)outlen); 671 len = len + outlen; 672 pos = pos + outlen; 673 bsz = bsz - (u_long)outlen; 674 } 675 676 total = total + dlslot->a_data; 677 678 if ((bsz > 0) && (pos < (off_t)total)) { 679 notdone = total - (u_long)pos; 680 if (notdone <= bsz) 681 outlen = read(dlslot->ldfd,&buf[len],notdone); 682 else 683 outlen = read(dlslot->ldfd,&buf[len],bsz); 684 len = len + outlen; 685 pos = pos + outlen; 686 bsz = bsz - (u_long)outlen; 687 } 688 689 total = total + dlslot->a_data_fill; 690 691 if ((bsz > 0) && (pos < (off_t)total)) { 692 notdone = total - (u_long)pos; 693 if (notdone <= bsz) 694 outlen = (ssize_t)notdone; 695 else 696 outlen = (ssize_t)bsz; 697 bzero(&buf[len],(u_long)outlen); 698 len = len + outlen; 699 pos = pos + outlen; 700 bsz = bsz - (u_long)outlen; 701 } 702 703 total = total + dlslot->a_bss; 704 705 if ((bsz > 0) && (pos < (off_t)total)) { 706 notdone = total - (u_long)pos; 707 if (notdone <= bsz) 708 outlen = (ssize_t)notdone; 709 else 710 outlen = (ssize_t)bsz; 711 bzero(&buf[len],(u_long)outlen); 712 len = len + outlen; 713 pos = pos + outlen; 714 bsz = bsz - (u_long)outlen; 715 } 716 717 total = total + dlslot->a_bss_fill; 718 719 if ((bsz > 0) && (pos < (off_t)total)) { 720 notdone = total - (u_long)pos; 721 if (notdone <= bsz) 722 outlen = (ssize_t)notdone; 723 else 724 outlen = (ssize_t)bsz; 725 bzero(&buf[len],(u_long)outlen); 726 len = len + outlen; 727 pos = pos + outlen; 728 bsz = bsz - (u_long)outlen; 729 } 730 731 dlslot->a_lseek = pos; 732 733 } 734 735 return (len); 736 } 737