1 /* $OpenBSD: file.c,v 1.19 2017/10/29 08:45:53 mpi 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.h" 29 #include "file.h" 30 #include "mopdef.h" 31 #include <stddef.h> 32 33 #ifndef NOAOUT 34 #if defined(__OpenBSD__) 35 #include <sys/exec.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 #ifndef NOELF 55 #if defined(__OpenBSD__) 56 #include <elf.h> 57 #else 58 #define NOELF 59 #endif 60 #endif 61 62 #ifndef NOELF 63 #if !defined(_LP64) 64 #define NOELF64 65 #endif 66 #endif 67 68 #ifndef NOAOUT 69 static int getCLBYTES(int); 70 static int getMID(int, int); 71 #endif 72 73 const char * 74 FileTypeName(mopd_imagetype type) 75 { 76 77 switch (type) { 78 case IMAGE_TYPE_MOP: 79 return ("MOP"); 80 81 case IMAGE_TYPE_ELF32: 82 return ("Elf32"); 83 84 case IMAGE_TYPE_ELF64: 85 return ("Elf64"); 86 87 case IMAGE_TYPE_AOUT: 88 return ("a.out"); 89 } 90 91 abort(); 92 } 93 94 void 95 mopFilePutLX(u_char *buf, int idx, u_int32_t value, int cnt) 96 { 97 int i; 98 for (i = 0; i < cnt; i++) { 99 buf[idx+i] = value % 256; 100 value = value / 256; 101 } 102 } 103 104 void 105 mopFilePutBX(u_char *buf, int idx, u_int32_t value, int cnt) 106 { 107 int i; 108 for (i = 0; i < cnt; i++) { 109 buf[idx+cnt-1-i] = value % 256; 110 value = value / 256; 111 } 112 } 113 114 u_int32_t 115 mopFileGetLX(u_char *buf, int idx, int cnt) 116 { 117 u_int32_t ret = 0; 118 int i; 119 120 for (i = 0; i < cnt; i++) { 121 int j = idx + cnt - 1 - i; 122 if (j < 0) 123 abort(); 124 ret = ret * 256 + buf[j]; 125 } 126 127 return(ret); 128 } 129 130 u_int32_t 131 mopFileGetBX(u_char *buf, int idx, int cnt) 132 { 133 u_int32_t ret = 0; 134 int i; 135 136 for (i = 0; i < cnt; i++) { 137 int j = idx + i; 138 if (j < 0) 139 abort(); 140 ret = ret * 256 + buf[j]; 141 } 142 143 return(ret); 144 } 145 146 #if !defined(NOELF) && !defined(NOELF64) 147 u_int64_t 148 mopFileGetLXX(u_char *buf, int idx, int cnt) 149 { 150 u_int64_t ret = 0; 151 int i; 152 153 for (i = 0; i < cnt; i++) { 154 int j = idx + cnt - 1 - i; 155 if (j < 0) 156 abort(); 157 ret = ret * 256 + buf[j]; 158 } 159 160 return(ret); 161 } 162 163 u_int64_t 164 mopFileGetBXX(u_char *buf, int idx, int cnt) 165 { 166 u_int64_t ret = 0; 167 int i; 168 169 for (i = 0; i < cnt; i++) { 170 int j = idx + i; 171 if (j < 0) 172 abort(); 173 ret = ret * 256 + buf[j]; 174 } 175 176 return(ret); 177 } 178 #endif 179 180 void 181 mopFileSwapX(u_char *buf, int idx, int cnt) 182 { 183 int i; 184 u_char c; 185 186 for (i = 0; i < (cnt / 2); i++) { 187 c = buf[idx+i]; 188 buf[idx+i] = buf[idx+cnt-1-i]; 189 buf[idx+cnt-1-i] = c; 190 } 191 192 } 193 194 int 195 CheckMopFile(int fd) 196 { 197 u_char header[512]; 198 short image_type; 199 200 if (read(fd, header, 512) != 512) 201 return(-1); 202 203 (void)lseek(fd, (off_t) 0, SEEK_SET); 204 205 image_type = (u_short)(header[IHD_W_ALIAS+1]*256 + header[IHD_W_ALIAS]); 206 207 switch(image_type) { 208 case IHD_C_NATIVE: /* Native mode image (VAX) */ 209 case IHD_C_RSX: /* RSX image produced by TKB */ 210 case IHD_C_BPA: /* BASIC plus analog */ 211 case IHD_C_ALIAS: /* Alias */ 212 case IHD_C_CLI: /* Image is CLI */ 213 case IHD_C_PMAX: /* PMAX system image */ 214 case IHD_C_ALPHA: /* ALPHA system image */ 215 break; 216 default: 217 return(-1); 218 } 219 220 return(0); 221 } 222 223 int 224 GetMopFileInfo(struct dllist *dl, int info) 225 { 226 u_char header[512]; 227 short image_type; 228 u_int32_t load_addr, xfr_addr, isd, iha, hbcnt, isize; 229 230 if (read(dl->ldfd, header, 512) != 512) 231 return(-1); 232 233 image_type = (u_short)(header[IHD_W_ALIAS+1]*256 + 234 header[IHD_W_ALIAS]); 235 236 switch (image_type) { 237 case IHD_C_NATIVE: /* Native mode image (VAX) */ 238 isd = (header[IHD_W_SIZE+1]*256 + 239 header[IHD_W_SIZE]); 240 iha = (header[IHD_W_ACTIVOFF+1]*256 + 241 header[IHD_W_ACTIVOFF]); 242 hbcnt = (header[IHD_B_HDRBLKCNT]); 243 isize = (header[isd+ISD_W_PAGCNT+1]*256 + 244 header[isd+ISD_W_PAGCNT]) * 512; 245 load_addr = ((header[isd+ISD_V_VPN+1]*256 + 246 header[isd+ISD_V_VPN]) & ISD_M_VPN) 247 * 512; 248 xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 + 249 header[iha+IHA_L_TFRADR1+2]*0x10000 + 250 header[iha+IHA_L_TFRADR1+1]*0x100 + 251 header[iha+IHA_L_TFRADR1]) & 0x7fffffff; 252 if (info == INFO_PRINT) { 253 printf("Native Image (VAX)\n"); 254 printf("Header Block Count: %d\n",hbcnt); 255 printf("Image Size: %08x\n",isize); 256 printf("Load Address: %08x\n",load_addr); 257 printf("Transfer Address: %08x\n",xfr_addr); 258 } 259 break; 260 case IHD_C_RSX: /* RSX image produced by TKB */ 261 hbcnt = header[L_BBLK+1]*256 + header[L_BBLK]; 262 isize = (header[L_BLDZ+1]*256 + header[L_BLDZ]) * 64; 263 load_addr = header[L_BSA+1]*256 + header[L_BSA]; 264 xfr_addr = header[L_BXFR+1]*256 + header[L_BXFR]; 265 if (info == INFO_PRINT) { 266 printf("RSX Image\n"); 267 printf("Header Block Count: %d\n",hbcnt); 268 printf("Image Size: %08x\n",isize); 269 printf("Load Address: %08x\n",load_addr); 270 printf("Transfer Address: %08x\n",xfr_addr); 271 } 272 break; 273 case IHD_C_BPA: /* BASIC plus analog */ 274 if (info == INFO_PRINT) { 275 printf("BASIC-Plus Image, not supported\n"); 276 } 277 return(-1); 278 break; 279 case IHD_C_ALIAS: /* Alias */ 280 if (info == INFO_PRINT) { 281 printf("Alias, not supported\n"); 282 } 283 return(-1); 284 break; 285 case IHD_C_CLI: /* Image is CLI */ 286 if (info == INFO_PRINT) { 287 printf("CLI, not supported\n"); 288 } 289 return(-1); 290 break; 291 case IHD_C_PMAX: /* PMAX system image */ 292 isd = (header[IHD_W_SIZE+1]*256 + 293 header[IHD_W_SIZE]); 294 iha = (header[IHD_W_ACTIVOFF+1]*256 + 295 header[IHD_W_ACTIVOFF]); 296 hbcnt = (header[IHD_B_HDRBLKCNT]); 297 isize = (header[isd+ISD_W_PAGCNT+1]*256 + 298 header[isd+ISD_W_PAGCNT]) * 512; 299 load_addr = (header[isd+ISD_V_VPN+1]*256 + 300 header[isd+ISD_V_VPN]) * 512; 301 xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 + 302 header[iha+IHA_L_TFRADR1+2]*0x10000 + 303 header[iha+IHA_L_TFRADR1+1]*0x100 + 304 header[iha+IHA_L_TFRADR1]); 305 if (info == INFO_PRINT) { 306 printf("PMAX Image \n"); 307 printf("Header Block Count: %d\n",hbcnt); 308 printf("Image Size: %08x\n",isize); 309 printf("Load Address: %08x\n",load_addr); 310 printf("Transfer Address: %08x\n",xfr_addr); 311 } 312 break; 313 case IHD_C_ALPHA: /* ALPHA system image */ 314 isd = (header[EIHD_L_ISDOFF+3]*0x1000000 + 315 header[EIHD_L_ISDOFF+2]*0x10000 + 316 header[EIHD_L_ISDOFF+1]*0x100 + 317 header[EIHD_L_ISDOFF]); 318 hbcnt = (header[EIHD_L_HDRBLKCNT+3]*0x1000000 + 319 header[EIHD_L_HDRBLKCNT+2]*0x10000 + 320 header[EIHD_L_HDRBLKCNT+1]*0x100 + 321 header[EIHD_L_HDRBLKCNT]); 322 isize = (header[isd+EISD_L_SECSIZE+3]*0x1000000 + 323 header[isd+EISD_L_SECSIZE+2]*0x10000 + 324 header[isd+EISD_L_SECSIZE+1]*0x100 + 325 header[isd+EISD_L_SECSIZE]); 326 load_addr = 0; 327 xfr_addr = 0; 328 if (info == INFO_PRINT) { 329 printf("Alpha Image \n"); 330 printf("Header Block Count: %d\n",hbcnt); 331 printf("Image Size: %08x\n",isize); 332 printf("Load Address: %08x\n",load_addr); 333 printf("Transfer Address: %08x\n",xfr_addr); 334 } 335 break; 336 default: 337 if (info == INFO_PRINT) { 338 printf("Unknown Image (%d)\n",image_type); 339 } 340 return(-1); 341 } 342 343 dl->image_type = IMAGE_TYPE_MOP; 344 dl->loadaddr = load_addr; 345 dl->xferaddr = xfr_addr; 346 347 return(0); 348 } 349 350 #ifndef NOAOUT 351 static int 352 getMID(int old_mid, int new_mid) 353 { 354 int mid; 355 356 mid = old_mid; 357 358 switch (new_mid) { 359 case MID_I386: 360 mid = MID_I386; 361 break; 362 #ifdef MID_M68K 363 case MID_M68K: 364 mid = MID_M68K; 365 break; 366 #endif 367 #ifdef MID_M68K4K 368 case MID_M68K4K: 369 mid = MID_M68K4K; 370 break; 371 #endif 372 #ifdef MID_NS32532 373 case MID_NS32532: 374 mid = MID_NS32532; 375 break; 376 #endif 377 case MID_SPARC: 378 mid = MID_SPARC; 379 break; 380 #ifdef MID_PMAX 381 case MID_PMAX: 382 mid = MID_PMAX; 383 break; 384 #endif 385 #ifdef MID_VAX 386 case MID_VAX: 387 mid = MID_VAX; 388 break; 389 #endif 390 #ifdef MID_ALPHA 391 case MID_ALPHA: 392 mid = MID_ALPHA; 393 break; 394 #endif 395 #ifdef MID_MIPS 396 case MID_MIPS: 397 mid = MID_MIPS; 398 break; 399 #endif 400 #ifdef MID_ARM6 401 case MID_ARM6: 402 mid = MID_ARM6; 403 break; 404 #endif 405 default: 406 break; 407 } 408 409 return(mid); 410 } 411 412 static int 413 getCLBYTES(int mid) 414 { 415 int clbytes; 416 417 switch (mid) { 418 #ifdef MID_VAX 419 case MID_VAX: 420 clbytes = 1024; 421 break; 422 #endif 423 #ifdef MID_I386 424 case MID_I386: 425 #endif 426 #ifdef MID_M68K4K 427 case MID_M68K4K: 428 #endif 429 #ifdef MID_NS32532 430 case MID_NS32532: 431 #endif 432 #ifdef MID_PMAX 433 case MID_PMAX: 434 #endif 435 #ifdef MID_MIPS 436 case MID_MIPS: 437 #endif 438 #ifdef MID_ARM6 439 case MID_ARM6: 440 #endif 441 #if defined(MID_I386) || defined(MID_M68K4K) || defined(MID_NS32532) || \ 442 defined(MID_PMAX) || defined(MID_MIPS) || defined(MID_ARM6) 443 clbytes = 4096; 444 break; 445 #endif 446 #ifdef MID_M68K 447 case MID_M68K: 448 #endif 449 #ifdef MID_ALPHA 450 case MID_ALPHA: 451 #endif 452 #ifdef MID_SPARC 453 case MID_SPARC: 454 #endif 455 #if defined(MID_M68K) || defined(MID_ALPHA) || defined(MID_SPARC) 456 clbytes = 8192; 457 break; 458 #endif 459 default: 460 clbytes = 0; 461 } 462 463 return(clbytes); 464 } 465 #endif 466 467 int 468 CheckElfFile(int fd) 469 { 470 #ifdef NOELF 471 return(-1); 472 #else 473 Elf32_Ehdr ehdr; 474 475 (void)lseek(fd, (off_t) 0, SEEK_SET); 476 477 if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) 478 return(-1); 479 480 if (ehdr.e_ident[0] != ELFMAG0 || 481 ehdr.e_ident[1] != ELFMAG1 || 482 ehdr.e_ident[2] != ELFMAG2 || 483 ehdr.e_ident[3] != ELFMAG3) 484 return(-1); 485 486 /* Must be Elf32 or Elf64... */ 487 if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 && 488 ehdr.e_ident[EI_CLASS] != ELFCLASS64) 489 return(-1); 490 491 return(0); 492 #endif /* NOELF */ 493 } 494 495 int 496 GetElf32FileInfo(struct dllist *dl, int info) 497 { 498 #ifdef NOELF 499 return(-1); 500 #else 501 Elf32_Ehdr ehdr; 502 Elf32_Phdr phdr; 503 uint32_t e_machine, e_entry; 504 uint32_t e_phoff, e_phentsize, e_phnum; 505 int ei_data, i; 506 507 (void)lseek(dl->ldfd, (off_t) 0, SEEK_SET); 508 509 if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) 510 return(-1); 511 512 if (ehdr.e_ident[0] != ELFMAG0 || 513 ehdr.e_ident[1] != ELFMAG1 || 514 ehdr.e_ident[2] != ELFMAG2 || 515 ehdr.e_ident[3] != ELFMAG3) 516 return(-1); 517 518 /* Must be Elf32... */ 519 if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) 520 return(-1); 521 522 ei_data = ehdr.e_ident[EI_DATA]; 523 524 switch (ei_data) { 525 case ELFDATA2LSB: 526 e_machine = mopFileGetLX((u_char *) &ehdr, 527 offsetof(Elf32_Ehdr, e_machine), 528 sizeof(ehdr.e_machine)); 529 e_entry = mopFileGetLX((u_char *) &ehdr, 530 offsetof(Elf32_Ehdr, e_entry), 531 sizeof(ehdr.e_entry)); 532 533 e_phoff = mopFileGetLX((u_char *) &ehdr, 534 offsetof(Elf32_Ehdr, e_phoff), 535 sizeof(ehdr.e_phoff)); 536 e_phentsize = mopFileGetLX((u_char *) &ehdr, 537 offsetof(Elf32_Ehdr, e_phentsize), 538 sizeof(ehdr.e_phentsize)); 539 e_phnum = mopFileGetLX((u_char *) &ehdr, 540 offsetof(Elf32_Ehdr, e_phnum), 541 sizeof(ehdr.e_phnum)); 542 break; 543 544 case ELFDATA2MSB: 545 e_machine = mopFileGetBX((u_char *) &ehdr, 546 offsetof(Elf32_Ehdr, e_machine), 547 sizeof(ehdr.e_machine)); 548 e_entry = mopFileGetBX((u_char *) &ehdr, 549 offsetof(Elf32_Ehdr, e_entry), 550 sizeof(ehdr.e_entry)); 551 552 e_phoff = mopFileGetBX((u_char *) &ehdr, 553 offsetof(Elf32_Ehdr, e_phoff), 554 sizeof(ehdr.e_phoff)); 555 e_phentsize = mopFileGetBX((u_char *) &ehdr, 556 offsetof(Elf32_Ehdr, e_phentsize), 557 sizeof(ehdr.e_phentsize)); 558 e_phnum = mopFileGetBX((u_char *) &ehdr, 559 offsetof(Elf32_Ehdr, e_phnum), 560 sizeof(ehdr.e_phnum)); 561 break; 562 563 default: 564 return(-1); 565 } 566 567 if (e_phnum > SEC_MAX) 568 return(-1); 569 dl->e_nsec = e_phnum; 570 for (i = 0; i < dl->e_nsec; i++) { 571 if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize), 572 SEEK_SET) == (off_t) -1) 573 return(-1); 574 if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) != 575 sizeof(phdr)) 576 return(-1); 577 578 switch (ei_data) { 579 case ELFDATA2LSB: 580 dl->e_sections[i].s_foff = 581 mopFileGetLX((u_char *) &phdr, 582 offsetof(Elf32_Phdr, p_offset), 583 sizeof(phdr.p_offset)); 584 dl->e_sections[i].s_vaddr = 585 mopFileGetLX((u_char *) &phdr, 586 offsetof(Elf32_Phdr, p_vaddr), 587 sizeof(phdr.p_vaddr)); 588 dl->e_sections[i].s_fsize = 589 mopFileGetLX((u_char *) &phdr, 590 offsetof(Elf32_Phdr, p_filesz), 591 sizeof(phdr.p_filesz)); 592 dl->e_sections[i].s_msize = 593 mopFileGetLX((u_char *) &phdr, 594 offsetof(Elf32_Phdr, p_memsz), 595 sizeof(phdr.p_memsz)); 596 break; 597 598 case ELFDATA2MSB: 599 dl->e_sections[i].s_foff = 600 mopFileGetBX((u_char *) &phdr, 601 offsetof(Elf32_Phdr, p_offset), 602 sizeof(phdr.p_offset)); 603 dl->e_sections[i].s_vaddr = 604 mopFileGetBX((u_char *) &phdr, 605 offsetof(Elf32_Phdr, p_vaddr), 606 sizeof(phdr.p_vaddr)); 607 dl->e_sections[i].s_fsize = 608 mopFileGetBX((u_char *) &phdr, 609 offsetof(Elf32_Phdr, p_filesz), 610 sizeof(phdr.p_filesz)); 611 dl->e_sections[i].s_msize = 612 mopFileGetBX((u_char *) &phdr, 613 offsetof(Elf32_Phdr, p_memsz), 614 sizeof(phdr.p_memsz)); 615 break; 616 617 default: 618 return(-1); 619 } 620 } 621 /* 622 * In addition to padding between segments, this also 623 * takes care of memsz > filesz. 624 */ 625 for (i = 0; i < dl->e_nsec - 1; i++) { 626 dl->e_sections[i].s_pad = 627 dl->e_sections[i + 1].s_vaddr - 628 (dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize); 629 } 630 dl->e_sections[dl->e_nsec - 1].s_pad = 631 dl->e_sections[dl->e_nsec - 1].s_msize - 632 dl->e_sections[dl->e_nsec - 1].s_fsize; 633 /* 634 * Now compute the logical offsets for each section. 635 */ 636 dl->e_sections[0].s_loff = 0; 637 for (i = 1; i < dl->e_nsec; i++) { 638 dl->e_sections[i].s_loff = 639 dl->e_sections[i - 1].s_loff + 640 dl->e_sections[i - 1].s_fsize + 641 dl->e_sections[i - 1].s_pad; 642 } 643 644 dl->image_type = IMAGE_TYPE_ELF32; 645 dl->loadaddr = 0; 646 #if 0 647 dl->xferaddr = e_entry; /* will relocate itself if necessary */ 648 #else 649 dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr; 650 #endif 651 652 /* Print info about the image. */ 653 if (info == INFO_PRINT) { 654 printf("Elf32 image ("); 655 switch (e_machine) { 656 #ifdef EM_VAX 657 case EM_VAX: 658 printf("VAX"); 659 break; 660 #endif 661 default: 662 printf("machine %d", e_machine); 663 break; 664 } 665 printf(")\n"); 666 printf("Transfer Address: %08x\n", dl->xferaddr); 667 printf("Program Sections: %d\n", dl->e_nsec); 668 for (i = 0; i < dl->e_nsec; i++) { 669 printf(" S%d File Size: %08x\n", i, 670 dl->e_sections[i].s_fsize); 671 printf(" S%d Pad Size: %08x\n", i, 672 dl->e_sections[i].s_pad); 673 } 674 } 675 676 dl->e_machine = e_machine; 677 678 dl->e_curpos = 0; 679 dl->e_cursec = 0; 680 681 return(0); 682 #endif /* NOELF */ 683 } 684 685 int 686 GetElf64FileInfo(struct dllist *dl, int info) 687 { 688 #if defined(NOELF) || defined(NOELF64) 689 return(-1); 690 #else 691 Elf64_Ehdr ehdr; 692 Elf64_Phdr phdr; 693 uint32_t e_machine; 694 uint32_t e_phentsize, e_phnum; 695 uint64_t e_entry, e_phoff; 696 int ei_data, i; 697 698 (void)lseek(dl->ldfd, (off_t) 0, SEEK_SET); 699 700 if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) 701 return(-1); 702 703 if (ehdr.e_ident[0] != ELFMAG0 || 704 ehdr.e_ident[1] != ELFMAG1 || 705 ehdr.e_ident[2] != ELFMAG2 || 706 ehdr.e_ident[3] != ELFMAG3) 707 return(-1); 708 709 /* Must be Elf64... */ 710 if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) 711 return(-1); 712 713 ei_data = ehdr.e_ident[EI_DATA]; 714 715 switch (ei_data) { 716 case ELFDATA2LSB: 717 e_machine = mopFileGetLX((u_char *) &ehdr, 718 offsetof(Elf64_Ehdr, e_machine), 719 sizeof(ehdr.e_machine)); 720 e_entry = mopFileGetLXX((u_char *) &ehdr, 721 offsetof(Elf64_Ehdr, e_entry), 722 sizeof(ehdr.e_entry)); 723 724 e_phoff = mopFileGetLXX((u_char *) &ehdr, 725 offsetof(Elf64_Ehdr, e_phoff), 726 sizeof(ehdr.e_phoff)); 727 e_phentsize = mopFileGetLX((u_char *) &ehdr, 728 offsetof(Elf64_Ehdr, e_phentsize), 729 sizeof(ehdr.e_phentsize)); 730 e_phnum = mopFileGetLX((u_char *) &ehdr, 731 offsetof(Elf64_Ehdr, e_phnum), 732 sizeof(ehdr.e_phnum)); 733 break; 734 735 case ELFDATA2MSB: 736 e_machine = mopFileGetBX((u_char *) &ehdr, 737 offsetof(Elf64_Ehdr, e_machine), 738 sizeof(ehdr.e_machine)); 739 e_entry = mopFileGetBXX((u_char *) &ehdr, 740 offsetof(Elf64_Ehdr, e_entry), 741 sizeof(ehdr.e_entry)); 742 743 e_phoff = mopFileGetBXX((u_char *) &ehdr, 744 offsetof(Elf64_Ehdr, e_phoff), 745 sizeof(ehdr.e_phoff)); 746 e_phentsize = mopFileGetBX((u_char *) &ehdr, 747 offsetof(Elf64_Ehdr, e_phentsize), 748 sizeof(ehdr.e_phentsize)); 749 e_phnum = mopFileGetBX((u_char *) &ehdr, 750 offsetof(Elf64_Ehdr, e_phnum), 751 sizeof(ehdr.e_phnum)); 752 break; 753 754 default: 755 return(-1); 756 } 757 758 if (e_phnum > SEC_MAX) 759 return(-1); 760 dl->e_nsec = e_phnum; 761 for (i = 0; i < dl->e_nsec; i++) { 762 if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize), 763 SEEK_SET) == (off_t) -1) 764 return(-1); 765 if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) != 766 sizeof(phdr)) 767 return(-1); 768 769 switch (ei_data) { 770 case ELFDATA2LSB: 771 dl->e_sections[i].s_foff = 772 mopFileGetLX((u_char *) &phdr, 773 offsetof(Elf64_Phdr, p_offset), 774 sizeof(phdr.p_offset)); 775 dl->e_sections[i].s_vaddr = 776 mopFileGetLX((u_char *) &phdr, 777 offsetof(Elf64_Phdr, p_vaddr), 778 sizeof(phdr.p_vaddr)); 779 dl->e_sections[i].s_fsize = 780 mopFileGetLX((u_char *) &phdr, 781 offsetof(Elf64_Phdr, p_filesz), 782 sizeof(phdr.p_filesz)); 783 dl->e_sections[i].s_msize = 784 mopFileGetLX((u_char *) &phdr, 785 offsetof(Elf64_Phdr, p_memsz), 786 sizeof(phdr.p_memsz)); 787 break; 788 789 case ELFDATA2MSB: 790 dl->e_sections[i].s_foff = 791 mopFileGetBX((u_char *) &phdr, 792 offsetof(Elf64_Phdr, p_offset), 793 sizeof(phdr.p_offset)); 794 dl->e_sections[i].s_vaddr = 795 mopFileGetBX((u_char *) &phdr, 796 offsetof(Elf64_Phdr, p_vaddr), 797 sizeof(phdr.p_vaddr)); 798 dl->e_sections[i].s_fsize = 799 mopFileGetBX((u_char *) &phdr, 800 offsetof(Elf64_Phdr, p_filesz), 801 sizeof(phdr.p_filesz)); 802 dl->e_sections[i].s_msize = 803 mopFileGetBX((u_char *) &phdr, 804 offsetof(Elf64_Phdr, p_memsz), 805 sizeof(phdr.p_memsz)); 806 break; 807 808 default: 809 return(-1); 810 } 811 } 812 /* 813 * In addition to padding between segments, this also 814 * takes care of memsz > filesz. 815 */ 816 for (i = 0; i < dl->e_nsec - 1; i++) { 817 dl->e_sections[i].s_pad = 818 dl->e_sections[i + 1].s_vaddr - 819 (dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize); 820 } 821 dl->e_sections[dl->e_nsec - 1].s_pad = 822 dl->e_sections[dl->e_nsec - 1].s_msize - 823 dl->e_sections[dl->e_nsec - 1].s_fsize; 824 /* 825 * Now compute the logical offsets for each section. 826 */ 827 dl->e_sections[0].s_loff = 0; 828 for (i = 1; i < dl->e_nsec; i++) { 829 dl->e_sections[i].s_loff = 830 dl->e_sections[i - 1].s_loff + 831 dl->e_sections[i - 1].s_fsize + 832 dl->e_sections[i - 1].s_pad; 833 } 834 835 dl->image_type = IMAGE_TYPE_ELF64; 836 dl->loadaddr = 0; 837 #if 0 838 dl->xferaddr = e_entry; /* will relocate itself if necessary */ 839 #else 840 dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr; 841 #endif 842 843 /* Print info about the image. */ 844 if (info == INFO_PRINT) { 845 printf("Elf64 image ("); 846 switch (e_machine) { 847 #ifdef EM_ALPHA 848 case EM_ALPHA: 849 #endif 850 #ifdef EM_ALPHA_EXP 851 case EM_ALPHA_EXP: 852 #endif 853 #if defined(EM_ALPHA) || defined(EM_ALPHA_EXP) 854 printf("ALPHA"); 855 break; 856 #endif 857 default: 858 printf("machine %d", e_machine); 859 break; 860 } 861 printf(")\n"); 862 printf("Transfer Address: %08x\n", dl->xferaddr); 863 printf("Program Sections: %d\n", dl->e_nsec); 864 for (i = 0; i < dl->e_nsec; i++) { 865 printf(" S%d File Size: %08x\n", i, 866 dl->e_sections[i].s_fsize); 867 printf(" S%d Pad Size: %08x\n", i, 868 dl->e_sections[i].s_pad); 869 } 870 } 871 872 dl->e_machine = e_machine; 873 874 dl->e_curpos = 0; 875 dl->e_cursec = 0; 876 877 return(0); 878 #endif /* NOELF || NOELF64 */ 879 } 880 881 int 882 CheckAOutFile(int fd) 883 { 884 #ifdef NOAOUT 885 return(-1); 886 #else 887 struct exec ex, ex_swap; 888 int mid = -1; 889 890 if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex)) 891 return(-1); 892 893 (void)lseek(fd, (off_t) 0, SEEK_SET); 894 895 if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap)) 896 return(-1); 897 898 (void)lseek(fd, (off_t) 0, SEEK_SET); 899 900 mid = getMID(mid, N_GETMID (ex)); 901 902 if (mid == -1) { 903 mid = getMID(mid, N_GETMID (ex_swap)); 904 } 905 906 if (mid != -1) { 907 return(0); 908 } else { 909 return(-1); 910 } 911 #endif /* NOAOUT */ 912 } 913 914 int 915 GetAOutFileInfo(struct dllist *dl, int info) 916 { 917 #ifdef NOAOUT 918 return(-1); 919 #else 920 struct exec ex, ex_swap; 921 u_int32_t mid = -1; 922 u_int32_t magic, clbytes, clofset; 923 924 if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex)) 925 return(-1); 926 927 (void)lseek(dl->ldfd, (off_t) 0, SEEK_SET); 928 929 if (read(dl->ldfd, (char *)&ex_swap, 930 sizeof(ex_swap)) != sizeof(ex_swap)) 931 return(-1); 932 933 mopFileSwapX((u_char *)&ex_swap, 0, 4); 934 935 mid = getMID(mid, N_GETMID (ex)); 936 937 if (mid == (uint32_t)-1) { 938 mid = getMID(mid, N_GETMID (ex_swap)); 939 if (mid != (uint32_t)-1) { 940 mopFileSwapX((u_char *)&ex, 0, 4); 941 } 942 } 943 944 if (mid == (uint32_t)-1) { 945 return(-1); 946 } 947 948 if (N_BADMAG (ex)) { 949 return(-1); 950 } 951 952 switch (mid) { 953 case MID_I386: 954 #ifdef MID_NS32532 955 case MID_NS32532: 956 #endif 957 #ifdef MID_PMAX 958 case MID_PMAX: 959 #endif 960 #ifdef MID_VAX 961 case MID_VAX: 962 #endif 963 #ifdef MID_ALPHA 964 case MID_ALPHA: 965 #endif 966 #ifdef MID_ARM6 967 case MID_ARM6: 968 #endif 969 ex.a_text = mopFileGetLX((u_char *)&ex_swap, 4, 4); 970 ex.a_data = mopFileGetLX((u_char *)&ex_swap, 8, 4); 971 ex.a_bss = mopFileGetLX((u_char *)&ex_swap, 12, 4); 972 ex.a_syms = mopFileGetLX((u_char *)&ex_swap, 16, 4); 973 ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4); 974 ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4); 975 ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4); 976 break; 977 #ifdef MID_M68K 978 case MID_M68K: 979 #endif 980 #ifdef MID_M68K4K 981 case MID_M68K4K: 982 #endif 983 case MID_SPARC: 984 #ifdef MID_MIPS 985 case MID_MIPS: 986 #endif 987 ex.a_text = mopFileGetBX((u_char *)&ex_swap, 4, 4); 988 ex.a_data = mopFileGetBX((u_char *)&ex_swap, 8, 4); 989 ex.a_bss = mopFileGetBX((u_char *)&ex_swap, 12, 4); 990 ex.a_syms = mopFileGetBX((u_char *)&ex_swap, 16, 4); 991 ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4); 992 ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4); 993 ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4); 994 break; 995 default: 996 break; 997 } 998 999 if (info == INFO_PRINT) { 1000 printf("a.out image ("); 1001 switch (N_GETMID (ex)) { 1002 case MID_I386: 1003 printf("i386"); 1004 break; 1005 #ifdef MID_M68K 1006 case MID_M68K: 1007 printf("m68k"); 1008 break; 1009 #endif 1010 #ifdef MID_M68K4K 1011 case MID_M68K4K: 1012 printf("m68k 4k"); 1013 break; 1014 #endif 1015 #ifdef MID_NS32532 1016 case MID_NS32532: 1017 printf("pc532"); 1018 break; 1019 #endif 1020 case MID_SPARC: 1021 printf("sparc"); 1022 break; 1023 #ifdef MID_PMAX 1024 case MID_PMAX: 1025 printf("pmax"); 1026 break; 1027 #endif 1028 #ifdef MID_VAX 1029 case MID_VAX: 1030 printf("vax"); 1031 break; 1032 #endif 1033 #ifdef MID_ALPHA 1034 case MID_ALPHA: 1035 printf("alpha"); 1036 break; 1037 #endif 1038 #ifdef MID_MIPS 1039 case MID_MIPS: 1040 printf("mips"); 1041 break; 1042 #endif 1043 #ifdef MID_ARM6 1044 case MID_ARM6: 1045 printf("arm32"); 1046 break; 1047 #endif 1048 default: 1049 break; 1050 } 1051 printf(") Magic: "); 1052 switch (N_GETMAGIC (ex)) { 1053 case OMAGIC: 1054 printf("OMAGIC"); 1055 break; 1056 case NMAGIC: 1057 printf("NMAGIC"); 1058 break; 1059 case ZMAGIC: 1060 printf("ZMAGIC"); 1061 break; 1062 case QMAGIC: 1063 printf("QMAGIC"); 1064 break; 1065 default: 1066 printf("Unknown %ld", (long) N_GETMAGIC (ex)); 1067 } 1068 printf("\n"); 1069 printf("Size of text: %08lx\n", (long)ex.a_text); 1070 printf("Size of data: %08lx\n", (long)ex.a_data); 1071 printf("Size of bss: %08lx\n", (long)ex.a_bss); 1072 printf("Size of symbol tab: %08lx\n", (long)ex.a_syms); 1073 printf("Transfer Address: %08lx\n", (long)ex.a_entry); 1074 printf("Size of reloc text: %08lx\n", (long)ex.a_trsize); 1075 printf("Size of reloc data: %08lx\n", (long)ex.a_drsize); 1076 } 1077 1078 magic = N_GETMAGIC (ex); 1079 clbytes = getCLBYTES(mid); 1080 clofset = clbytes - 1; 1081 1082 dl->image_type = IMAGE_TYPE_AOUT; 1083 dl->loadaddr = 0; 1084 dl->xferaddr = ex.a_entry; 1085 1086 dl->a_text = ex.a_text; 1087 if (magic == ZMAGIC || magic == NMAGIC) { 1088 dl->a_text_fill = clbytes - (ex.a_text & clofset); 1089 if (dl->a_text_fill == clbytes) 1090 dl->a_text_fill = 0; 1091 } else 1092 dl->a_text_fill = 0; 1093 dl->a_data = ex.a_data; 1094 if (magic == ZMAGIC || magic == NMAGIC) { 1095 dl->a_data_fill = clbytes - (ex.a_data & clofset); 1096 if (dl->a_data_fill == clbytes) 1097 dl->a_data_fill = 0; 1098 } else 1099 dl->a_data_fill = 0; 1100 dl->a_bss = ex.a_bss; 1101 if (magic == ZMAGIC || magic == NMAGIC) { 1102 dl->a_bss_fill = clbytes - (ex.a_bss & clofset); 1103 if (dl->a_bss_fill == clbytes) 1104 dl->a_bss_fill = 0; 1105 } else { 1106 dl->a_bss_fill = clbytes - 1107 ((ex.a_text+ex.a_data+ex.a_bss) & clofset); 1108 if (dl->a_bss_fill == clbytes) 1109 dl->a_bss_fill = 0; 1110 } 1111 dl->a_mid = mid; 1112 1113 return(0); 1114 #endif /* NOAOUT */ 1115 } 1116 1117 int 1118 GetFileInfo(struct dllist *dl, int info) 1119 { 1120 int error; 1121 1122 error = CheckElfFile(dl->ldfd); 1123 if (error == 0) { 1124 error = GetElf32FileInfo(dl, info); 1125 if (error != 0) 1126 error = GetElf64FileInfo(dl, info); 1127 if (error != 0) { 1128 return(-1); 1129 } 1130 return (0); 1131 } 1132 1133 error = CheckAOutFile(dl->ldfd); 1134 if (error == 0) { 1135 error = GetAOutFileInfo(dl, info); 1136 if (error != 0) { 1137 return(-1); 1138 } 1139 return (0); 1140 } 1141 1142 error = CheckMopFile(dl->ldfd); 1143 if (error == 0) { 1144 error = GetMopFileInfo(dl, info); 1145 if (error != 0) { 1146 return(-1); 1147 } 1148 return (0); 1149 } 1150 1151 /* Unknown file format. */ 1152 return(-1); 1153 } 1154 1155 ssize_t 1156 mopFileRead(struct dllist *dlslot, u_char *buf) 1157 { 1158 ssize_t len, outlen; 1159 int bsz, sec; 1160 int32_t pos, notdone, total; 1161 uint32_t secoff; 1162 1163 switch (dlslot->image_type) { 1164 case IMAGE_TYPE_MOP: 1165 len = read(dlslot->ldfd,buf,dlslot->dl_bsz); 1166 break; 1167 1168 case IMAGE_TYPE_ELF32: 1169 case IMAGE_TYPE_ELF64: 1170 sec = dlslot->e_cursec; 1171 1172 /* 1173 * We're pretty simplistic here. We do only file-backed 1174 * or only zero-fill. 1175 */ 1176 1177 /* Determine offset into section. */ 1178 secoff = dlslot->e_curpos - dlslot->e_sections[sec].s_loff; 1179 1180 /* 1181 * If we're in the file-backed part of the section, 1182 * transmit some of the file. 1183 */ 1184 if (secoff < dlslot->e_sections[sec].s_fsize) { 1185 bsz = dlslot->e_sections[sec].s_fsize - secoff; 1186 if (bsz > dlslot->dl_bsz) 1187 bsz = dlslot->dl_bsz; 1188 if (lseek(dlslot->ldfd, 1189 dlslot->e_sections[sec].s_foff + secoff, 1190 SEEK_SET) == (off_t) -1) 1191 return (-1); 1192 len = read(dlslot->ldfd, buf, bsz); 1193 } 1194 /* 1195 * Otherwise, if we're in the zero-fill part of the 1196 * section, transmit some zeros. 1197 */ 1198 else if (secoff < (dlslot->e_sections[sec].s_fsize + 1199 dlslot->e_sections[sec].s_pad)) { 1200 bsz = dlslot->e_sections[sec].s_pad - 1201 (secoff - dlslot->e_sections[sec].s_fsize); 1202 if (bsz > dlslot->dl_bsz) 1203 bsz = dlslot->dl_bsz; 1204 memset(buf, 0, (len = bsz)); 1205 } 1206 /* 1207 * ...and if we haven't hit either of those cases, 1208 * that's the end of the image. 1209 */ 1210 else { 1211 return (0); 1212 } 1213 /* 1214 * Advance the logical image pointer. 1215 */ 1216 dlslot->e_curpos += bsz; 1217 if (dlslot->e_curpos >= (dlslot->e_sections[sec].s_loff + 1218 dlslot->e_sections[sec].s_fsize + 1219 dlslot->e_sections[sec].s_pad)) 1220 if (++sec != dlslot->e_nsec) 1221 dlslot->e_cursec = sec; 1222 break; 1223 1224 case IMAGE_TYPE_AOUT: 1225 bsz = dlslot->dl_bsz; 1226 pos = dlslot->a_lseek; 1227 len = 0; 1228 1229 total = dlslot->a_text; 1230 1231 if (pos < total) { 1232 notdone = total - pos; 1233 if (notdone <= bsz) { 1234 outlen = read(dlslot->ldfd,&buf[len],notdone); 1235 } else { 1236 outlen = read(dlslot->ldfd,&buf[len],bsz); 1237 } 1238 len = len + outlen; 1239 pos = pos + outlen; 1240 bsz = bsz - outlen; 1241 } 1242 1243 total = total + dlslot->a_text_fill; 1244 1245 if ((bsz > 0) && (pos < total)) { 1246 notdone = total - pos; 1247 if (notdone <= bsz) { 1248 outlen = notdone; 1249 } else { 1250 outlen = bsz; 1251 } 1252 memset(&buf[len], 0, outlen); 1253 len = len + outlen; 1254 pos = pos + outlen; 1255 bsz = bsz - outlen; 1256 } 1257 1258 total = total + dlslot->a_data; 1259 1260 if ((bsz > 0) && (pos < total)) { 1261 notdone = total - pos; 1262 if (notdone <= bsz) { 1263 outlen = read(dlslot->ldfd,&buf[len],notdone); 1264 } else { 1265 outlen = read(dlslot->ldfd,&buf[len],bsz); 1266 } 1267 len = len + outlen; 1268 pos = pos + outlen; 1269 bsz = bsz - outlen; 1270 } 1271 1272 total = total + dlslot->a_data_fill; 1273 1274 if ((bsz > 0) && (pos < total)) { 1275 notdone = total - pos; 1276 if (notdone <= bsz) { 1277 outlen = notdone; 1278 } else { 1279 outlen = bsz; 1280 } 1281 memset(&buf[len], 0, outlen); 1282 len = len + outlen; 1283 pos = pos + outlen; 1284 bsz = bsz - outlen; 1285 } 1286 1287 total = total + dlslot->a_bss; 1288 1289 if ((bsz > 0) && (pos < total)) { 1290 notdone = total - pos; 1291 if (notdone <= bsz) { 1292 outlen = notdone; 1293 } else { 1294 outlen = bsz; 1295 } 1296 memset(&buf[len], 0, outlen); 1297 len = len + outlen; 1298 pos = pos + outlen; 1299 bsz = bsz - outlen; 1300 } 1301 1302 total = total + dlslot->a_bss_fill; 1303 1304 if ((bsz > 0) && (pos < total)) { 1305 notdone = total - pos; 1306 if (notdone <= bsz) { 1307 outlen = notdone; 1308 } else { 1309 outlen = bsz; 1310 } 1311 memset(&buf[len], 0, outlen); 1312 len = len + outlen; 1313 pos = pos + outlen; 1314 bsz = bsz - outlen; 1315 } 1316 1317 dlslot->a_lseek = pos; 1318 break; 1319 1320 default: 1321 abort(); 1322 } 1323 1324 return(len); 1325 } 1326