xref: /openbsd/usr.sbin/mopd/common/file.c (revision d415bd75)
1 /*	$OpenBSD: file.c,v 1.19 2017/10/29 08:45:53 mpi Exp $ */
2 
3 /*
4  * Copyright (c) 1995-96 Mats O Jansson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "os.h"
28 #include "common.h"
29 #include "file.h"
30 #include "mopdef.h"
31 #include <stddef.h>
32 
33 #ifndef NOAOUT
34 #if defined(__OpenBSD__)
35 #include <sys/exec.h>
36 #endif
37 #if defined(__bsdi__)
38 #define NOAOUT
39 #endif
40 #if defined(__FreeBSD__)
41 #include <sys/imgact_aout.h>
42 #endif
43 #if !defined(MID_I386)
44 #define MID_I386 134
45 #endif
46 #if !defined(MID_SPARC)
47 #define MID_SPARC 138
48 #endif
49 #if !defined(MID_VAX)
50 #define MID_VAX 140
51 #endif
52 #endif
53 
54 #ifndef NOELF
55 #if defined(__OpenBSD__)
56 #include <elf.h>
57 #else
58 #define NOELF
59 #endif
60 #endif
61 
62 #ifndef NOELF
63 #if !defined(_LP64)
64 #define NOELF64
65 #endif
66 #endif
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_ELF64:
85 		return ("Elf64");
86 
87 	case IMAGE_TYPE_AOUT:
88 		return ("a.out");
89 	}
90 
91 	abort();
92 }
93 
94 void
95 mopFilePutLX(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+i] = value % 256;
100 		value = value / 256;
101 	}
102 }
103 
104 void
105 mopFilePutBX(u_char *buf, int idx, u_int32_t value, int cnt)
106 {
107 	int i;
108 	for (i = 0; i < cnt; i++) {
109 		buf[idx+cnt-1-i] = value % 256;
110 		value = value / 256;
111 	}
112 }
113 
114 u_int32_t
115 mopFileGetLX(u_char *buf, int idx, int cnt)
116 {
117 	u_int32_t ret = 0;
118 	int i;
119 
120 	for (i = 0; i < cnt; i++) {
121 		int j = idx + cnt - 1 - i;
122 		if (j < 0)
123 			abort();
124 		ret = ret * 256 + buf[j];
125 	}
126 
127 	return(ret);
128 }
129 
130 u_int32_t
131 mopFileGetBX(u_char *buf, int idx, int cnt)
132 {
133 	u_int32_t ret = 0;
134 	int i;
135 
136 	for (i = 0; i < cnt; i++) {
137 		int j = idx + i;
138 		if (j < 0)
139 			abort();
140 		ret = ret * 256 + buf[j];
141 	}
142 
143 	return(ret);
144 }
145 
146 #if !defined(NOELF) && !defined(NOELF64)
147 u_int64_t
148 mopFileGetLXX(u_char *buf, int idx, int cnt)
149 {
150 	u_int64_t ret = 0;
151 	int i;
152 
153 	for (i = 0; i < cnt; i++) {
154 		int j = idx + cnt - 1 - i;
155 		if (j < 0)
156 			abort();
157 		ret = ret * 256 + buf[j];
158 	}
159 
160 	return(ret);
161 }
162 
163 u_int64_t
164 mopFileGetBXX(u_char *buf, int idx, int cnt)
165 {
166 	u_int64_t ret = 0;
167 	int i;
168 
169 	for (i = 0; i < cnt; i++) {
170 		int j = idx + i;
171 		if (j < 0)
172 			abort();
173 		ret = ret * 256 + buf[j];
174 	}
175 
176 	return(ret);
177 }
178 #endif
179 
180 void
181 mopFileSwapX(u_char *buf, int idx, int cnt)
182 {
183 	int i;
184 	u_char c;
185 
186 	for (i = 0; i < (cnt / 2); i++) {
187 		c = buf[idx+i];
188 		buf[idx+i] = buf[idx+cnt-1-i];
189 		buf[idx+cnt-1-i] = c;
190 	}
191 
192 }
193 
194 int
195 CheckMopFile(int fd)
196 {
197 	u_char	header[512];
198 	short	image_type;
199 
200 	if (read(fd, header, 512) != 512)
201 		return(-1);
202 
203 	(void)lseek(fd, (off_t) 0, SEEK_SET);
204 
205 	image_type = (u_short)(header[IHD_W_ALIAS+1]*256 + header[IHD_W_ALIAS]);
206 
207 	switch(image_type) {
208 	case IHD_C_NATIVE:		/* Native mode image (VAX)   */
209 	case IHD_C_RSX:			/* RSX image produced by TKB */
210 	case IHD_C_BPA:			/* BASIC plus analog         */
211 	case IHD_C_ALIAS:		/* Alias		     */
212 	case IHD_C_CLI:			/* Image is CLI		     */
213 	case IHD_C_PMAX:		/* PMAX system image	     */
214 	case IHD_C_ALPHA:		/* ALPHA system image	     */
215 		break;
216 	default:
217 		return(-1);
218 	}
219 
220 	return(0);
221 }
222 
223 int
224 GetMopFileInfo(struct dllist *dl, int info)
225 {
226 	u_char		header[512];
227 	short		image_type;
228 	u_int32_t	load_addr, xfr_addr, isd, iha, hbcnt, isize;
229 
230 	if (read(dl->ldfd, header, 512) != 512)
231 		return(-1);
232 
233 	image_type = (u_short)(header[IHD_W_ALIAS+1]*256 +
234 			       header[IHD_W_ALIAS]);
235 
236 	switch (image_type) {
237 	case IHD_C_NATIVE:		/* Native mode image (VAX)   */
238 		isd = (header[IHD_W_SIZE+1]*256 +
239 		       header[IHD_W_SIZE]);
240 		iha = (header[IHD_W_ACTIVOFF+1]*256 +
241 		       header[IHD_W_ACTIVOFF]);
242 		hbcnt = (header[IHD_B_HDRBLKCNT]);
243 		isize = (header[isd+ISD_W_PAGCNT+1]*256 +
244 			 header[isd+ISD_W_PAGCNT]) * 512;
245 		load_addr = ((header[isd+ISD_V_VPN+1]*256 +
246 			      header[isd+ISD_V_VPN]) & ISD_M_VPN)
247 				* 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]) & 0x7fffffff;
252 		if (info == INFO_PRINT) {
253 			printf("Native Image (VAX)\n");
254 			printf("Header Block Count: %d\n",hbcnt);
255 			printf("Image Size:         %08x\n",isize);
256 			printf("Load Address:       %08x\n",load_addr);
257 			printf("Transfer Address:   %08x\n",xfr_addr);
258 		}
259 		break;
260 	case IHD_C_RSX:			/* RSX image produced by TKB */
261 		hbcnt = header[L_BBLK+1]*256 + header[L_BBLK];
262 		isize = (header[L_BLDZ+1]*256 + header[L_BLDZ]) * 64;
263 		load_addr = header[L_BSA+1]*256 + header[L_BSA];
264 		xfr_addr  = header[L_BXFR+1]*256 + header[L_BXFR];
265 		if (info == INFO_PRINT) {
266 			printf("RSX Image\n");
267 			printf("Header Block Count: %d\n",hbcnt);
268 			printf("Image Size:         %08x\n",isize);
269 			printf("Load Address:       %08x\n",load_addr);
270 			printf("Transfer Address:   %08x\n",xfr_addr);
271 		}
272 		break;
273 	case IHD_C_BPA:			/* BASIC plus analog         */
274 		if (info == INFO_PRINT) {
275 			printf("BASIC-Plus Image, not supported\n");
276 		}
277 		return(-1);
278 		break;
279 	case IHD_C_ALIAS:		/* Alias		     */
280 		if (info == INFO_PRINT) {
281 			printf("Alias, not supported\n");
282 		}
283 		return(-1);
284 		break;
285 	case IHD_C_CLI:			/* Image is CLI		     */
286 		if (info == INFO_PRINT) {
287 			printf("CLI, not supported\n");
288 		}
289 		return(-1);
290 		break;
291 	case IHD_C_PMAX:		/* PMAX system image	     */
292 		isd = (header[IHD_W_SIZE+1]*256 +
293 		       header[IHD_W_SIZE]);
294 		iha = (header[IHD_W_ACTIVOFF+1]*256 +
295 		       header[IHD_W_ACTIVOFF]);
296 		hbcnt = (header[IHD_B_HDRBLKCNT]);
297 		isize = (header[isd+ISD_W_PAGCNT+1]*256 +
298 			 header[isd+ISD_W_PAGCNT]) * 512;
299 		load_addr = (header[isd+ISD_V_VPN+1]*256 +
300 			     header[isd+ISD_V_VPN]) * 512;
301 		xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 +
302 			    header[iha+IHA_L_TFRADR1+2]*0x10000 +
303 			    header[iha+IHA_L_TFRADR1+1]*0x100 +
304 			    header[iha+IHA_L_TFRADR1]);
305 		if (info == INFO_PRINT) {
306 			printf("PMAX Image \n");
307 			printf("Header Block Count: %d\n",hbcnt);
308 			printf("Image Size:         %08x\n",isize);
309 			printf("Load Address:       %08x\n",load_addr);
310 			printf("Transfer Address:   %08x\n",xfr_addr);
311 		}
312 		break;
313 	case IHD_C_ALPHA:		/* ALPHA system image	     */
314 		isd = (header[EIHD_L_ISDOFF+3]*0x1000000 +
315 		       header[EIHD_L_ISDOFF+2]*0x10000 +
316 		       header[EIHD_L_ISDOFF+1]*0x100 +
317 		       header[EIHD_L_ISDOFF]);
318 		hbcnt = (header[EIHD_L_HDRBLKCNT+3]*0x1000000 +
319 			 header[EIHD_L_HDRBLKCNT+2]*0x10000 +
320 			 header[EIHD_L_HDRBLKCNT+1]*0x100 +
321 			 header[EIHD_L_HDRBLKCNT]);
322 		isize = (header[isd+EISD_L_SECSIZE+3]*0x1000000 +
323 			 header[isd+EISD_L_SECSIZE+2]*0x10000 +
324 			 header[isd+EISD_L_SECSIZE+1]*0x100 +
325 			 header[isd+EISD_L_SECSIZE]);
326 		load_addr = 0;
327 		xfr_addr = 0;
328 		if (info == INFO_PRINT) {
329 			printf("Alpha Image \n");
330 			printf("Header Block Count: %d\n",hbcnt);
331 			printf("Image Size:         %08x\n",isize);
332 			printf("Load Address:       %08x\n",load_addr);
333 			printf("Transfer Address:   %08x\n",xfr_addr);
334 		}
335 		break;
336 	default:
337 		if (info == INFO_PRINT) {
338 			printf("Unknown Image (%d)\n",image_type);
339 		}
340 		return(-1);
341 	}
342 
343 	dl->image_type = IMAGE_TYPE_MOP;
344 	dl->loadaddr = load_addr;
345 	dl->xferaddr = xfr_addr;
346 
347 	return(0);
348 }
349 
350 #ifndef NOAOUT
351 static int
352 getMID(int old_mid, int new_mid)
353 {
354 	int	mid;
355 
356 	mid = old_mid;
357 
358 	switch (new_mid) {
359 	case MID_I386:
360 		mid = MID_I386;
361 		break;
362 #ifdef MID_M68K
363 	case MID_M68K:
364 		mid = MID_M68K;
365 		break;
366 #endif
367 #ifdef MID_M68K4K
368 	case MID_M68K4K:
369 		mid = MID_M68K4K;
370 		break;
371 #endif
372 #ifdef MID_NS32532
373 	case MID_NS32532:
374 		mid = MID_NS32532;
375 		break;
376 #endif
377 	case MID_SPARC:
378 		mid = MID_SPARC;
379 		break;
380 #ifdef MID_PMAX
381 	case MID_PMAX:
382 		mid = MID_PMAX;
383 		break;
384 #endif
385 #ifdef MID_VAX
386 	case MID_VAX:
387 		mid = MID_VAX;
388 		break;
389 #endif
390 #ifdef MID_ALPHA
391 	case MID_ALPHA:
392 		mid = MID_ALPHA;
393 		break;
394 #endif
395 #ifdef MID_MIPS
396 	case MID_MIPS:
397 		mid = MID_MIPS;
398 		break;
399 #endif
400 #ifdef MID_ARM6
401 	case MID_ARM6:
402 		mid = MID_ARM6;
403 		break;
404 #endif
405 	default:
406 		break;
407 	}
408 
409 	return(mid);
410 }
411 
412 static int
413 getCLBYTES(int mid)
414 {
415 	int	clbytes;
416 
417 	switch (mid) {
418 #ifdef MID_VAX
419 	case MID_VAX:
420 		clbytes = 1024;
421 		break;
422 #endif
423 #ifdef MID_I386
424 	case MID_I386:
425 #endif
426 #ifdef MID_M68K4K
427 	case MID_M68K4K:
428 #endif
429 #ifdef MID_NS32532
430 	case MID_NS32532:
431 #endif
432 #ifdef MID_PMAX
433 	case MID_PMAX:
434 #endif
435 #ifdef MID_MIPS
436 	case MID_MIPS:
437 #endif
438 #ifdef MID_ARM6
439 	case MID_ARM6:
440 #endif
441 #if defined(MID_I386) || defined(MID_M68K4K) || defined(MID_NS32532) || \
442     defined(MID_PMAX) || defined(MID_MIPS) || defined(MID_ARM6)
443 		clbytes = 4096;
444 		break;
445 #endif
446 #ifdef MID_M68K
447 	case MID_M68K:
448 #endif
449 #ifdef MID_ALPHA
450 	case MID_ALPHA:
451 #endif
452 #ifdef MID_SPARC
453 	case MID_SPARC:
454 #endif
455 #if defined(MID_M68K) || defined(MID_ALPHA) || defined(MID_SPARC)
456 		clbytes = 8192;
457 		break;
458 #endif
459 	default:
460 		clbytes = 0;
461 	}
462 
463 	return(clbytes);
464 }
465 #endif
466 
467 int
468 CheckElfFile(int fd)
469 {
470 #ifdef NOELF
471 	return(-1);
472 #else
473 	Elf32_Ehdr ehdr;
474 
475 	(void)lseek(fd, (off_t) 0, SEEK_SET);
476 
477 	if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
478 		return(-1);
479 
480 	if (ehdr.e_ident[0] != ELFMAG0 ||
481 	    ehdr.e_ident[1] != ELFMAG1 ||
482 	    ehdr.e_ident[2] != ELFMAG2 ||
483 	    ehdr.e_ident[3] != ELFMAG3)
484 		return(-1);
485 
486 	/* Must be Elf32 or Elf64... */
487 	if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 &&
488 	    ehdr.e_ident[EI_CLASS] != ELFCLASS64)
489 		return(-1);
490 
491 	return(0);
492 #endif /* NOELF */
493 }
494 
495 int
496 GetElf32FileInfo(struct dllist *dl, int info)
497 {
498 #ifdef NOELF
499 	return(-1);
500 #else
501 	Elf32_Ehdr ehdr;
502 	Elf32_Phdr phdr;
503 	uint32_t e_machine, e_entry;
504 	uint32_t e_phoff, e_phentsize, e_phnum;
505 	int ei_data, i;
506 
507 	(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
508 
509 	if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
510 		return(-1);
511 
512 	if (ehdr.e_ident[0] != ELFMAG0 ||
513 	    ehdr.e_ident[1] != ELFMAG1 ||
514 	    ehdr.e_ident[2] != ELFMAG2 ||
515 	    ehdr.e_ident[3] != ELFMAG3)
516 		return(-1);
517 
518 	/* Must be Elf32... */
519 	if (ehdr.e_ident[EI_CLASS] != ELFCLASS32)
520 		return(-1);
521 
522 	ei_data = ehdr.e_ident[EI_DATA];
523 
524 	switch (ei_data) {
525 	case ELFDATA2LSB:
526 		e_machine = mopFileGetLX((u_char *) &ehdr,
527 		    offsetof(Elf32_Ehdr, e_machine),
528 		    sizeof(ehdr.e_machine));
529 		e_entry = mopFileGetLX((u_char *) &ehdr,
530 		    offsetof(Elf32_Ehdr, e_entry),
531 		    sizeof(ehdr.e_entry));
532 
533 		e_phoff = mopFileGetLX((u_char *) &ehdr,
534 		    offsetof(Elf32_Ehdr, e_phoff),
535 		    sizeof(ehdr.e_phoff));
536 		e_phentsize = mopFileGetLX((u_char *) &ehdr,
537 		    offsetof(Elf32_Ehdr, e_phentsize),
538 		    sizeof(ehdr.e_phentsize));
539 		e_phnum = mopFileGetLX((u_char *) &ehdr,
540 		    offsetof(Elf32_Ehdr, e_phnum),
541 		    sizeof(ehdr.e_phnum));
542 		break;
543 
544 	case ELFDATA2MSB:
545 		e_machine = mopFileGetBX((u_char *) &ehdr,
546 		    offsetof(Elf32_Ehdr, e_machine),
547 		    sizeof(ehdr.e_machine));
548 		e_entry = mopFileGetBX((u_char *) &ehdr,
549 		    offsetof(Elf32_Ehdr, e_entry),
550 		    sizeof(ehdr.e_entry));
551 
552 		e_phoff = mopFileGetBX((u_char *) &ehdr,
553 		    offsetof(Elf32_Ehdr, e_phoff),
554 		    sizeof(ehdr.e_phoff));
555 		e_phentsize = mopFileGetBX((u_char *) &ehdr,
556 		    offsetof(Elf32_Ehdr, e_phentsize),
557 		    sizeof(ehdr.e_phentsize));
558 		e_phnum = mopFileGetBX((u_char *) &ehdr,
559 		    offsetof(Elf32_Ehdr, e_phnum),
560 		    sizeof(ehdr.e_phnum));
561 		break;
562 
563 	default:
564 		return(-1);
565 	}
566 
567 	if (e_phnum > SEC_MAX)
568 		return(-1);
569 	dl->e_nsec = e_phnum;
570 	for (i = 0; i < dl->e_nsec; i++) {
571 		if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize),
572 		    SEEK_SET) == (off_t) -1)
573 			return(-1);
574 		if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) !=
575 		    sizeof(phdr))
576 			return(-1);
577 
578 		switch (ei_data) {
579 		case ELFDATA2LSB:
580 			dl->e_sections[i].s_foff =
581 			    mopFileGetLX((u_char *) &phdr,
582 			    offsetof(Elf32_Phdr, p_offset),
583 			    sizeof(phdr.p_offset));
584 			dl->e_sections[i].s_vaddr =
585 			    mopFileGetLX((u_char *) &phdr,
586 			    offsetof(Elf32_Phdr, p_vaddr),
587 			    sizeof(phdr.p_vaddr));
588 			dl->e_sections[i].s_fsize =
589 			    mopFileGetLX((u_char *) &phdr,
590 			    offsetof(Elf32_Phdr, p_filesz),
591 			    sizeof(phdr.p_filesz));
592 			dl->e_sections[i].s_msize =
593 			    mopFileGetLX((u_char *) &phdr,
594 			    offsetof(Elf32_Phdr, p_memsz),
595 			    sizeof(phdr.p_memsz));
596 			break;
597 
598 		case ELFDATA2MSB:
599 			dl->e_sections[i].s_foff =
600 			    mopFileGetBX((u_char *) &phdr,
601 			    offsetof(Elf32_Phdr, p_offset),
602 			    sizeof(phdr.p_offset));
603 			dl->e_sections[i].s_vaddr =
604 			    mopFileGetBX((u_char *) &phdr,
605 			    offsetof(Elf32_Phdr, p_vaddr),
606 			    sizeof(phdr.p_vaddr));
607 			dl->e_sections[i].s_fsize =
608 			    mopFileGetBX((u_char *) &phdr,
609 			    offsetof(Elf32_Phdr, p_filesz),
610 			    sizeof(phdr.p_filesz));
611 			dl->e_sections[i].s_msize =
612 			    mopFileGetBX((u_char *) &phdr,
613 			    offsetof(Elf32_Phdr, p_memsz),
614 			    sizeof(phdr.p_memsz));
615 			break;
616 
617 		default:
618 			return(-1);
619 		}
620 	}
621 	/*
622 	 * In addition to padding between segments, this also
623 	 * takes care of memsz > filesz.
624 	 */
625 	for (i = 0; i < dl->e_nsec - 1; i++) {
626 		dl->e_sections[i].s_pad =
627 		    dl->e_sections[i + 1].s_vaddr -
628 		    (dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize);
629 	}
630 	dl->e_sections[dl->e_nsec - 1].s_pad =
631 	    dl->e_sections[dl->e_nsec - 1].s_msize -
632 	    dl->e_sections[dl->e_nsec - 1].s_fsize;
633 	/*
634 	 * Now compute the logical offsets for each section.
635 	 */
636 	dl->e_sections[0].s_loff = 0;
637 	for (i = 1; i < dl->e_nsec; i++) {
638 		dl->e_sections[i].s_loff =
639 		    dl->e_sections[i - 1].s_loff +
640 		    dl->e_sections[i - 1].s_fsize +
641 		    dl->e_sections[i - 1].s_pad;
642 	}
643 
644 	dl->image_type = IMAGE_TYPE_ELF32;
645 	dl->loadaddr = 0;
646 #if 0
647 	dl->xferaddr = e_entry;		/* will relocate itself if necessary */
648 #else
649 	dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr;
650 #endif
651 
652 	/* Print info about the image. */
653 	if (info == INFO_PRINT) {
654 		printf("Elf32 image (");
655 		switch (e_machine) {
656 #ifdef EM_VAX
657 		case EM_VAX:
658 			printf("VAX");
659 			break;
660 #endif
661 		default:
662 			printf("machine %d", e_machine);
663 			break;
664 		}
665 		printf(")\n");
666 		printf("Transfer Address:   %08x\n", dl->xferaddr);
667 		printf("Program Sections:   %d\n", dl->e_nsec);
668 		for (i = 0; i < dl->e_nsec; i++) {
669 			printf(" S%d File Size:      %08x\n", i,
670 			    dl->e_sections[i].s_fsize);
671 			printf(" S%d Pad Size:       %08x\n", i,
672 			    dl->e_sections[i].s_pad);
673 		}
674 	}
675 
676 	dl->e_machine = e_machine;
677 
678 	dl->e_curpos = 0;
679 	dl->e_cursec = 0;
680 
681 	return(0);
682 #endif /* NOELF */
683 }
684 
685 int
686 GetElf64FileInfo(struct dllist *dl, int info)
687 {
688 #if defined(NOELF) || defined(NOELF64)
689 	return(-1);
690 #else
691 	Elf64_Ehdr ehdr;
692 	Elf64_Phdr phdr;
693 	uint32_t e_machine;
694 	uint32_t e_phentsize, e_phnum;
695 	uint64_t e_entry, e_phoff;
696 	int ei_data, i;
697 
698 	(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
699 
700 	if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
701 		return(-1);
702 
703 	if (ehdr.e_ident[0] != ELFMAG0 ||
704 	    ehdr.e_ident[1] != ELFMAG1 ||
705 	    ehdr.e_ident[2] != ELFMAG2 ||
706 	    ehdr.e_ident[3] != ELFMAG3)
707 		return(-1);
708 
709 	/* Must be Elf64... */
710 	if (ehdr.e_ident[EI_CLASS] != ELFCLASS64)
711 		return(-1);
712 
713 	ei_data = ehdr.e_ident[EI_DATA];
714 
715 	switch (ei_data) {
716 	case ELFDATA2LSB:
717 		e_machine = mopFileGetLX((u_char *) &ehdr,
718 		    offsetof(Elf64_Ehdr, e_machine),
719 		    sizeof(ehdr.e_machine));
720 		e_entry = mopFileGetLXX((u_char *) &ehdr,
721 		    offsetof(Elf64_Ehdr, e_entry),
722 		    sizeof(ehdr.e_entry));
723 
724 		e_phoff = mopFileGetLXX((u_char *) &ehdr,
725 		    offsetof(Elf64_Ehdr, e_phoff),
726 		    sizeof(ehdr.e_phoff));
727 		e_phentsize = mopFileGetLX((u_char *) &ehdr,
728 		    offsetof(Elf64_Ehdr, e_phentsize),
729 		    sizeof(ehdr.e_phentsize));
730 		e_phnum = mopFileGetLX((u_char *) &ehdr,
731 		    offsetof(Elf64_Ehdr, e_phnum),
732 		    sizeof(ehdr.e_phnum));
733 		break;
734 
735 	case ELFDATA2MSB:
736 		e_machine = mopFileGetBX((u_char *) &ehdr,
737 		    offsetof(Elf64_Ehdr, e_machine),
738 		    sizeof(ehdr.e_machine));
739 		e_entry = mopFileGetBXX((u_char *) &ehdr,
740 		    offsetof(Elf64_Ehdr, e_entry),
741 		    sizeof(ehdr.e_entry));
742 
743 		e_phoff = mopFileGetBXX((u_char *) &ehdr,
744 		    offsetof(Elf64_Ehdr, e_phoff),
745 		    sizeof(ehdr.e_phoff));
746 		e_phentsize = mopFileGetBX((u_char *) &ehdr,
747 		    offsetof(Elf64_Ehdr, e_phentsize),
748 		    sizeof(ehdr.e_phentsize));
749 		e_phnum = mopFileGetBX((u_char *) &ehdr,
750 		    offsetof(Elf64_Ehdr, e_phnum),
751 		    sizeof(ehdr.e_phnum));
752 		break;
753 
754 	default:
755 		return(-1);
756 	}
757 
758 	if (e_phnum > SEC_MAX)
759 		return(-1);
760 	dl->e_nsec = e_phnum;
761 	for (i = 0; i < dl->e_nsec; i++) {
762 		if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize),
763 		    SEEK_SET) == (off_t) -1)
764 			return(-1);
765 		if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) !=
766 		    sizeof(phdr))
767 			return(-1);
768 
769 		switch (ei_data) {
770 		case ELFDATA2LSB:
771 			dl->e_sections[i].s_foff =
772 			    mopFileGetLX((u_char *) &phdr,
773 			    offsetof(Elf64_Phdr, p_offset),
774 			    sizeof(phdr.p_offset));
775 			dl->e_sections[i].s_vaddr =
776 			    mopFileGetLX((u_char *) &phdr,
777 			    offsetof(Elf64_Phdr, p_vaddr),
778 			    sizeof(phdr.p_vaddr));
779 			dl->e_sections[i].s_fsize =
780 			    mopFileGetLX((u_char *) &phdr,
781 			    offsetof(Elf64_Phdr, p_filesz),
782 			    sizeof(phdr.p_filesz));
783 			dl->e_sections[i].s_msize =
784 			    mopFileGetLX((u_char *) &phdr,
785 			    offsetof(Elf64_Phdr, p_memsz),
786 			    sizeof(phdr.p_memsz));
787 			break;
788 
789 		case ELFDATA2MSB:
790 			dl->e_sections[i].s_foff =
791 			    mopFileGetBX((u_char *) &phdr,
792 			    offsetof(Elf64_Phdr, p_offset),
793 			    sizeof(phdr.p_offset));
794 			dl->e_sections[i].s_vaddr =
795 			    mopFileGetBX((u_char *) &phdr,
796 			    offsetof(Elf64_Phdr, p_vaddr),
797 			    sizeof(phdr.p_vaddr));
798 			dl->e_sections[i].s_fsize =
799 			    mopFileGetBX((u_char *) &phdr,
800 			    offsetof(Elf64_Phdr, p_filesz),
801 			    sizeof(phdr.p_filesz));
802 			dl->e_sections[i].s_msize =
803 			    mopFileGetBX((u_char *) &phdr,
804 			    offsetof(Elf64_Phdr, p_memsz),
805 			    sizeof(phdr.p_memsz));
806 			break;
807 
808 		default:
809 			return(-1);
810 		}
811 	}
812 	/*
813 	 * In addition to padding between segments, this also
814 	 * takes care of memsz > filesz.
815 	 */
816 	for (i = 0; i < dl->e_nsec - 1; i++) {
817 		dl->e_sections[i].s_pad =
818 		    dl->e_sections[i + 1].s_vaddr -
819 		    (dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize);
820 	}
821 	dl->e_sections[dl->e_nsec - 1].s_pad =
822 	    dl->e_sections[dl->e_nsec - 1].s_msize -
823 	    dl->e_sections[dl->e_nsec - 1].s_fsize;
824 	/*
825 	 * Now compute the logical offsets for each section.
826 	 */
827 	dl->e_sections[0].s_loff = 0;
828 	for (i = 1; i < dl->e_nsec; i++) {
829 		dl->e_sections[i].s_loff =
830 		    dl->e_sections[i - 1].s_loff +
831 		    dl->e_sections[i - 1].s_fsize +
832 		    dl->e_sections[i - 1].s_pad;
833 	}
834 
835 	dl->image_type = IMAGE_TYPE_ELF64;
836 	dl->loadaddr = 0;
837 #if 0
838 	dl->xferaddr = e_entry;		/* will relocate itself if necessary */
839 #else
840 	dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr;
841 #endif
842 
843 	/* Print info about the image. */
844 	if (info == INFO_PRINT) {
845 		printf("Elf64 image (");
846 		switch (e_machine) {
847 #ifdef EM_ALPHA
848 		case EM_ALPHA:
849 #endif
850 #ifdef EM_ALPHA_EXP
851 		case EM_ALPHA_EXP:
852 #endif
853 #if defined(EM_ALPHA) || defined(EM_ALPHA_EXP)
854 			printf("ALPHA");
855 			break;
856 #endif
857 		default:
858 			printf("machine %d", e_machine);
859 			break;
860 		}
861 		printf(")\n");
862 		printf("Transfer Address:   %08x\n", dl->xferaddr);
863 		printf("Program Sections:   %d\n", dl->e_nsec);
864 		for (i = 0; i < dl->e_nsec; i++) {
865 			printf(" S%d File Size:      %08x\n", i,
866 			    dl->e_sections[i].s_fsize);
867 			printf(" S%d Pad Size:       %08x\n", i,
868 			    dl->e_sections[i].s_pad);
869 		}
870 	}
871 
872 	dl->e_machine = e_machine;
873 
874 	dl->e_curpos = 0;
875 	dl->e_cursec = 0;
876 
877 	return(0);
878 #endif /* NOELF || NOELF64 */
879 }
880 
881 int
882 CheckAOutFile(int fd)
883 {
884 #ifdef NOAOUT
885 	return(-1);
886 #else
887 	struct exec ex, ex_swap;
888 	int	mid = -1;
889 
890 	if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex))
891 		return(-1);
892 
893 	(void)lseek(fd, (off_t) 0, SEEK_SET);
894 
895 	if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap))
896 		return(-1);
897 
898 	(void)lseek(fd, (off_t) 0, SEEK_SET);
899 
900 	mid = getMID(mid, N_GETMID (ex));
901 
902 	if (mid == -1) {
903 		mid = getMID(mid, N_GETMID (ex_swap));
904 	}
905 
906 	if (mid != -1) {
907 		return(0);
908 	} else {
909 		return(-1);
910 	}
911 #endif /* NOAOUT */
912 }
913 
914 int
915 GetAOutFileInfo(struct dllist *dl, int info)
916 {
917 #ifdef NOAOUT
918 	return(-1);
919 #else
920 	struct exec ex, ex_swap;
921 	u_int32_t	mid = -1;
922 	u_int32_t	magic, clbytes, clofset;
923 
924 	if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex))
925 		return(-1);
926 
927 	(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
928 
929 	if (read(dl->ldfd, (char *)&ex_swap,
930 		 sizeof(ex_swap)) != sizeof(ex_swap))
931 		return(-1);
932 
933 	mopFileSwapX((u_char *)&ex_swap, 0, 4);
934 
935 	mid = getMID(mid, N_GETMID (ex));
936 
937 	if (mid == (uint32_t)-1) {
938 		mid = getMID(mid, N_GETMID (ex_swap));
939 		if (mid != (uint32_t)-1) {
940 			mopFileSwapX((u_char *)&ex, 0, 4);
941 		}
942 	}
943 
944 	if (mid == (uint32_t)-1) {
945 		return(-1);
946 	}
947 
948 	if (N_BADMAG (ex)) {
949 		return(-1);
950 	}
951 
952 	switch (mid) {
953 	case MID_I386:
954 #ifdef MID_NS32532
955 	case MID_NS32532:
956 #endif
957 #ifdef MID_PMAX
958 	case MID_PMAX:
959 #endif
960 #ifdef MID_VAX
961 	case MID_VAX:
962 #endif
963 #ifdef MID_ALPHA
964 	case MID_ALPHA:
965 #endif
966 #ifdef MID_ARM6
967 	case MID_ARM6:
968 #endif
969 		ex.a_text  = mopFileGetLX((u_char *)&ex_swap,  4, 4);
970 		ex.a_data  = mopFileGetLX((u_char *)&ex_swap,  8, 4);
971 		ex.a_bss   = mopFileGetLX((u_char *)&ex_swap, 12, 4);
972 		ex.a_syms  = mopFileGetLX((u_char *)&ex_swap, 16, 4);
973 		ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4);
974 		ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4);
975 		ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4);
976 		break;
977 #ifdef MID_M68K
978 	case MID_M68K:
979 #endif
980 #ifdef MID_M68K4K
981 	case MID_M68K4K:
982 #endif
983 	case MID_SPARC:
984 #ifdef MID_MIPS
985 	case MID_MIPS:
986 #endif
987 		ex.a_text  = mopFileGetBX((u_char *)&ex_swap,  4, 4);
988 		ex.a_data  = mopFileGetBX((u_char *)&ex_swap,  8, 4);
989 		ex.a_bss   = mopFileGetBX((u_char *)&ex_swap, 12, 4);
990 		ex.a_syms  = mopFileGetBX((u_char *)&ex_swap, 16, 4);
991 		ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4);
992 		ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4);
993 		ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4);
994 		break;
995 	default:
996 		break;
997 	}
998 
999 	if (info == INFO_PRINT) {
1000 		printf("a.out image (");
1001 		switch (N_GETMID (ex)) {
1002 		case MID_I386:
1003 			printf("i386");
1004 			break;
1005 #ifdef MID_M68K
1006 		case MID_M68K:
1007 			printf("m68k");
1008 			break;
1009 #endif
1010 #ifdef MID_M68K4K
1011 		case MID_M68K4K:
1012 			printf("m68k 4k");
1013 			break;
1014 #endif
1015 #ifdef MID_NS32532
1016 		case MID_NS32532:
1017 			printf("pc532");
1018 			break;
1019 #endif
1020 		case MID_SPARC:
1021 			printf("sparc");
1022 			break;
1023 #ifdef MID_PMAX
1024 		case MID_PMAX:
1025 			printf("pmax");
1026 			break;
1027 #endif
1028 #ifdef MID_VAX
1029 		case MID_VAX:
1030 			printf("vax");
1031 			break;
1032 #endif
1033 #ifdef MID_ALPHA
1034 		case MID_ALPHA:
1035 			printf("alpha");
1036 			break;
1037 #endif
1038 #ifdef MID_MIPS
1039 		case MID_MIPS:
1040 			printf("mips");
1041 			break;
1042 #endif
1043 #ifdef MID_ARM6
1044 		case MID_ARM6:
1045 			printf("arm32");
1046 			break;
1047 #endif
1048 		default:
1049 			break;
1050 		}
1051 		printf(") Magic: ");
1052 		switch (N_GETMAGIC (ex)) {
1053 		case OMAGIC:
1054 			printf("OMAGIC");
1055 			break;
1056 		case NMAGIC:
1057 			printf("NMAGIC");
1058 			break;
1059 		case ZMAGIC:
1060 			printf("ZMAGIC");
1061 			break;
1062 		case QMAGIC:
1063 			printf("QMAGIC");
1064 			break;
1065 		default:
1066 			printf("Unknown %ld", (long) N_GETMAGIC (ex));
1067 		}
1068 		printf("\n");
1069 		printf("Size of text:       %08lx\n", (long)ex.a_text);
1070 		printf("Size of data:       %08lx\n", (long)ex.a_data);
1071 		printf("Size of bss:        %08lx\n", (long)ex.a_bss);
1072 		printf("Size of symbol tab: %08lx\n", (long)ex.a_syms);
1073 		printf("Transfer Address:   %08lx\n", (long)ex.a_entry);
1074 		printf("Size of reloc text: %08lx\n", (long)ex.a_trsize);
1075 		printf("Size of reloc data: %08lx\n", (long)ex.a_drsize);
1076 	}
1077 
1078 	magic = N_GETMAGIC (ex);
1079 	clbytes = getCLBYTES(mid);
1080 	clofset = clbytes - 1;
1081 
1082 	dl->image_type = IMAGE_TYPE_AOUT;
1083 	dl->loadaddr = 0;
1084 	dl->xferaddr = ex.a_entry;
1085 
1086 	dl->a_text = ex.a_text;
1087 	if (magic == ZMAGIC || magic == NMAGIC) {
1088 		dl->a_text_fill = clbytes - (ex.a_text & clofset);
1089 		if (dl->a_text_fill == clbytes)
1090 			dl->a_text_fill = 0;
1091 	} else
1092 		dl->a_text_fill = 0;
1093 	dl->a_data = ex.a_data;
1094 	if (magic == ZMAGIC || magic == NMAGIC) {
1095 		dl->a_data_fill = clbytes - (ex.a_data & clofset);
1096 		if (dl->a_data_fill == clbytes)
1097 			dl->a_data_fill = 0;
1098 	} else
1099 		dl->a_data_fill = 0;
1100 	dl->a_bss = ex.a_bss;
1101 	if (magic == ZMAGIC || magic == NMAGIC) {
1102 		dl->a_bss_fill = clbytes - (ex.a_bss & clofset);
1103 		if (dl->a_bss_fill == clbytes)
1104 			dl->a_bss_fill = 0;
1105 	} else {
1106 		dl->a_bss_fill = clbytes -
1107 		    ((ex.a_text+ex.a_data+ex.a_bss) & clofset);
1108 		if (dl->a_bss_fill == clbytes)
1109 			dl->a_bss_fill = 0;
1110 	}
1111 	dl->a_mid = mid;
1112 
1113 	return(0);
1114 #endif /* NOAOUT */
1115 }
1116 
1117 int
1118 GetFileInfo(struct dllist *dl, int info)
1119 {
1120 	int error;
1121 
1122 	error = CheckElfFile(dl->ldfd);
1123 	if (error == 0) {
1124 		error = GetElf32FileInfo(dl, info);
1125 		if (error != 0)
1126 			error = GetElf64FileInfo(dl, info);
1127 		if (error != 0) {
1128 			return(-1);
1129 		}
1130 		return (0);
1131 	}
1132 
1133 	error = CheckAOutFile(dl->ldfd);
1134 	if (error == 0) {
1135 		error = GetAOutFileInfo(dl, info);
1136 		if (error != 0) {
1137 			return(-1);
1138 		}
1139 		return (0);
1140 	}
1141 
1142 	error = CheckMopFile(dl->ldfd);
1143 	if (error == 0) {
1144 		error = GetMopFileInfo(dl, info);
1145 		if (error != 0) {
1146 			return(-1);
1147 		}
1148 		return (0);
1149 	}
1150 
1151 	/* Unknown file format. */
1152 	return(-1);
1153 }
1154 
1155 ssize_t
1156 mopFileRead(struct dllist *dlslot, u_char *buf)
1157 {
1158 	ssize_t len, outlen;
1159 	int	bsz, sec;
1160 	int32_t	pos, notdone, total;
1161 	uint32_t secoff;
1162 
1163 	switch (dlslot->image_type) {
1164 	case IMAGE_TYPE_MOP:
1165 		len = read(dlslot->ldfd,buf,dlslot->dl_bsz);
1166 		break;
1167 
1168 	case IMAGE_TYPE_ELF32:
1169 	case IMAGE_TYPE_ELF64:
1170 		sec = dlslot->e_cursec;
1171 
1172 		/*
1173 		 * We're pretty simplistic here.  We do only file-backed
1174 		 * or only zero-fill.
1175 		 */
1176 
1177 		/* Determine offset into section. */
1178 		secoff = dlslot->e_curpos - dlslot->e_sections[sec].s_loff;
1179 
1180 		/*
1181 		 * If we're in the file-backed part of the section,
1182 		 * transmit some of the file.
1183 		 */
1184 		if (secoff < dlslot->e_sections[sec].s_fsize) {
1185 			bsz = dlslot->e_sections[sec].s_fsize - secoff;
1186 			if (bsz > dlslot->dl_bsz)
1187 				bsz = dlslot->dl_bsz;
1188 			if (lseek(dlslot->ldfd,
1189 			    dlslot->e_sections[sec].s_foff + secoff,
1190 			    SEEK_SET) == (off_t) -1)
1191 				return (-1);
1192 			len = read(dlslot->ldfd, buf, bsz);
1193 		}
1194 		/*
1195 		 * Otherwise, if we're in the zero-fill part of the
1196 		 * section, transmit some zeros.
1197 		 */
1198 		else if (secoff < (dlslot->e_sections[sec].s_fsize +
1199 				   dlslot->e_sections[sec].s_pad)) {
1200 			bsz = dlslot->e_sections[sec].s_pad -
1201 			    (secoff - dlslot->e_sections[sec].s_fsize);
1202 			if (bsz > dlslot->dl_bsz)
1203 				bsz = dlslot->dl_bsz;
1204 			memset(buf, 0, (len = bsz));
1205 		}
1206 		/*
1207 		 * ...and if we haven't hit either of those cases,
1208 		 * that's the end of the image.
1209 		 */
1210 		else {
1211 			return (0);
1212 		}
1213 		/*
1214 		 * Advance the logical image pointer.
1215 		 */
1216 		dlslot->e_curpos += bsz;
1217 		if (dlslot->e_curpos >= (dlslot->e_sections[sec].s_loff +
1218 					 dlslot->e_sections[sec].s_fsize +
1219 					 dlslot->e_sections[sec].s_pad))
1220 			if (++sec != dlslot->e_nsec)
1221 				dlslot->e_cursec = sec;
1222 		break;
1223 
1224 	case IMAGE_TYPE_AOUT:
1225 		bsz = dlslot->dl_bsz;
1226 		pos = dlslot->a_lseek;
1227 		len = 0;
1228 
1229 		total = dlslot->a_text;
1230 
1231 		if (pos < total) {
1232 			notdone = total - pos;
1233 			if (notdone <= bsz) {
1234 				outlen = read(dlslot->ldfd,&buf[len],notdone);
1235 			} else {
1236 				outlen = read(dlslot->ldfd,&buf[len],bsz);
1237 			}
1238 			len = len + outlen;
1239 			pos = pos + outlen;
1240 			bsz = bsz - outlen;
1241 		}
1242 
1243 		total = total + dlslot->a_text_fill;
1244 
1245 		if ((bsz > 0) && (pos < total)) {
1246 			notdone = total - pos;
1247 			if (notdone <= bsz) {
1248 				outlen = notdone;
1249 			} else {
1250 				outlen = bsz;
1251 			}
1252 			memset(&buf[len], 0, outlen);
1253 			len = len + outlen;
1254 			pos = pos + outlen;
1255 			bsz = bsz - outlen;
1256 		}
1257 
1258 		total = total + dlslot->a_data;
1259 
1260 		if ((bsz > 0) && (pos < total)) {
1261 			notdone = total - pos;
1262 			if (notdone <= bsz) {
1263 				outlen = read(dlslot->ldfd,&buf[len],notdone);
1264 			} else {
1265 				outlen = read(dlslot->ldfd,&buf[len],bsz);
1266 			}
1267 			len = len + outlen;
1268 			pos = pos + outlen;
1269 			bsz = bsz - outlen;
1270 		}
1271 
1272 		total = total + dlslot->a_data_fill;
1273 
1274 		if ((bsz > 0) && (pos < total)) {
1275 			notdone = total - pos;
1276 			if (notdone <= bsz) {
1277 				outlen = notdone;
1278 			} else {
1279 				outlen = bsz;
1280 			}
1281 			memset(&buf[len], 0, outlen);
1282 			len = len + outlen;
1283 			pos = pos + outlen;
1284 			bsz = bsz - outlen;
1285 		}
1286 
1287 		total = total + dlslot->a_bss;
1288 
1289 		if ((bsz > 0) && (pos < total)) {
1290 			notdone = total - pos;
1291 			if (notdone <= bsz) {
1292 				outlen = notdone;
1293 			} else {
1294 				outlen = bsz;
1295 			}
1296 			memset(&buf[len], 0, outlen);
1297 			len = len + outlen;
1298 			pos = pos + outlen;
1299 			bsz = bsz - outlen;
1300 		}
1301 
1302 		total = total + dlslot->a_bss_fill;
1303 
1304 		if ((bsz > 0) && (pos < total)) {
1305 			notdone = total - pos;
1306 			if (notdone <= bsz) {
1307 				outlen = notdone;
1308 			} else {
1309 				outlen = bsz;
1310 			}
1311 			memset(&buf[len], 0, outlen);
1312 			len = len + outlen;
1313 			pos = pos + outlen;
1314 			bsz = bsz - outlen;
1315 		}
1316 
1317 		dlslot->a_lseek = pos;
1318 		break;
1319 
1320 	default:
1321 		abort();
1322 	}
1323 
1324 	return(len);
1325 }
1326