1 /* $OpenBSD: file.c,v 1.20 2024/10/16 18:47:48 miod 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 <a.out.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 *
FileTypeName(mopd_imagetype type)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
mopFilePutLX(u_char * buf,int idx,u_int32_t value,int cnt)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
mopFilePutBX(u_char * buf,int idx,u_int32_t value,int cnt)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
mopFileGetLX(u_char * buf,int idx,int cnt)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
mopFileGetBX(u_char * buf,int idx,int cnt)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
mopFileGetLXX(u_char * buf,int idx,int cnt)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
mopFileGetBXX(u_char * buf,int idx,int cnt)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
mopFileSwapX(u_char * buf,int idx,int cnt)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
CheckMopFile(int fd)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
GetMopFileInfo(struct dllist * dl,int info)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
getMID(int old_mid,int new_mid)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
getCLBYTES(int mid)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
CheckElfFile(int fd)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
GetElf32FileInfo(struct dllist * dl,int info)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
GetElf64FileInfo(struct dllist * dl,int info)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
CheckAOutFile(int fd)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
GetAOutFileInfo(struct dllist * dl,int info)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
GetFileInfo(struct dllist * dl,int info)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
mopFileRead(struct dllist * dlslot,u_char * buf)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