1/*	$NetBSD: file.c,v 1.14 2011/08/30 19:49:10 joerg 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.14 2011/08/30 19:49:10 joerg 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
62static int	getCLBYTES(int);
63static int	getMID(int, int);
64#endif
65
66const char *
67FileTypeName(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
84void
85mopFilePutLX(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
94void
95mopFilePutBX(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
104u_int32_t
105mopFileGetLX(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
120u_int32_t
121mopFileGetBX(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
136void
137mopFileSwapX(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
150int
151CheckMopFile(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
180int
181GetMopFileInfo(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
292static int
293getMID(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
353static int
354getCLBYTES(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
408int
409CheckElfFile(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
435int
436GetElfFileInfo(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
618int
619CheckAOutFile(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
651int
652GetAOutFileInfo(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
852int
853GetFileInfo(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
888ssize_t
889mopFileRead(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