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