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