|
|
1.1 root 1: /*
2: * static char dis_utls_ID[] = "@(#)dis_utls.c 1.25 12/15/83";
3: */
4: #define DEBUG
5: #include <stdio.h>
6: #include <ar.h>
7: #include "dis.h"
8: #include "filehdr.h"
9: #include "ldfcn.h"
10: #include "sgs.h"
11: #include "scnhdr.h"
12: #include "linenum.h"
13: #include "syms.h"
14: #include "structs.h"
15: #ifdef OLIST
16: #include "olist_defs.h"
17: #endif
18:
19: #ifndef OLIST
20: #define TOOL "dis"
21: #endif
22: /*
23: * The following #define is necessary so that the disassembler
24: * will run on UNIX 370 3.0 and UNIX 370 4.0 (printf was changed).
25: *
26: */
27: #ifndef UNIX
28: #define UNIX 3
29: #endif
30:
31: #define FUNC_NM 0 /* for line_nums func, indicates the */
32: /* line number entry value for the */
33: /* beginning of a function */
34: #define BADADDR -1L /* used by the resynchronization */
35: /* function to indicate that a restart */
36: /* candidate has not been found */
37:
38: #ifdef OLIST
39: extern struct files *curfile;
40: extern char linebuf[];
41: #endif
42:
43: /*
44: * This structure is used for storing data needed for the looking up
45: * of symbols for labels or functions. It consists of a pointer to a
46: * structure describing a symbol table entry, and a pointer to another
47: * structure of its own type (a forward linked list will be created).
48: */
49:
50: struct SYMLINK {
51: SYMENT *element;
52: struct SYMLINK *next;
53: };
54:
55: /*
56: * To look up labels, a linked list of 'struct SYMLINK' will be
57: * searched. 'num_labels' will be set to the number of label
58: * entries that exist, and 'head_ptr' will point to the head
59: * of this list.
60: */
61:
62: static int num_labels = 0;
63: static struct SYMLINK *head_ptr;
64: #ifdef OLIST
65: static int firsttime = 1;
66: #endif
67:
68: /*
69: * To store the names and addresses of all the functions in the symbol
70: * table, SYMLINK is used so that all symbol information is collected
71: * for flexname purposes.
72: * In the previous version, only the name and address of the symbol
73: * was saved.
74: */
75:
76:
77: extern unsigned short num_funcs;
78: static struct SYMLINK *func_ptr;
79:
80: /*
81: * To store the name of each section and associate it with its section
82: * number, an array of pointers is used.
83: */
84:
85: static char **section;
86:
87: /*
88: * The following declarations provide space for the current
89: * lint number entry and the number of line numbers that have
90: * been read
91: */
92: static LINENO line_ent;
93: static unsigned short lnno_cnt;
94:
95: FUNCLIST *currfunc;
96:
97: /*
98: * build_labels ()
99: *
100: * Construct an array containing all the label entries in the
101: * symbol table. (This will be a forward linked structure.)
102: * Then construct an array containing each section name,
103: * associating the section name with its section number by its
104: * index. This is needed in looking up the labels.
105: */
106:
107: build_labels()
108: {
109: /* the following items are from _extn.c */
110: extern FILHDR filhdr;
111: extern LDFILE *f_ptr,
112: *symb;
113: extern char *fname;
114: extern int trace,
115: Lflag,
116: save_Lflag;
117: SCNHDR sect_hdr;
118: LDFILE *sect_ptr;
119: unsigned short j;
120: long limit;
121: struct SYMLINK *current;
122: char *calloc();
123: SYMENT sym_ent;
124: SYMENT *sym_ptr = &sym_ent;
125: long sym_cnt;
126:
127: if ((filhdr.f_flags & F_LSYMS) || (filhdr.f_symptr == NULL)) {
128: printf("\nfile %s has been stripped of labels\n",fname);
129: /* if labels are stripped off save the value of Lflag */
130: save_Lflag = Lflag;
131: Lflag = -1;
132: return;
133: }
134:
135: limit = filhdr.f_nsyms; /* # of symbol table entries */
136:
137: /*
138: * Allocate for link structure of first element.
139: */
140:
141: if ((head_ptr = (struct SYMLINK *) calloc(1,sizeof(struct SYMLINK))) == NULL) {
142: fprintf( stderr, "memory allocation failure on call to calloc");
143: exit(0);
144: }
145:
146: current = head_ptr; /* point to first entry */
147:
148: /*
149: * Allocate for symbol structure of first element.
150: */
151:
152: if ((current->element = (SYMENT *) calloc(1,SYMESZ)) == NULL) {
153: fprintf( stderr, "memory allocation failure on call to calloc");
154: exit(0);
155: }
156:
157: /*
158: * initialize all needed for get_sym()
159: */
160:
161: ldtbseek(symb);
162:
163: /*
164: * Search the whole symbol table looking for elements
165: * with a storage class of label (C_LABEL)
166: */
167:
168: for( sym_cnt = 0; sym_cnt < limit; sym_cnt++ ) {
169: if (ldtbread( symb, sym_cnt, sym_ptr ) == FAILURE)
170: {
171: fprintf( stderr, "%s%s: %s: cannot read symbol table\n",
172: SGS, TOOL, fname );
173: exit(1);
174: }
175: if (trace > 0) {
176: printf("\nsym name %s\tsec # %d\tstor cl %d\n",
177: sym_ptr->n_name,
178: sym_ptr->n_scnum,
179: sym_ptr->n_sclass);
180: }
181: if (sym_ptr->n_sclass == C_LABEL) {
182:
183: /* if it's a label add it to the list */
184:
185: #ifdef FLEXNAMES
186: current->element->n_zeroes=sym_ptr->n_zeroes;
187: current->element->n_offset=sym_ptr->n_offset;
188: #else
189: strcpy(current->element->n_name,sym_ptr->n_name);
190: #endif
191: current->element->n_value = sym_ptr->n_value;
192: current->element->n_scnum = sym_ptr->n_scnum;
193: current->element->n_type = sym_ptr->n_type;
194: current->element->n_sclass = sym_ptr->n_sclass;
195: current->element->n_numaux = sym_ptr->n_numaux;
196:
197: /*
198: * Obtain space for another link structure.
199: */
200:
201: if ((current->next = (struct SYMLINK *) calloc(1,sizeof(struct SYMLINK))) == NULL) {
202: fprintf( stderr, "memory allocation failure on call to calloc");
203: exit(0);
204: }
205:
206: current = current->next;
207:
208: /*
209: * Obtain space for another symbol element.
210: */
211:
212: if ((current->element = (SYMENT *) calloc(1,SYMESZ)) == NULL) {
213: fprintf( stderr, "memory allocation failure on call to calloc");
214: exit(0);
215: }
216: num_labels++;
217: }
218: sym_cnt += sym_ptr->n_numaux;
219: }
220: current->next = NULL;
221:
222: sect_ptr = NULL;
223: sect_ptr = ldaopen(fname,f_ptr);
224:
225: /*
226: * now build an array to store the pointers to the names of
227: * each section. First allocate a pointer for each section.
228: */
229:
230: if ((section = (char **) calloc(filhdr.f_nscns + 1, sizeof(section))) == NULL) {
231: fprintf( stderr, "memory allocation failure on call to calloc");
232: exit(0);
233: }
234:
235: /*
236: * now have section[0] point to a block of memory big enough to
237: * hold all the section names (their size has 1 added to
238: * account for a trailing '\0').
239: */
240:
241: if ((*section = calloc ( filhdr.f_nscns + 1, (sizeof(sect_hdr.s_name)+1))) == NULL) {
242: fprintf( stderr, "memory allocation failure on call to calloc");
243: exit(0);
244: }
245:
246: /*
247: * now read and assign the section names. One will note that
248: * the allocated memory for the first name is not used. This
249: * does not cause us to run out of space, though, since '1'
250: * was added above in allocating space.
251: */
252:
253: for (j = 1; j < filhdr.f_nscns; j++) {
254: ldshread(sect_ptr, j, §_hdr);
255: section[j] = section[j-1] + sizeof(sect_hdr.s_name) + 1;
256: sprintf(section[j],"%-.8s",sect_hdr.s_name);
257: }
258: ldaclose(sect_ptr);
259: }
260:
261: /*
262: * compoff (lng, temp)
263: *
264: * This routine will compute the location to which control is to be
265: * transferred. 'lng' is the number indicating the jump amount
266: * (already in proper form, meaning masked and negated if necessary)
267: * and 'temp' is a character array which already has the actual
268: * jump amount. The result computed here will go at the end of 'temp'.
269: * (This is a great routine for people that don't like to compute in
270: * hex arithmetic.)
271: */
272:
273: compoff(lng, temp)
274: long lng;
275: char *temp;
276: {
277: extern int oflag; /* from _extn.c */
278: extern long loc; /* from _extn.c */
279:
280: lng += loc;
281: if (oflag)
282: sprintf(temp,"%s <%lo>",temp,lng);
283: else
284: sprintf(temp,"%s <%lx>",temp,lng);
285: }
286: /*
287: * convert (num, temp, flag)
288: *
289: * Convert the passed number to either hex or octal, depending on
290: * the oflag, leaving the result in the supplied string array.
291: * If LEAD is specified, preceed the number with '0' or '0x' to
292: * indicate the base (used for information going to the mnemonic
293: * printout). NOLEAD will be used for all other printing (for
294: * printing the offset, object code, and the second byte in two
295: * byte immediates, displacements, etc.) and will assure that
296: * there are leading zeros.
297: */
298:
299: convert(num,temp,flag)
300: unsigned num;
301: char temp[];
302: int flag;
303:
304: {
305: extern int oflag; /* in _extn.c */
306:
307: #if UNIX < 4
308: #ifdef B16
309: if (flag == NOLEAD)
310: (oflag) ? sprintf(temp,"%03o",num):
311: sprintf(temp,"%02x",num);
312: #else
313: if (flag == NOLEAD)
314: (oflag) ? sprintf(temp,"%06o",num):
315: sprintf(temp,"%04x",num);
316: #endif /* B16 */
317: #else
318: #ifdef B16
319: if (flag == NOLEAD)
320: (oflag) ? sprintf(temp,"%.3o",num):
321: sprintf(temp,"%.2x",num);
322: #else
323: if (flag == NOLEAD)
324: (oflag) ? sprintf(temp,"%.6o",num):
325: sprintf(temp,"%.4x",num);
326: #endif /* B16 */
327: #endif /* UNIX < 4 */
328: if (flag == LEAD)
329: (oflag) ? sprintf(temp,"0%o",num):
330: sprintf(temp,"0x%x",num);
331: }
332: /*
333: * dis_data ()
334: *
335: * the routine to disassemble a data section,
336: * which consists of just dumping it with byte offsets
337: */
338:
339: dis_data( sectp )
340: SCNLIST *sectp;
341:
342: {
343: extern SCNHDR scnhdr; /* from _extn.c */
344: extern int oflag; /* from _extn.c */
345: extern int trace; /* from _extn.c */
346: extern short aflag; /* from _extn.c */
347: extern long loc; /* from _extn.c */
348: extern char mneu[]; /* from _extn.c */
349: extern char object[];/* from _extn.c */
350: extern unsigned short cur2bytes; /* from _extn.c */
351: extern LDFILE *f_ptr;
352: extern char *fname;
353:
354: LDFILE *d_ptr;
355: short count;
356: long last_addr;
357:
358: scnhdr = sectp->shdr;
359: d_ptr = ldaopen( fname, f_ptr );
360: ldsseek( d_ptr, sectp->scnum );
361:
362: /* Blank out mneu so the printline routine won't print extraneous
363: * garbage.
364: */
365:
366: sprintf(mneu,"");
367: if (scnhdr.s_nlnno != 0){
368: fprintf(stderr,"\n%sdis: QUIRK--data section has line number entries",SGS);
369: printf("\n Are you sure this was a data section?!\n");
370: }
371:
372: if (trace > 0){
373: printf("\ntrace: section name %s\n",scnhdr.s_name);
374: printf("\ntrace: section size %x\n",scnhdr.s_size);
375: }
376:
377: for (loc = aflag? scnhdr.s_paddr: 0, last_addr = loc + scnhdr.s_size;
378: loc < last_addr; printline()) {
379: /* if -da flag specified, actual adress will be printed
380: if -d flag specified, offset within section will be printed */
381: printf("\t");
382: prt_offset();
383: #ifdef B16
384: for (count=0; (count<6) && (loc<last_addr); count++)
385: getbyte(d_ptr);
386: #endif
387: #ifdef MC68
388: for (count=0; (count<8) && (loc<last_addr); count+=2)
389: get2bytes(d_ptr);
390: #endif
391: #ifdef N3B
392: for (count=0; (count<8) && (loc<last_addr); count+=2)
393: get2bytes(d_ptr);
394: #endif
395: #ifdef M32
396: for (count=0; (count<8) && (loc<last_addr); count+=2)
397: /* bytes of data are swapped so they must be swapped back */
398: getswapb2(d_ptr);
399: #endif /* M32 */
400: }
401:
402: }
403: #if U3B | N3B | U3B5 | M32
404: /*
405: * dfpconv(fpword1, fpword2, fpdoub, fpshort)
406: *
407: * This routine will convert the 2 longs (64 bit) "fpword1 fpword2" double
408: * precision floating point representation of a number into its decimal
409: * equivalent. The result will be stored in *fpdoub. The routine will
410: * return a value indicating what type of floating point number was
411: * converted.
412: * *NOTE* The conversion routine will calculate a decimal value
413: * if the disassembler is to run native mode on the 3B.
414: * If the 3B disassembler is to be run on a DEC processor
415: * (pdp11 or vax) the routine will store the exponent in
416: * *fpshort. The mantissa will be stored in the form:
417: * "T.fraction" where "T" is the implied bit and the
418: * fraction is of radix 2. The mantissa will be stored
419: * in *fpdoub. This is due to the difference in range
420: * of floating point numbers between the 3B and DEC
421: * processors.
422: */
423: dfpconv(fpword1, fpword2, fpdoub, fpshort)
424: long fpword1, fpword2;
425: double *fpdoub;
426: short *fpshort;
427: {
428: unsigned short exponent;
429: short leadbit, signbit;
430: double dtemp, dec2exp, mantissa;
431: long ltemp;
432:
433: exponent = (unsigned short)((fpword1>>20) & 0x7ffL);
434: /* exponent is bits 1-11 of the double */
435:
436: ltemp = fpword1 & 0xfffffL; /* first 20 bits of mantissa */
437: mantissa = ((double)ltemp * TWO_32) + (double)fpword2;
438: /* mantissa is bits 12-63 of the double */
439:
440: signbit = (short)((fpword1>>31) & 0x1L);
441: /* sign bit (1-negative, 0-positive) is bit 0 of double */
442:
443: leadbit = 1;
444: /* implied bit to the left of the decimal point */
445:
446: if (exponent==2047)
447: if (mantissa)
448: return(NOTANUM);
449: else
450: return((signbit)? NEGINF: INFINITY);
451:
452: if (exponent==0)
453: if (mantissa)
454: /* This is a denormalized number. The implied bit to
455: * the left of the decimal point is 0.
456: */
457: leadbit = 0;
458: else
459: return((signbit)? NEGZERO: ZERO);
460:
461: /*
462: * Convert the 52 bit mantissa into "I.fraction" where
463: * "I" is the implied bit. The 52 bits are divided by
464: * 2 to the 52rd power to transform the mantissa into a
465: * fraction. Then the implied bit is added on.
466: */
467: dtemp = (double)(leadbit + (mantissa/TWO_52));
468:
469: #if U3B | U3B5
470: /* Calculate 2 raised to the (exponent-BIAS) power and
471: * store it in a double.
472: */
473: if (exponent < DBIAS)
474: for(dec2exp=1; exponent < DBIAS; ++exponent)
475: dec2exp /= 2;
476: else
477: for(dec2exp=1; exponent > DBIAS; --exponent)
478: dec2exp *= 2;
479:
480: /* Multiply "I.fraction" by 2 raised to the (exponent-BIAS)
481: * power to obtain the decimal floating point number.
482: */
483: *fpdoub = dtemp *dec2exp;
484:
485: if (signbit)
486: *fpdoub = -(*fpdoub);
487: return(FPNUM);
488: #else
489: *fpshort = exponent - DBIAS;
490: *fpdoub = ((signbit)? (-dtemp): dtemp);
491: return(FPBIGNUM);
492: #endif /* U3B | U3B5 */
493: }
494: #endif /* U3B | N3B | U3B5 | M32 */
495:
496: /*
497: * getbyte (ptr)
498: *
499: * read a byte, mask it, then return the result in 'curbyte'.
500: * The getting of all single bytes is done here. The 'getbyte[s]'
501: * routines are the only place where the global variable 'loc'
502: * is incremented.
503: */
504: int
505: getbyte(ptr)
506: LDFILE *ptr;
507:
508: {
509: extern long loc; /* from _extn.c */
510: extern unsigned short curbyte; /* from _extn.c */
511: extern char object[]; /* from _extn.c */
512: char temp[NCPS+1];
513: char byte;
514:
515: if ( FREAD(&byte,sizeof(byte),1,ptr) == NULL){
516: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL);
517: exit(4);
518: }
519: loc++;
520: curbyte = byte & 0377;
521: convert(curbyte, temp, NOLEAD);
522: sprintf(object,"%s%s ",object,temp);
523: }
524: /*
525: * lookbyte (ptr)
526: *
527: * read a byte, mask it, then return the result in 'curbyte'.
528: * The byte is not immediately placed into the string object[].
529: * is incremented.
530: */
531:
532: int
533: lookbyte(ptr)
534: LDFILE *ptr;
535:
536: {
537: extern long loc; /* from _extn.c */
538: extern unsigned short curbyte; /* from _extn.c */
539: char byte;
540:
541: if ( FREAD(&byte,sizeof(byte),1,ptr) == NULL){
542: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL);
543: exit(4);
544: }
545: loc++;
546: curbyte = byte & 0377;
547: }
548:
549: /*
550: * get2bytes(ptr)
551: *
552: * This routine will get 2 bytes, print them in the object file
553: * and place the result in 'cur2bytes'.
554: */
555:
556: int
557: get2bytes(ptr)
558: LDFILE *ptr;
559: {
560: extern long loc; /* from _extn.c */
561: extern unsigned short cur2bytes; /* from _extn.c */
562: extern char object[]; /* from _extn.c */
563: char temp[NCPS+1];
564: extern int trace;
565:
566: if ( FREAD(&cur2bytes,sizeof(cur2bytes),1,ptr) == NULL){
567: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL);
568: exit(4);
569: }
570: loc += 2;
571: convert( (cur2bytes & 0xffff), temp, NOLEAD);
572: sprintf(object,"%s%s ",object, temp);
573: if (trace > 1)
574: printf("\nin get2bytes object<%s>\n",object);
575: }
576: #ifdef M32
577: /*
578: * getswapb2(ptr)
579: *
580: * This routine is used only for m32 and m32a. It will get and
581: * swap 2 bytes, print them in the object file and place the
582: * result in 'cur2bytes'.
583: */
584:
585: int
586: getswapb2(ptr)
587: LDFILE *ptr;
588: {
589: extern long loc; /* from _extn.c */
590: extern unsigned short cur2bytes; /* from _extn.c */
591: extern char object[]; /* from _extn.c */
592: char temp[NCPS+1];
593: extern int trace;
594:
595: if ( FREAD(&cur2bytes,sizeof(cur2bytes),1,ptr) == NULL){
596: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL);
597: exit(4);
598: }
599: loc += 2;
600: /* swap the 2 bytes contained in 'cur2bytes' */
601: cur2bytes = ((cur2bytes>>8) & (unsigned short)0x00ff) |
602: ((cur2bytes<<8) & (unsigned short)0xff00);
603: convert( (cur2bytes & 0xffff), temp, NOLEAD);
604: sprintf(object,"%s%s ",object, temp);
605: if (trace > 1)
606: printf("\nin getswapb2 object<%s>\n",object);
607: }
608: #endif
609: /*
610: * get4bytes(ptr)
611: *
612: * This routine will bet 4 bytes, print them in the object and
613: * place the results in 'cur4bytes'.
614: */
615:
616: get4bytes(ptr)
617: LDFILE *ptr;
618: {
619: extern long loc; /* from _extn.c */
620: #ifdef AR32WR
621: extern unsigned long cur4bytes; /* from _extn.c */
622: #else
623: extern long cur4bytes;
624: #endif
625: extern unsigned short cur2bytes; /* from _extn.c */
626: extern char object[]; /* from _extn.c */
627: char temp[NCPS+1];
628: unsigned send;
629: extern int trace; /* in _extn.c */
630: #ifdef AR32WR
631: unsigned long tempvax;
632: #endif
633:
634: if ( FREAD(&cur4bytes,sizeof(cur4bytes),1,ptr) == NULL){
635: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL);
636: exit(4);
637: }
638:
639: loc += 4;
640: #ifdef AR32WR
641: tempvax = (( cur4bytes >>16 ) & 0xffffL);
642: cur4bytes = (( cur4bytes <<16 ) | tempvax);
643: #endif
644: send = (cur4bytes >> 16) & 0xffffL;
645: convert(send, temp, NOLEAD);
646: sprintf(object,"%s%s ",object,temp);
647: cur2bytes = cur4bytes & 0xffffL;
648: send = cur4bytes & 0xffffL;
649: convert(send, temp, NOLEAD);
650: sprintf(object,"%s%s ",object,temp);
651: if (trace > 1)
652: printf("\nin get4bytes object<%s>\n",object);
653: }
654: /*
655: * label_free ()
656: *
657: * Free all the space that has been allocated which would be the space
658: * for section names plus those label entries that are not already free.
659: */
660:
661: label_free()
662:
663: {
664: struct SYMLINK *temp;
665: int i;
666:
667: cfree(section[0]);
668: cfree(section);
669:
670: for (i = 0; i < num_labels; i++) {
671: temp = head_ptr;
672: head_ptr = head_ptr->next;
673: free(temp->element);
674: free(temp);
675: }
676:
677: }
678: /*
679: * lib_free ()
680: *
681: * After all the files have been processed, free the space that was
682: * allocated for libraries that were disassembled.
683: */
684:
685: lib_free()
686:
687: {
688: /* the following array is from _extn.c */
689: extern char *libs[];
690: extern int lflag; /* from _extn.c */
691: int i;
692:
693: for (i = lflag; i > 0; i--)
694: free(libs[i]);
695:
696: }
697:
698: /*
699: * line_nums ()
700: *
701: * This function prints out the names of functions being disassembled
702: * and break-pointable line numbers. First it checks the address
703: * of the next function in the list of functions; if if matches
704: * the current location, it prints the name of that function.
705: *
706: * It then examines the line number entries. If the address of the
707: * current line number equals that of the current location, the
708: * line number is printed.
709: */
710: line_nums()
711: {
712: /* the following items are from _extn.c */
713: extern LDFILE *l_ptr,
714: *t_ptr,
715: *symb,
716: *symb_ptr;
717:
718: extern SCNHDR scnhdr;
719: extern FILHDR filhdr;
720: extern int trace;
721: extern int oflag;
722: #ifndef OLIST
723: extern int fflag;
724: #endif
725: extern long loc;
726: extern FUNCLIST *next_function;
727: extern FUNCLIST *currfunc;
728: #ifdef OLIST
729: extern int nosource;
730: extern int funcs_listed;
731: #endif
732:
733: SYMENT sym_ent;
734: SYMENT *sym_ptr = &sym_ent;
735: long sym_cnt;
736: char *flexname, /* pointer to flexname returned by ldgetname */
737: *ldgetname();
738: LINENO *lnno_ptr = &line_ent;
739:
740: #ifdef OLIST
741: linebuf[0] = '\0';
742: #endif
743:
744: while (next_function != NULL)
745: {
746: /* not there yet */
747: if (loc < next_function->faddr)
748: break;
749:
750: if (loc > next_function->faddr)
751: {
752: /* this is an error condition */
753: fflush( stdout );
754: fprintf( stderr, "\nWARNING: Possible strings in text or bad physical address before location ");
755: if (oflag)
756: fprintf( stderr, "0%lo\n", loc );
757: else
758: fprintf( stderr, "0x%lx\n", loc );
759: FSEEK( t_ptr, (next_function->faddr - scnhdr.s_paddr) + scnhdr.s_scnptr, 0);
760: loc = next_function->faddr;
761: }
762:
763: /* loc == next_function->addr, so print the function name */
764: #if OLIST
765: funcs_listed++;
766: if (nosource == TRUE)
767: printf( "\t" );
768: else if (curfile->f_nam[ strlen( curfile->f_nam ) -1] == 's')
769: printf( "\n\@FUNCTION: %s\n\n", next_function->funcnm );
770: #endif
771: printf("%s()\n", next_function->funcnm );
772: currfunc = next_function;
773: next_function = next_function->nextfunc;
774: }
775:
776: if (scnhdr.s_lnnoptr != NULL)
777: {
778: #if OLIST
779: /* read the first one for the section */
780: if (loc == scnhdr.s_paddr || firsttime)
781: {
782: firsttime = 0;
783: FSEEK( l_ptr, scnhdr.s_lnnoptr, 0 );
784: lnno_cnt = 0;
785: if (FREAD( (char *) lnno_ptr, LINESZ,1, l_ptr ) != 1)
786: fatal( "cannot read line numbers" );
787: }
788: #else
789: if (loc == scnhdr.s_paddr)
790: {
791: if (fflag) {
792: if ((ldlinit(l_ptr, currfunc->fcnindex)) == FAILURE)
793: return;
794: } else
795: FSEEK( l_ptr, scnhdr.s_lnnoptr, 0 );
796: lnno_cnt = 0;
797: if (FREAD( (char *) lnno_ptr, LINESZ,1, l_ptr ) != 1)
798: fatal( "cannot read line numbers" );
799: }
800: #endif
801:
802: for ( ; lnno_cnt < scnhdr.s_nlnno; )
803: {
804: if (lnno_ptr->l_lnno == FUNC_NM)
805: {
806: if (currfunc && lnno_ptr->l_addr.l_symndx == currfunc->fcnindex)
807: {
808: /* if the function matches the last one
809: * printed, skip the line number entry
810: */
811: if (FREAD((char *) lnno_ptr, LINESZ,1, l_ptr ) !=1 )
812: fatal( "cannot read line numbers" );
813: lnno_cnt++;
814: }
815: else
816: {
817: /* should never get here. All of the
818: * functions should be in the function
819: * list, but the code is here just
820: * in case
821: */
822: if (ldtbread( symb_ptr, lnno_ptr->l_addr.l_symndx, sym_ptr ) == FAILURE)
823: fatal( "cannot read symbol table");
824: if (sym_ptr->n_value > loc)
825: break;
826: if (sym_ptr->n_value < loc)
827: #if OLIST
828: if (sym_ptr->n_value < curfile->tbegin)
829: {
830: lnno_cnt += 1;
831: if (FREAD ((char *) lnno_ptr, LINESZ, 1, l_ptr ) != 1)
832: fatal("cannot read line numbers");
833: continue;
834: }
835: else
836: #endif
837: {
838: fflush( stdout );
839: fprintf( stderr, "\nWARNING: Possible strings in text or bad physical address before location " );
840: if (oflag)
841: fprintf( stderr, "0%lo\n", loc);
842: else
843: fprintf(stderr, "0x%lx\n", loc);
844: FSEEK(t_ptr, (sym_ptr->n_value - scnhdr.s_paddr) + scnhdr.s_scnptr, BEGINNING);
845: loc = sym_ptr->n_value;
846: }
847:
848: /* the address of the function matches so print its name */
849: if(!(flexname = ldgetname(symb_ptr, sym_ptr)))
850: fprintf(stderr, "ldgetname returned 0\n");
851: #ifdef OLIST
852: if (nosource == TRUE )
853: printf("\t");
854: else if (curfile->f_nam[strlen(curfile->f_nam)-1] =='s')
855: printf("\n\\@FUNCTION: %s\n\n", flexname);
856: #endif
857: printf("%s()\n",flexname);
858: lnno_cnt += 1;
859: if (FREAD( lnno_ptr, LINESZ, 1, l_ptr ) != 1)
860: fatal( "cannot read line numbers\n");
861: }
862: }
863: else
864: {
865: /* this is just a line number entry */
866: #ifdef OLIST
867: if ((loc == lnno_ptr->l_addr.l_paddr) && (nosource != TRUE))
868: sprintf(linebuf, "%s[%-d%]", linebuf, lnno_ptr->l_lnno);
869: #else
870: if (loc == lnno_ptr->l_addr.l_paddr)
871: printf("[%d]",lnno_ptr->l_lnno);
872: #endif
873: else if (loc < lnno_ptr->l_addr.l_paddr)
874: break;
875: if (FREAD( lnno_ptr, LINESZ, 1, l_ptr ) != 1)
876: fatal( "cannot read line numbers\n" );
877: lnno_cnt++;
878: }
879: }
880: }
881:
882: #ifndef OLIST
883: printf("\t");
884: #endif
885: }
886:
887: /*
888: * looklabel (addr, sect_num)
889: *
890: * This function will look in the symbol table to see if
891: * a label exists which may be printed.
892: */
893:
894: looklabel(addr, sect_num)
895: long addr;
896: unsigned short sect_num;
897:
898: {
899: struct SYMLINK *current,
900: *previous;
901: int i;
902: extern LDFILE *symb_ptr;
903: char *flexname,
904: *ldgetname();
905:
906: current = head_ptr;
907: previous = current;
908:
909: for (i = 0; i < num_labels; i++) {
910:
911: /* both the address and section number must match */
912: if (current->element->n_value == addr &&
913: current->element->n_scnum == sect_num) {
914:
915: /* found the label so print it */
916: if(!(flexname = ldgetname(symb_ptr, current->element))) {
917: fprintf(stderr, "ldgetname returned 0\n");
918: }
919: printf("%s:\n",flexname);
920:
921: /* now free up the space occupied by the */
922: /* found element */
923:
924: if (current == head_ptr)
925: head_ptr = head_ptr->next;
926:
927: previous->next = current->next;
928: free (current->element);
929: free(current);
930: num_labels--;
931: return;
932: }
933: /* didn't find a label yet, so go to the next label */
934: previous = current;
935: current = current->next;
936: }
937: }
938:
939: /*
940: * printline ()
941: *
942: * Print the disassembled line, consisting of the object code
943: * and the mnemonics. The breakpointable line number, if any,
944: * has already been printed, and 'object' contains the offset
945: * within the section for the instruction.
946: */
947:
948: printline()
949:
950: {
951: extern int oflag; /* in _extn.c */
952: extern char object[];
953: extern char mneu[];
954: #ifdef OLIST
955: extern int nosource;
956: #endif
957:
958: #ifdef B16
959: (oflag > 0) ?
960: printf("%-36s%s\n",object,mneu): /* to print octal */
961: printf("%-30s%s\n",object,mneu); /* to print hex */
962: #endif
963: #ifdef MC68
964: (oflag > 0) ?
965: printf("%-36s%s\n",object,mneu): /* to print octal */
966: printf("%-37s%s\n",object,mneu); /* to print hex */
967: #endif
968: #ifdef N3B
969: #ifdef OLIST
970: if (nosource == TRUE) return;
971: printf("%-46s%-8s%s\n", object, linebuf, mneu);
972: #else
973: (oflag > 0) ?
974: printf("%-36s%s\n",object,mneu): /* to print octal */
975: printf("%-37s%s\n",object,mneu); /* to print hex */
976: #endif
977: #endif
978: #ifdef M32
979: (oflag > 0) ?
980: printf("%-36s%s\n",object,mneu): /* to print octal */
981: printf("%-37s%s\n",object,mneu); /* to print hex */
982: #endif /* M32 */
983: }
984: /*
985: * prt_offset ()
986: *
987: * Print the offset, right justified, followed by a ':'.
988: */
989:
990:
991: prt_offset()
992:
993: {
994: extern long loc; /* from _extn.c */
995: extern int oflag;
996: extern char object[];
997:
998: #ifdef OLIST
999: if (oflag)
1000: sprintf(object,"0%.7lo ", loc);
1001: else
1002: sprintf(object, "0x%.6lx ", loc);
1003: #else
1004: if (oflag)
1005: sprintf(object,"%6lo: ",loc);
1006: else
1007: sprintf(object,"%4lx: ",loc);
1008: #endif
1009: }
1010: /*
1011: * resync ()
1012: *
1013: * If a bad op code is encountered, the disassembler will attempt
1014: * to resynchronize itself. The next line number entry and the
1015: * next function symbol table entry will be found. The restart
1016: * point will be the smaller of these two addresses and bytes
1017: * of object code will be dumped (not disassembled) until the
1018: * restart point is reached.
1019: */
1020:
1021:
1022: resync()
1023:
1024: {
1025: /* the following 7 items are from _extn.c */
1026: extern char *fname;
1027: extern char *sname;
1028: extern LDFILE *f_ptr;
1029: extern LDFILE *t_ptr;
1030: extern LDFILE *l_ptr;
1031: extern LDFILE *symb;
1032: extern FILHDR filhdr;
1033: extern SCNHDR scnhdr;
1034: extern long loc;
1035: extern FUNCLIST *next_function;
1036: extern FUNCLIST *currfunc;
1037: extern char mneu[];
1038: extern int nosyms;
1039: #if OLIST
1040: extern int funcs_listed;
1041: extern int nosource;
1042: #endif
1043:
1044: #if AR16WR && !OLIST
1045: static long firstfn = -1L;
1046: #endif
1047:
1048: struct lineno *eptr = &line_ent;
1049: struct syment sentry, stbentry, *septr;
1050: long paddr, sindex, linaddr, symaddr, dumpaddr, s_end;
1051:
1052: linaddr = BADADDR;
1053: symaddr = BADADDR;
1054: s_end = scnhdr.s_paddr + scnhdr.s_size;
1055: /* Find the next line number entry if the file has not been
1056: * stripped of line number information. Each entry from the
1057: * beginning will be read until one having a greater address
1058: * than the present location is found.
1059: */
1060: if (nosyms == TRUE) {
1061: printf ("\n\t** FILE IS STRIPPED **\t\n");
1062: printf ("\t** SKIP TWO BYTES AND TRY AGAIN **\n");
1063: return(SUCCESS);
1064: }
1065: if (stripped() != TRUE)
1066: {
1067: for( ; lnno_cnt < scnhdr.s_nlnno; lnno_cnt++ )
1068: {
1069: if (eptr->l_lnno == 0) {
1070: if (symb == NULL)
1071: break;
1072: ldtbread(symb, eptr->l_addr.l_symndx, &sentry);
1073: linaddr = sentry.n_value;
1074: if (loc <= linaddr)
1075: goto symfind;
1076: }
1077: else if (eptr->l_addr.l_paddr >= loc) {
1078: linaddr = eptr->l_addr.l_paddr;
1079: goto symfind;
1080: }
1081: FREAD(eptr, LINESZ, 1, l_ptr);
1082: }
1083: /* Cannot restart based on line number information.
1084: * Try to use symbol table information to find restart
1085: * point.
1086: */
1087: if (symb == NULL)
1088: linaddr = BADADDR;
1089: else
1090: /* If no further line numbers have been found,
1091: * the address of the section end will be a
1092: * candidate for a restart point.
1093: */
1094: linaddr = s_end;
1095: }
1096: symfind:
1097: /* Find next function symbol table entry. */
1098: for( ; next_function; currfunc = next_function, next_function = next_function->nextfunc )
1099: if (next_function->faddr >= loc)
1100: {
1101: symaddr = next_function->faddr;
1102: break;
1103: }
1104: #if OLIST
1105: else
1106: funcs_listed += 1;
1107:
1108: if (next_function == NULL)
1109: symaddr = curfile->tend;
1110: #else
1111: #if AR32W || AR32WR
1112: if (next_function == NULL)
1113: symaddr = scnhdr.s_paddr + scnhdr.s_size;
1114: #else
1115: /* scan the symbol table */
1116: if ((filhdr.f_nsyms != 0L) && (symb != NULL) && (ldtbseek(symb) != FAILURE)) {
1117: /*
1118: * set firstfn equal to the symbol table index
1119: * of the first function symbol table entry.
1120: * The search for the next function symbol
1121: * table entry will always begin at firstfn.
1122: */
1123: septr = &stbentry;
1124: if (firstfn == BADADDR) {
1125: ldtbread (symb, 0, septr);
1126: for (sindex = 1+septr->n_numaux; (sindex<filhdr.f_nsyms)
1127: && ((septr->n_scnum<1) || (!ISFCN(septr->n_type)
1128: || (septr->n_value < scnhdr.s_paddr)
1129: || (septr->n_value > s_end))); sindex++) {
1130: ldtbread (symb, sindex, septr);
1131: sindex += septr->n_numaux;
1132: }
1133: firstfn = sindex -1 - septr->n_numaux;
1134: }
1135: ldtbread(symb, firstfn, septr);
1136: sindex = firstfn + 1 + septr->n_numaux;
1137: for (;(sindex < filhdr.f_nsyms) && ((septr->n_scnum < 1)
1138: || (septr->n_numaux == 0) || ( !ISFCN(septr->n_type))
1139: || (septr->n_value < scnhdr.s_paddr)
1140: || (septr->n_value > s_end)
1141: || (septr->n_value <= loc)); sindex++) {
1142: ldtbread(symb, sindex, septr);
1143: sindex += septr->n_numaux;
1144: }
1145: /*
1146: * If the next fuction symbol table entry has been
1147: * found, it is a candidate for a restart point.
1148: * If the entire symbol table has been read, and a
1149: * possible restart point has not been found, the end
1150: * of the section is a candidate for a restart point.
1151: */
1152: if ((sindex - septr->n_numaux) == filhdr.f_nsyms)
1153: symaddr = s_end;
1154: else
1155: symaddr = septr->n_value;
1156: }
1157: /* end of the section is end of the function */
1158: #endif
1159: #endif
1160:
1161: if (symaddr == BADADDR) {
1162: /* Restart point was not found by searching the
1163: * symbol table.
1164: */
1165: if (linaddr == BADADDR) {
1166: /* Restart point was not found by looking
1167: * at line number information.
1168: */
1169: #ifdef OLIST
1170: if (nosource == FALSE)
1171: #endif
1172: {
1173: printf ("\n\t**\tCANNOT FIND NEXT LINE NUMBER\t\t\t**\n");
1174: printf ("\t** CANNOT FIND NEXT FUNCTION SYMBOL TABLE ENTRY\t**\n");
1175: printf ("\t** FOLLOWING DISASSEMBLY MAY BE OUT OF SYNC\t\t**\n");
1176: }
1177: return (FAILURE);
1178: }
1179: else {
1180: /* The next line number entry will be the
1181: * restart point.
1182: */
1183: paddr = linaddr;
1184: #ifdef OLIST
1185: if (nosource == FALSE)
1186: #endif
1187: {
1188: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n");
1189: printf ("\t** THE NEXT BREAKPOINTABLE LINE NUMBER\t**\n");
1190: }
1191: }
1192: }
1193: else if (linaddr == BADADDR) {
1194: /* The next function symbol table entry or the end
1195: * of the section will be the restart point.
1196: */
1197: paddr = symaddr;
1198: #ifdef OLIST
1199: if (nosource == FALSE)
1200: #endif
1201: {
1202: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n");
1203: printf ("\t** THE BEGINNING OF THE NEXT FUNCTION\t**\n");
1204: printf ("\t** OR UNTIL THE END OF THE SECTION\t**\n");
1205: }
1206: }
1207: else {
1208: /* The smaller address of the next line number
1209: * entry and the next function symbol table entry
1210: * will be the restart point.
1211: */
1212: paddr = (linaddr < symaddr)? linaddr: symaddr;
1213: #ifdef OLIST
1214: if (nosource == FALSE)
1215: #endif
1216: {
1217: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n");
1218: printf ("\t** RESTART POINT IS REACHED\t\t**\n");
1219: }
1220: }
1221: dumpaddr = (loc < paddr - scnhdr.s_paddr)? (paddr -scnhdr.s_paddr):
1222: paddr;
1223: for (; loc < dumpaddr; ) {
1224: /* Dump bytes until the restart point is reached. */
1225: #ifdef OLIST
1226: if (nosource == FALSE)
1227: #endif
1228: printf("\t");
1229: prt_offset();
1230: #ifdef B16
1231: getbyte( t_ptr );
1232: if (loc < dumpaddr)
1233: getbyte( t_ptr );
1234: #endif
1235: #ifdef MC68
1236: get2bytes(t_ptr);
1237: #endif
1238: #ifdef N3B
1239: get2bytes(t_ptr);
1240: #endif
1241: #ifdef M32
1242: get1byte(t_ptr);
1243: #endif /* M32 */
1244: sprintf(mneu,"");
1245: printline();
1246: } /* end of dump of unused object code */
1247:
1248: #ifdef OLIST
1249: if ( nosource == FALSE )
1250: #endif
1251: printf("\n\t** DISASSEMBLER RESYNCHRONIZED **\n");
1252: return(SUCCESS);
1253:
1254: }
1255: /*
1256: * sect_name ()
1257: *
1258: * If labels are to be looked up, the 'looklabel' routine needs to know
1259: * the number of the section being processed. Compare the section name
1260: * to the stored names, created in 'build_labels', and return the
1261: * appropriate section number.
1262: */
1263:
1264: short
1265: sect_name()
1266:
1267: {
1268: /* the following 2 items are from _extn.c */
1269: extern char *sname;
1270: extern FILHDR filhdr;
1271:
1272: unsigned short i;
1273:
1274: for (i = 1; i < filhdr.f_nscns +1; i++)
1275: if (strcmp(sname,section[i]) == STRNGEQ)
1276: return(i);
1277:
1278: return (FAILURE);
1279: }
1280:
1281: #if N3B | U3B | M32 | U3B5
1282: /*
1283: * sfpconv(fprep, fpdoub)
1284: *
1285: * This routine will convert the long "fprep" single precision
1286: * floating point representation of a number into its decimal
1287: * equivalent. The result will be stored in *fpdoub. The routine
1288: * will return a value indicating what type of floating point
1289: * number was converted.
1290: */
1291: sfpconv(fprep, fpdoub)
1292: long fprep;
1293: double *fpdoub;
1294: {
1295: unsigned short exponent;
1296: short leadbit, signbit;
1297: long mantissa;
1298: double dtemp, dec2exp;
1299:
1300: exponent = (unsigned short)((fprep>>23) & 0xffL);
1301: /* exponent is bits 1-8 of the long */
1302:
1303: mantissa = fprep & 0x7fffffL;
1304: /* mantissa is bits 9-31 of the long */
1305:
1306: signbit = (fprep>>31) & 0x1L;
1307: /* sign bit (1-negative, 0-positive) is bit 0 of long */
1308:
1309: leadbit = 1;
1310: /* implied bit to the left of the decimal point */
1311:
1312: if (exponent==255)
1313: if (mantissa)
1314: return(NOTANUM);
1315: else
1316: return((signbit)? NEGINF: INFINITY);
1317:
1318: if (exponent==0)
1319: if (mantissa)
1320: /* This is a denormalized number. The implied bit to
1321: * the left of the decimal point is 0.
1322: */
1323: leadbit = 0;
1324: else
1325: return((signbit)? NEGZERO: ZERO);
1326:
1327: /*
1328: * Convert the 23 bit mantissa into "I.fraction" where
1329: * "I" is the implied bit. The 23 bits are divided by
1330: * 2 to the 23rd power to transform the mantissa into a
1331: * fraction. Then the implied bit is added on.
1332: */
1333: dtemp = (double)(leadbit + (double)mantissa/TWO_23);
1334:
1335: /* Calculate 2 raised to the (exponent-BIAS) power and
1336: * store it in a double.
1337: */
1338: if (exponent < BIAS)
1339: for(dec2exp=1; exponent < BIAS; ++exponent)
1340: dec2exp /= 2;
1341: else
1342: for(dec2exp=1; exponent > BIAS; --exponent)
1343: dec2exp *= 2;
1344:
1345: /* Multiply "I.fraction" by 2 raised to the (exponent-BIAS)
1346: * power to obtain the decimal floating point number.
1347: */
1348: *fpdoub = dtemp *dec2exp;
1349:
1350: if (signbit)
1351: *fpdoub = -(*fpdoub);
1352: return(FPNUM);
1353: }
1354: #endif /* N3B | U3B | M32 | U3B5 */
1355:
1356: /*
1357: * stripped ()
1358: *
1359: * Is the file stripped (no line number entries)?
1360: * If so, return TRUE else FALSE.
1361: */
1362:
1363: stripped()
1364:
1365: {
1366: extern SCNHDR scnhdr; /* from _extn.c */
1367:
1368: return( (scnhdr.s_nlnno == 0) ? TRUE : FALSE);
1369: }
1370:
1371: /*
1372: * fatal()
1373: *
1374: * print an error message and quit
1375: */
1376:
1377: fatal( message )
1378: char *message;
1379: {
1380: extern char *fname;
1381:
1382: fprintf( stderr, "\n%s%s: %s: %s\n", SGS, TOOL, fname, message );
1383: exit(1);
1384: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.