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