1 /*
2 * This is a combination of three tools for decoding information from
3 * Dev86/ELKS object files and executables.
4 *
5 * This executable can be given the names:
6 *
7 * objdump86: Dumps detailed information about a binary file.
8 * size86: Summary sizes of the data in a binary file.
9 * nm86: The symbol table of the binary file.
10 *
11 * None of these programs have any options.
12 * This may be a minor problem with nm86.
13 *
14 * Copyright (c) 1999 by Greg Haerr <greg@censoft.com>
15 * Added archive file reading capabilties
16 */
17
18 #include <stdio.h>
19 #ifdef __STDC__
20 #include <stdlib.h>
21 #else
22 #include <malloc.h>
23 #endif
24 #include <string.h>
25 #include "const.h"
26 #include "ar.h"
27 #include "obj.h"
28
29 FILE * ifd;
30 char * ifname;
31
32 #ifdef __STDC__
33 #define _(x) x
34 #else
35 #define _(x) ()
36 #endif
37
38 long get_long _((void));
39 long get_sized _((int sz));
40 unsigned int get_word _((void));
41 int get_byte _((void));
42 int main _((int argc, char**argv));
43 void do_file _((char * fname));
44 long read_arheader _((char *archentry));
45 void do_module _((char * fname, char *archive));
46 int error _((char * str));
47 int read_objheader _((void));
48 int read_sectheader _((void));
49 int read_syms _((void));
50 void disp_sectheader _((void));
51 int disp_syms _((void));
52 void read_databytes _((void));
53 void hex_output _((int ch));
54 void fetch_aout_hdr _((void));
55 void dump_aout _((void));
56 void size_aout _((void));
57 void nm_aout _((void));
58 #ifndef VERY_SMALL_MEMORY
59 void fetch_v7_hdr _((void));
60 void dump_v7 _((void));
61 void size_v7 _((void));
62 #endif
63
64 int obj_ver;
65 int sections;
66 long segsizes[16];
67 long textoff;
68 long textlen;
69 long str_off;
70 long str_len;
71 long filepos;
72 int num_syms;
73 long code_bytes;
74
75 char ** symnames;
76 char * strtab;
77
78 struct {
79 unsigned int nameoff, symtype;
80 long offset;
81 } *symtab;
82
83 int display_mode = 0;
84 int multiple_files = 0;
85 int byte_order = 0;
86
87 int opt_o;
88
89 long size_text, size_data, size_bss;
90 long tot_size_text=0, tot_size_data=0, tot_size_bss=0;
91
92 int
main(argc,argv)93 main(argc, argv)
94 int argc;
95 char ** argv;
96 {
97 int ar;
98 char * p;
99
100 ifd = stdin; /* In Libc6 stdin is weird */
101
102 p = strrchr(argv[0], '/');
103 if(p) p++; else p=argv[0];
104
105 if( p[0] == 's' ) display_mode = 1;
106 if( p[0] == 'n' ) display_mode = 2;
107
108 multiple_files = 0;
109 for(ar=1; ar<argc; ar++)
110 {
111 if( argv[ar][0] == '-' ) switch(argv[ar][1])
112 {
113 case 's': display_mode = 1; break;
114 case 'n': display_mode = 2; break;
115 case 'o': opt_o++; break;
116 }
117 else
118 multiple_files++;
119 }
120
121 if( !multiple_files ) exit(1);
122
123 multiple_files = (multiple_files>1);
124
125 if( display_mode == 1 )
126 printf("text\tdata\tbss\tdec\thex\tfilename\n");
127
128 for(ar=1; ar<argc; ar++) if(argv[ar][0] != '-')
129 do_file(argv[ar]);
130
131 if( display_mode == 1 && multiple_files)
132 printf("%ld\t%ld\t%ld\t%ld\t%lx\tTotal\n",
133 tot_size_text, tot_size_data, tot_size_bss,
134 tot_size_text+ tot_size_data+ tot_size_bss,
135 tot_size_text+ tot_size_data+ tot_size_bss);
136
137 return 0;
138 }
139
140 void
do_file(fname)141 do_file(fname)
142 char * fname;
143 {
144 unsigned int magic;
145 long filelength;
146 char archentry[sizeof(struct ar_hdr)]; /* sizeof ar_hdr.ar_name*/
147 char filemagic[SARMAG];
148
149 ifname = fname;
150 if( (ifd=fopen(fname, "rb")) == 0 )
151 {
152 error("Cannot open file");
153 return;
154 }
155 filepos = 0L;
156
157 /* check if file is an archive*/
158 if(fread(filemagic, sizeof(filemagic), 1, ifd) == 1
159 && strncmp(filemagic, ARMAG, sizeof filemagic) == 0)
160 {
161 filepos = SARMAG;
162 while((filelength = read_arheader(archentry)) > 0)
163 {
164 filepos += sizeof(struct ar_hdr);
165 magic = get_word();
166 if(magic == 0x86A3)
167 { /* OMAGIC*/
168 fseek(ifd, filepos, 0);
169 do_module(archentry, fname);
170 }
171 else if(magic == 0x3C21 ) /* "!<" */
172 filelength = SARMAG;
173 filepos += ld_roundup(filelength, 2, long);
174 fseek(ifd, filepos, 0);
175 }
176 }
177 else
178 {
179 fseek(ifd, 0L, 0);
180 do_module(fname, NULL);
181 }
182 fclose(ifd);
183 }
184
185 /* read archive header and return length */
186 long
read_arheader(archentry)187 read_arheader(archentry)
188 char *archentry;
189 {
190 char * endptr;
191 struct ar_hdr arheader;
192
193 if(fread((char *)&arheader, sizeof(arheader), 1, ifd) != 1)
194 return 0;
195 strncpy(archentry, arheader.ar_name, sizeof(arheader.ar_name));
196 archentry[sizeof(arheader.ar_name)] = 0;
197 endptr = archentry + sizeof(arheader.ar_name);
198 do
199 {
200 *endptr-- = 0;
201 } while(endptr > archentry && (*endptr == ' ' || *endptr == '/'));
202 return strtoul(arheader.ar_size, (char **)NULL, 0);
203 }
204
205 void
do_module(fname,archive)206 do_module(fname, archive)
207 char * fname;
208 char * archive;
209 {
210 int modno, i;
211
212 size_text = size_data = size_bss = 0;
213 byte_order = 0;
214
215 if( !display_mode )
216 {
217 if(archive)
218 printf("ARCHIVEFILE '%s'\n", archive);
219 printf("OBJECTFILE '%s'\n", fname);
220 }
221
222 switch( read_objheader() )
223 {
224 case 0: /* as86 object file */
225
226 for(modno=1; modno<=sections; modno++)
227 {
228 if( modno != 1 && !display_mode )
229 printf("OBJECTSECTION %d\n", modno);
230 if( read_sectheader() < 0 ) break;
231
232 /* segments 0, 4-E are text, 1-3 are data*/
233 for(i=0; i<16; i++)
234 {
235 if(i < 1 || i > 4)
236 size_text += segsizes[i];
237 else size_data += segsizes[i];
238 }
239
240 if( read_syms() < 0 ) break;
241
242 strtab = malloc((unsigned int)str_len+1);
243 if( strtab == 0 ) { error("Out of memory"); break; }
244 str_off = ftell(ifd);
245 fread(strtab, 1, (unsigned int)str_len, ifd);
246
247 disp_sectheader();
248 disp_syms();
249
250 if( display_mode == 0 )
251 printf("text\tdata\tbss\tdec\thex\tfilename\n");
252 if( display_mode != 2 )
253 {
254 printf("%ld\t%ld\t%ld\t%ld\t%lx\t",
255 size_text, size_data, size_bss,
256 size_text+ size_data+ size_bss,
257 size_text+ size_data+ size_bss);
258
259 if(archive) printf("%s(%s)\n", archive, fname);
260 else printf("%s\n", fname);
261
262 tot_size_text += size_text;
263 tot_size_data += size_data;
264 tot_size_bss += size_bss;
265 }
266
267 if( sections == 1 && display_mode != 0 )
268 break;
269
270 read_databytes();
271 }
272 break;
273
274 case 1: /* ELKS executable */
275 fseek(ifd, 0L, 0);
276 fetch_aout_hdr();
277
278 switch(display_mode)
279 {
280 case 0: dump_aout(); break;
281 case 1: size_aout(); break;
282 case 2: nm_aout(); break;
283 }
284 break;
285 #ifndef VERY_SMALL_MEMORY
286 case 2: /* V7 executable */
287 fseek(ifd, 0L, 0);
288 fetch_v7_hdr();
289
290 switch(display_mode)
291 {
292 case 0: dump_v7(); break;
293 case 1: size_v7(); break;
294 case 2: error("Symbol table not supported for v7"); exit(1); break;
295 }
296 break;
297 #endif
298 }
299
300 if( strtab ) free(strtab);
301 if( symnames ) free(symnames);
302 strtab = 0;
303 symnames = 0;
304 }
305
306 int
error(str)307 error(str)
308 char * str;
309 {
310 switch( display_mode )
311 {
312 case 1: fprintf(stderr, "size: %s: %s\n", ifname, str); break;
313 case 2: fprintf(stderr, "nm: %s: %s\n", ifname, str); break;
314 default:
315 printf("Error: %s\n", str);
316 break;
317 }
318 return -1;
319 }
320
321 int
read_objheader()322 read_objheader()
323 {
324 unsigned char buf[5];
325
326 if( fread(buf, 1, 5, ifd) != 5 )
327 return error("Cannot read object header");
328
329 if( buf[0] != 0xA3 || buf[1] != 0x86 )
330 {
331 if( buf[0] == 1 && buf[1] == 3 )
332 {
333 sections = 1;
334 return 1;
335 }
336 #ifndef VERY_SMALL_MEMORY
337 if( buf[1] == 1 ) /* 04xx octal */
338 {
339 sections = 1;
340 return 2;
341 }
342 #endif
343 return error("Bad magic number");
344 }
345
346 if( (unsigned char)(buf[0] + buf[1] + buf[2] + buf[3]) != buf[4] )
347 return error("Bad header checksum");
348
349 sections= buf[2]+256*buf[3];
350
351 return 0;
352 }
353
354 int
read_sectheader()355 read_sectheader()
356 {
357 long ssenc;
358 int i;
359
360 textoff = get_long(); /* Offset of bytecode in file */
361 textlen = get_long(); /* Length of text+data (no bss) in memory */
362 str_len = get_word(); /* Length of string table in file */
363 obj_ver = get_word(); /* 0.0 */
364
365 (void)get_long(); /* Ignore fives */
366 ssenc = get_long(); /* Sixteen segment size sizes */
367
368 for(i=0; i<16; i++)
369 {
370 int ss;
371 ss = (i^3);
372 ss = ((ssenc>>(2*(15-ss)))&3);
373 segsizes[i] = get_sized(ss);
374 }
375
376 num_syms = get_word(); /* Number of symbol codes */
377
378 return 0;
379 }
380
381 void
disp_sectheader()382 disp_sectheader()
383 {
384 int i;
385 if( display_mode ) return;
386
387 printf("MODULE '%s'\n", strtab);
388 printf("BYTEPOS %08lx\n", textoff);
389 printf("BINLEN %08lx\n", textlen);
390 printf("STRINGS %04lx +%04lx\n", str_off, str_len);
391 printf("VERSION %d.%d\n", obj_ver/256, obj_ver%256);
392
393 for(i=0; i<16; i++)
394 if( segsizes[i] )
395 printf("SEG%x %08lx\n", i, segsizes[i]);
396
397 printf("\n");
398 printf("SYMS %u\n", num_syms);
399 }
400
401 int
read_syms()402 read_syms()
403 {
404 int i;
405
406 if( num_syms < 0 ) return error("Bad symbol table");
407
408 symnames = malloc(num_syms*sizeof(char*)+1);
409 if( symnames == 0 ) return error("Out of memory");
410
411 symtab = calloc(num_syms, sizeof(*symtab));
412 if( symtab == 0 ) return error("Out of memory");
413
414 for(i=0; i<num_syms; i++)
415 {
416 unsigned int symtype;
417
418 symtab[i].nameoff = get_word();
419 symtab[i].symtype = get_word();
420 symtype = (symtab[i].symtype & 0x3FFF);
421
422 if (symtab[i].nameoff == -1 || symtab[i].symtype == -1) {
423 printf("!!! EOF in symbol table\n");
424 break;
425 }
426 symtab[i].offset = get_sized((symtab[i].symtype>>14)&3);
427
428 if( symtype == 0x43 || symtype == 0x2003 )
429 size_bss += symtab[i].offset;
430 }
431
432 return 0;
433 }
434
435 int
disp_syms()436 disp_syms()
437 {
438 int i;
439
440 if(display_mode == 2 && multiple_files && !opt_o)
441 printf("\n%s:\n", ifname);
442
443 for(i=0; i<num_syms; i++)
444 {
445 long offset=0;
446 unsigned int nameoff, symtype;
447
448 nameoff = symtab[i].nameoff;
449 symtype = symtab[i].symtype;
450 offset = symtab[i].offset;
451
452 symtype &= 0x3FFF;
453 if (nameoff > str_len || nameoff < 0)
454 symnames[i] = strtab + str_len;
455 else
456 symnames[i] = strtab+nameoff;
457
458 if( !display_mode )
459 {
460 printf("SYM %-4d %08lx ", i, offset);
461
462 printf("%s", (symtype&0x2000)?"C":".");
463 printf("%s", (symtype&0x0100)?"N":".");
464 printf("%s", (symtype&0x0080)?"E":".");
465 printf("%s", (symtype&0x0040)?"I":".");
466 printf("%c", "T12D456789abcdeUAhijklmnopqrstuv"[symtype&0x1F]);
467 if( symtype &0x1E20 )
468 printf(" %04x", symtype);
469 printf(" %s\n", symnames[i]);
470 }
471 if( display_mode == 2 )
472 {
473 if (opt_o)
474 printf("%s: ", ifname);
475 if( symtype == 0x004f || symtype == 0x0040 )
476 printf(" ");
477 else
478 printf("%08lx ", offset);
479 switch(symtype)
480 {
481 case 0x004F: putchar('U'); break;
482 case 0x0000: putchar('t'); break;
483 case 0x0003: putchar('d'); break;
484 case 0x2003: putchar('b'); break;
485 case 0x0043: putchar('C'); break;
486 case 0x0083: putchar('D'); break;
487 case 0x0080: putchar('T'); break;
488 case 0x0040: putchar('T'); break;
489 case 0x0180: putchar('N'); break;
490 case 0x0010: putchar('a'); break;
491 case 0x0090: putchar('A'); break;
492 default:
493 if((symtype & ~0xF) == 0x40 )
494 putchar('u');
495 else if((symtype & ~0xF) == 0x80 )
496 printf("%c", "T12D456789abcdeU"[symtype&0xF]);
497 else
498 putchar('?');
499 break;
500 }
501 printf(" %s\n", symnames[i]);
502 }
503 }
504 if( !display_mode )
505 printf("\n");
506
507 return 0;
508 }
509
510 void
read_databytes()511 read_databytes()
512 {
513 static char * relstr[] = {"ERR", "DB", "DW", "DD"};
514 long l, cpos;
515 int ch, i;
516 int curseg = 0;
517 int relsize = 0;
518
519 cpos = ftell(ifd);
520 fseek(ifd, filepos+textoff, 0);
521
522 printf("\nBYTECODE\n");
523 for(;;)
524 {
525 if( (ch=get_byte()) == -1 ) break;
526
527 if( ch == 0 ) break;
528
529 switch( ch & 0xC0 )
530 {
531 case 0x00: switch(ch & 0xF0)
532 {
533 case 0x00: /* Relocator size */
534 printf("RELSZ %d\n", relsize= (ch&0xF));
535 if(relsize>3) relsize=3;
536 break;
537 case 0x10: /* Skip bytes */
538 printf("SKP %ld\n", get_sized(ch&0xF));
539 break;
540 case 0x20: /* Segment */
541 printf("SEG %x\n", curseg= (ch&0xF));
542 break;
543 default: printf("CODE %02x - unknown\n", ch);
544 goto break_break ;
545 }
546 break;
547 case 0x40: /* Raw bytes */
548 {
549 int abscnt = (ch&0x3F);
550 if( abscnt == 0 ) abscnt = 64;
551 for( i=0; i<abscnt; i++ )
552 {
553 if( (ch=get_byte()) == -1 ) break;
554 hex_output(ch);
555 }
556 hex_output(EOF);
557
558 if( ch == -1 ) goto break_break;
559 }
560 break;
561 case 0x80: /* Relocator - simple */
562 l = get_sized(relsize);
563 printf("%s SEG%x%s%s", relstr[relsize],
564 (ch&0xF),
565 (ch&0x20)?"-PC":"",
566 (ch&0x10)?"+?":"");
567 if(l)
568 printf("+0x%04lx", l);
569 putchar('\n');
570 break;
571 case 0xC0: /* Relocator - symbol relative */
572 if( ch & 0x18 )
573 {
574 printf("CODE %02x - unknown\n", ch);
575 goto break_break;
576 }
577 if( ch & 4 ) i = get_word();
578 else i = get_byte();
579 l = get_sized(ch&3);
580
581 printf("%s %s%s%s", relstr[relsize],
582 symnames[i],
583 (ch&0x20)?"-PC":"",
584 (ch&0x18)?"+?":"");
585 if(l)
586 printf("+0x%04lx", l);
587 putchar('\n');
588 break;
589 }
590 }
591 break_break:;
592 printf("\n");
593 fseek(ifd, cpos, 0);
594 }
595
596 long
get_sized(sz)597 get_sized(sz)
598 int sz;
599 {
600 switch(sz)
601 {
602 case 0: return 0;
603 case 1: return get_byte();
604 case 2: return get_word();
605 case 3: return get_long();
606 }
607 return -1;
608 }
609
610 long
get_long()611 get_long()
612 {
613 long retv = 0;
614 int i;
615 for(i=0; i<32; i+=16)
616 {
617 unsigned int v = get_word();
618 if( byte_order & 2 )
619 retv += ((long)v<<(16-i));
620 else
621 retv += ((long)v<<i);
622 }
623 return retv;
624 }
625
626 unsigned int
get_word()627 get_word()
628 {
629 long retv = 0;
630 int i;
631 for(i=0; i<16; i+=8)
632 {
633 int v = getc(ifd);
634 if( v == EOF ) return -1;
635 code_bytes++;
636 if( byte_order & 1 )
637 retv += (v<<(8-i));
638 else
639 retv += (v<<i);
640 }
641 return retv;
642 }
643
644 int
get_byte()645 get_byte()
646 {
647 int v = getc(ifd);
648 if (v == EOF) return -1;
649 code_bytes++;
650 return v;
651 }
652
653 void
hex_output(ch)654 hex_output(ch)
655 int ch;
656 {
657 static char linebuf[80];
658 static char buf[20];
659 static int pos = 0;
660
661 if( ch == EOF )
662 {
663 if(pos)
664 printf(": %.66s\n", linebuf);
665 pos = 0;
666 }
667 else
668 {
669 if(!pos)
670 memset(linebuf, ' ', sizeof(linebuf));
671 sprintf(buf, "%02x", ch&0xFF);
672 memcpy(linebuf+pos*3+(pos>7), buf, 2);
673 if( ch > ' ' && ch <= '~' ) linebuf[50+pos] = ch;
674 else linebuf[50+pos] = '.';
675 pos = ((pos+1) & 0xF);
676 if( pos == 0 )
677 {
678 printf(": %.66s\n", linebuf);
679 memset(linebuf, ' ', sizeof(linebuf));
680 }
681 }
682 }
683
684 /************************************************************************/
685 /* ELKS a.out versions
686 */
687
688 long header[12];
689 int h_len, h_flgs, h_cpu;
690
691 void
fetch_aout_hdr()692 fetch_aout_hdr()
693 {
694 int i;
695
696 header[0] = get_long();
697 header[1] = get_long();
698 byte_order = ((header[0]>>24) & 3);
699
700 h_len = (header[1] & 0xFF);
701 h_flgs = ((header[0]>>16) & 0xFF);
702 h_cpu = ((header[0]>>24) & 0xFF);
703
704 for(i=2; i<8; i++)
705 {
706 if( i*4 <= h_len )
707 header[i] = get_long();
708 else
709 header[i] = 0;
710 }
711 }
712
713 void
dump_aout()714 dump_aout()
715 {
716 static char * cpu[] = { "unknown", "8086", "m68k", "ns16k", "i386", "sparc" };
717 static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" };
718 int i;
719 long l;
720
721 if( h_cpu > 0x17 ) h_cpu &= 3;
722
723 printf("HLEN %d\n", h_len);
724 printf("CPU %s %s\n", cpu[h_cpu>>2], byteord[h_cpu&3]);
725
726 printf("FLAGS:");
727 if( h_flgs & 0x01 ) printf(" A_UZP");
728 if( h_flgs & 0x02 ) printf(" A_PAL");
729 if( h_flgs & 0x04 ) printf(" A_NSYM");
730 if( h_flgs & 0x08 ) printf(" FLG-08");
731 if( h_flgs & 0x10 ) printf(" A_EXEC");
732 if( h_flgs & 0x20 ) printf(" A_SEP");
733 if( h_flgs & 0x40 ) printf(" A_PURE");
734 if( h_flgs & 0x80 ) printf(" A_TOVLY");
735 printf("\n");
736
737 if( header[5] )
738 printf("a_entry = 0x%08lx\n", header[5]);
739 printf("a_total = 0x%08lx\n", header[6]);
740 if( header[7] )
741 printf("a_syms = 0x%08lx\n", header[7]);
742
743 if( h_len >= 36 )
744 printf("a_trsize = 0x%08lx\n", header[8]);
745 if( h_len >= 40 )
746 printf("a_drsize = 0x%08lx\n", header[9]);
747 if( h_len >= 44 )
748 printf("a_tbase = 0x%08lx\n", header[10]);
749 if( h_len >= 48 )
750 printf("a_dbase = 0x%08lx\n", header[11]);
751 printf("\n");
752
753 size_aout();
754 printf("\n");
755
756 if( header[7] )
757 {
758 printf("SYMBOLS\n");
759 nm_aout();
760 }
761 else
762 printf("NO SYMBOLS\n");
763 printf("\n");
764
765 printf("TEXTSEG\n");
766 fseek(ifd, (long)h_len, 0);
767 for(l=0; l<header[2]; l++)
768 {
769 if( (i=getc(ifd)) == EOF ) break;
770 hex_output(i);
771 }
772 hex_output(EOF);
773
774 printf("DATASEG\n");
775 fseek(ifd, (long)h_len+header[2], 0);
776 for(l=0; l<header[3]; l++)
777 {
778 if( (i=getc(ifd)) == EOF ) break;
779 hex_output(i);
780 }
781 hex_output(EOF);
782 }
783
784 void
size_aout()785 size_aout()
786 {
787 if( display_mode == 0 )
788 printf("text\tdata\tbss\tdec\thex\tfilename\n");
789
790 printf("%ld\t%ld\t%ld\t%ld\t%lx\t%s\n",
791 header[2], header[3], header[4],
792 header[2]+ header[3]+ header[4],
793 header[2]+ header[3]+ header[4],
794 ifname);
795
796 tot_size_text += header[2];
797 tot_size_data += header[3];
798 tot_size_bss += header[4];
799 }
800
801 void
nm_aout()802 nm_aout()
803 {
804 char n_name[10];
805 long n_value;
806 int n_sclass, n_numaux, n_type;
807 long bytes_left;
808 int pending_nl = 0;
809
810 fseek(ifd, h_len+header[2]+header[3]+header[8]+header[9], 0);
811
812 if( h_flgs & 4 )
813 { error("Executable has new format symbol table.\n"); return; }
814
815 bytes_left = header[7];
816
817 if( bytes_left == 0 )
818 printf("No symbols in '%s'\n", ifname);
819 else if(multiple_files && !opt_o)
820 printf("\n%s:\n", ifname);
821
822 while(bytes_left > 16)
823 {
824 if( fread(n_name, 1, 8, ifd) != 8 ) break;
825 n_name[8] = 0;
826 n_value = get_long();
827 if( (n_sclass = getc(ifd)) == EOF ) break;
828 if( (n_numaux = getc(ifd)) == EOF ) break;
829 n_type = get_word();
830
831 if( pending_nl && n_sclass == 0 )
832 {
833 printf("%s", n_name);
834 continue;
835 }
836
837 if( pending_nl ) putchar('\n');
838 if (opt_o)
839 printf("%s: ", ifname);
840 if( n_sclass == 0x10 )
841 printf(" ");
842 else
843 printf("%08lx ", n_value);
844 switch(n_sclass)
845 {
846 case 0x01: printf("a "); break;
847 case 0x12: printf("T "); break;
848 case 0x13: printf("D "); break;
849 case 0x14: printf("C "); break;
850 case 0x1a: printf("t "); break;
851 case 0x1b: printf("d "); break;
852 case 0x1c: printf("b "); break;
853 case 0x10: printf("U "); break;
854 default: if( display_mode )
855 {
856 printf("? "); break;
857 }
858
859 printf("n_sclass=");
860 switch(n_sclass>>3)
861 {
862 case 0: printf("C_NULL,"); break;
863 case 2: printf("C_EXT,"); break;
864 case 3: printf("C_STAT,"); break;
865 default: printf("%04o,", n_sclass&0xF8);
866 }
867 switch(n_sclass&7)
868 {
869 case 0: printf("N_UNDF "); break;
870 case 1: printf("N_ABS "); break;
871 case 2: printf("N_TEXT "); break;
872 case 3: printf("N_DATA "); break;
873 case 4: printf("N_BSS "); break;
874 case 5: printf("N_COMM "); break;
875 default: printf("%o ", n_sclass&7); break;
876 }
877 break;
878 }
879
880 if( display_mode == 0 )
881 {
882 if( n_numaux )
883 printf("n_numaux=%02x ", n_numaux);
884 if( n_type )
885 printf("n_type=%04x ", n_type);
886 }
887
888 printf("%s", n_name);
889
890 pending_nl=1;
891 }
892
893 if( pending_nl ) putchar('\n');
894 }
895
896 #ifndef VERY_SMALL_MEMORY
897 /************************************************************************/
898 /* V7 a.out versions
899 */
900
901 void
fetch_v7_hdr()902 fetch_v7_hdr()
903 {
904 int i;
905
906 h_len = 8;
907 for(i=0; i<h_len; i++)
908 {
909 header[i] = get_word();
910 }
911 }
912
913 void
size_v7()914 size_v7()
915 {
916 if( display_mode == 0 )
917 printf("text\tdata\tbss\tdec\thex\tfilename\n");
918
919 printf("%ld\t%ld\t%ld\t%ld\t%lx\t%s\n",
920 header[1], header[2], header[3],
921 header[1]+ header[2]+ header[3],
922 header[1]+ header[2]+ header[3],
923 ifname);
924
925 tot_size_text += header[1];
926 tot_size_data += header[2];
927 tot_size_bss += header[3];
928 }
929
930 void
dump_v7()931 dump_v7()
932 {
933 int i;
934 long l;
935
936 printf("TYPE:");
937 switch (header[0]) {
938 case 0405: printf(" overlay"); break;
939 case 0407: printf(" impure"); break;
940 case 0410: printf(" read-only text"); break;
941 case 0411: printf(" pure"); break;
942 case 0413: printf(" demand load"); break;
943 default: printf(" (unknown)"); break;
944 }
945 printf("\n");
946
947 if( header[5] )
948 printf("a_entry = 0x%08lx\n", header[5]);
949 printf("\n");
950
951 size_aout();
952 printf("\n");
953
954 printf("TEXTSEG\n");
955 fseek(ifd, (long)h_len, 0);
956 for(l=0; l<header[1]; l++)
957 {
958 if( (i=getc(ifd)) == EOF ) break;
959 hex_output(i);
960 }
961 hex_output(EOF);
962
963 printf("DATASEG\n");
964 fseek(ifd, (long)h_len+header[1], 0);
965 for(l=0; l<header[2]; l++)
966 {
967 if( (i=getc(ifd)) == EOF ) break;
968 hex_output(i);
969 }
970 hex_output(EOF);
971 }
972 #endif
973