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