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