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