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