1*47955Sbostic /*-
2*47955Sbostic * Copyright (c) 1980 The Regents of the University of California.
3*47955Sbostic * All rights reserved.
4*47955Sbostic *
5*47955Sbostic * %sccs.include.proprietary.c%
622872Smckusick */
722872Smckusick
822872Smckusick #ifndef lint
9*47955Sbostic static char sccsid[] = "@(#)stab.c 5.4 (Berkeley) 04/12/91";
10*47955Sbostic #endif /* not lint */
1122872Smckusick
1222872Smckusick /*
1322872Smckusick * stab.c
1422872Smckusick *
1522872Smckusick * Symbolic debugging info interface for the f77 compiler.
1622872Smckusick *
1722872Smckusick * Here we generate pseudo-ops that cause the assembler to put
1822872Smckusick * symbolic debugging information into the object file.
1922872Smckusick *
2022872Smckusick * University of Utah CS Dept modification history:
2122872Smckusick *
2222872Smckusick * $Log: stab.c,v $
2325815Sdonn * Revision 5.3 86/01/10 17:12:58 donn
2425815Sdonn * Add junk to handle PARAMETER variables.
2525815Sdonn *
2625815Sdonn * Revision 5.2 86/01/10 13:51:31 donn
2725815Sdonn * Changes to produce correct stab information for logical and logical*2 types
2825815Sdonn * (from Jerry Berkman) plus changes for dummy procedures.
2925815Sdonn *
3025815Sdonn * Revision 5.1 85/08/10 03:50:06 donn
3125815Sdonn * 4.3 alpha
3225815Sdonn *
3322872Smckusick * Revision 1.2 85/02/02 01:30:09 donn
3422872Smckusick * Don't put the 'program' name into the file; it only confuses dbx, sigh.
3522872Smckusick *
3622872Smckusick */
3722872Smckusick
3822872Smckusick #include "defs.h"
3922872Smckusick
4022872Smckusick #include <sys/types.h>
4122872Smckusick #include <a.out.h>
4222872Smckusick #include <stab.h>
4322872Smckusick
4422872Smckusick #define public
4522872Smckusick #define private static
4622872Smckusick #define and &&
4722872Smckusick #define or ||
4822872Smckusick #define not !
4922872Smckusick #define div /
5022872Smckusick #define mod %
5122872Smckusick #define nil 0
5222872Smckusick
5322872Smckusick typedef enum { false, true } Boolean;
5422872Smckusick
5522872Smckusick static char asmline[128];
5622872Smckusick int len;
5722872Smckusick extern char *malloc();
5822872Smckusick
prstab(s,code,type,loc)5922872Smckusick prstab(s, code, type, loc)
6022872Smckusick char *s, *loc;
6122872Smckusick int code, type;
6222872Smckusick {
6322872Smckusick char *locout;
6422872Smckusick
6522872Smckusick if (sdbflag) {
6622872Smckusick locout = (loc == nil) ? "0" : loc;
6722872Smckusick if (s == nil) {
6822872Smckusick sprintf(asmline, "\t.stabn\t0x%x,0,0x%x,%s\n", code, type, locout);
6922872Smckusick } else {
7022872Smckusick sprintf(asmline, "\t.stabs\t\"%s\",0x%x,0,0x%x,%s\n", s, code, type,
7122872Smckusick locout);
7222872Smckusick }
7322872Smckusick p2pass( asmline );
7422872Smckusick }
7522872Smckusick }
7622872Smckusick
filenamestab(s)7722872Smckusick filenamestab(s)
7822872Smckusick char *s;
7922872Smckusick {
8022872Smckusick sprintf(asmline,"\t.stabs\t\"%s\",0x%x,0,0,0\n", s, N_SO);
8122872Smckusick p2pass( asmline );
8222872Smckusick }
8322872Smckusick
linenostab(lineno)8422872Smckusick linenostab(lineno)
8522872Smckusick int lineno;
8622872Smckusick {
8722872Smckusick sprintf(asmline,"\t.stabd\t0x%x,0,%d\n", N_SLINE, lineno);
8822872Smckusick p2pass( asmline );
8922872Smckusick }
9022872Smckusick
9122872Smckusick /*
9222872Smckusick * Generate information for an entry point
9322872Smckusick */
9422872Smckusick
entrystab(p,class)9522872Smckusick public entrystab(p,class)
9622872Smckusick register struct Entrypoint *p;
9722872Smckusick int class;
9822872Smckusick {
9922872Smckusick int et;
10022872Smckusick Namep q;
10122872Smckusick
10222872Smckusick switch(class) {
10322872Smckusick case CLMAIN:
10422872Smckusick et=writestabtype(TYSUBR);
10522872Smckusick sprintf(asmline, "\t.stabs\t\"MAIN:F%2d\",0x%x,0,0,L%d\n",
10622872Smckusick et,N_FUN,p->entrylabel);
10722872Smckusick p2pass(asmline);
10822872Smckusick break;
10922872Smckusick
11022872Smckusick case CLBLOCK: /* May need to something with block data LATER */
11122872Smckusick break;
11222872Smckusick
11322872Smckusick default :
11422872Smckusick if( (q=p->enamep) == nil) fatal("entrystab has no nameblock");
11522872Smckusick sprintf(asmline, "\t.stabs\t\"%s:F", varstr(VL,q->varname));
11622872Smckusick len = strlen(asmline);
11722872Smckusick /* when insufficient information is around assume TYSUBR; enddcl
11822872Smckusick will fill this in*/
11922872Smckusick if(q->vtype == TYUNKNOWN || (q->vtype == TYCHAR && q->vleng == nil) ){
12022872Smckusick sprintf(asmline+len, "%2d", writestabtype(TYSUBR));
12122872Smckusick }
12222872Smckusick else addtypeinfo(q);
12322872Smckusick len += strlen(asmline+len);
12422872Smckusick sprintf(asmline+len, "\",0x%x,0,0,L%d\n",N_FUN,p->entrylabel);
12522872Smckusick p2pass(asmline);
12622872Smckusick break;
12722872Smckusick }
12822872Smckusick }
12922872Smckusick
13022872Smckusick /*
13122872Smckusick * Generate information for a symbol table (name block ) entry.
13222872Smckusick */
13322872Smckusick
namestab(sym)13422872Smckusick public namestab(sym)
13522872Smckusick Namep sym;
13622872Smckusick {
13722872Smckusick register Namep p;
13822872Smckusick char *varname, *classname;
13925815Sdonn expptr ep;
14025815Sdonn char buf[100];
14122872Smckusick Boolean ignore;
14222872Smckusick int vartype;
14322872Smckusick
14422872Smckusick ignore = false;
14522872Smckusick p = sym;
14622872Smckusick if(!p->vdcldone) return;
14722872Smckusick vartype = p->vtype;
14822872Smckusick varname = varstr(VL, p->varname);
14922872Smckusick switch (p->vclass) {
15022872Smckusick case CLPARAM: /* parameter (constant) */
15125815Sdonn classname = buf;
15225815Sdonn if ((ep = ((struct Paramblock *) p)->paramval) &&
15325815Sdonn ep->tag == TCONST) {
15425815Sdonn switch(ep->constblock.vtype) {
15525815Sdonn case TYLONG:
15625815Sdonn case TYSHORT:
15725815Sdonn case TYLOGICAL:
15825815Sdonn case TYADDR:
15933257Sbostic sprintf(buf, "c=i%d", ep->constblock.constant.ci);
16025815Sdonn break;
16125815Sdonn case TYREAL:
16225815Sdonn case TYDREAL:
16333257Sbostic sprintf(buf, "c=r%f", ep->constblock.constant.cd[0]);
16425815Sdonn break;
16525815Sdonn default:
16625815Sdonn /* punt */
16725815Sdonn ignore = true;
16825815Sdonn break;
16925815Sdonn }
17025815Sdonn } else {
17125815Sdonn ignore = true;
17225815Sdonn }
17322872Smckusick break;
17422872Smckusick
17522872Smckusick case CLVAR: /* variable */
17622872Smckusick case CLUNKNOWN:
17722872Smckusick if(p->vstg == STGARG) classname = "v";
17822872Smckusick else classname = "V";
17922872Smckusick break;
18022872Smckusick
18125815Sdonn case CLPROC: /* external or function or subroutine */
18225815Sdonn if(p->vstg == STGARG) {
18325815Sdonn classname = "v";
18425815Sdonn break;
18525815Sdonn }
18625815Sdonn /* FALL THROUGH */
18722872Smckusick case CLMAIN: /* main program */
18822872Smckusick case CLENTRY: /* secondary entry point */
18922872Smckusick case CLBLOCK: /* block data name*/
19022872Smckusick ignore = true; /* these are put out by entrystab */
19122872Smckusick break;
19222872Smckusick
19322872Smckusick
19422872Smckusick }
19522872Smckusick if (not ignore) {
19622872Smckusick sprintf(asmline, "\t.stabs\t\"%s:%s", varname, classname);
19722872Smckusick len = strlen(asmline);
19822872Smckusick addtypeinfo(p);
19922872Smckusick len += strlen(asmline+len);
20022872Smckusick switch(p->vstg) {
20122872Smckusick
20222872Smckusick case STGUNKNOWN :
20322872Smckusick case STGCONST :
20422872Smckusick case STGEXT :
20522872Smckusick case STGINTR :
20622872Smckusick case STGSTFUNCT :
20722872Smckusick case STGLENG :
20822872Smckusick case STGNULL :
20922872Smckusick case STGREG :
21022872Smckusick case STGINIT :
21125815Sdonn if (p->vclass == CLPARAM) {
21225815Sdonn /* these have zero storage class for some reason */
21325815Sdonn sprintf(asmline+len, "\",0x%x,0,0,0\n", N_LSYM);
21425815Sdonn break;
21525815Sdonn }
21622872Smckusick sprintf(asmline+len,
21722872Smckusick "\",0x%x,0,0,0 /* don't know how to calc loc for stg %d*/ \n",
21822872Smckusick N_LSYM,p->vstg);
21922872Smckusick break;
22022872Smckusick
22122872Smckusick case STGARG :
22222872Smckusick sprintf(asmline+len,"\",0x%x,0,0,%d \n",
22322872Smckusick N_PSYM,p->vardesc.varno + ARGOFFSET );
22422872Smckusick break;
22522872Smckusick
22622872Smckusick case STGCOMMON :
22722872Smckusick sprintf(asmline+len, "\",0x%x,0,0,%d\n",
22822872Smckusick N_GSYM, p->voffset);
22922872Smckusick break;
23022872Smckusick
23122872Smckusick case STGBSS :
23222872Smckusick sprintf(asmline+len, "\",0x%x,0,0,v.%d\n",
23322872Smckusick (p->inlcomm ? N_LCSYM : N_STSYM),
23422872Smckusick p->vardesc.varno);
23522872Smckusick break;
23622872Smckusick
23722872Smckusick case STGEQUIV :
23822872Smckusick sprintf(asmline+len, "\",0x%x,0,0,%s + %d \n",
23922872Smckusick (p->inlcomm ? N_LCSYM : N_STSYM) ,
24022872Smckusick memname(STGEQUIV,p->vardesc.varno),(p->voffset)) ;
24122872Smckusick break;
24222872Smckusick
24322872Smckusick case STGAUTO :
24422872Smckusick sprintf(asmline+len, "\",0x%x,0,0,-%d \n",
24522872Smckusick N_LSYM, p->voffset);
24622872Smckusick
24722872Smckusick }
24822872Smckusick p2pass(asmline);
24922872Smckusick }
25022872Smckusick }
25122872Smckusick
25225815Sdonn static typenum[NTYPES+1]; /* has the given type already been defined ?*/
25322872Smckusick
writestabtype(type)25422872Smckusick private writestabtype(type)
25522872Smckusick int type;
25622872Smckusick {
25722872Smckusick char asmline[130];
25825815Sdonn static char *typename[NTYPES+1] = {
25925815Sdonn "unknown", "addr", "integer*2", "integer", "real", "double precision",
26025815Sdonn "complex", "double complex", "logical", "char", "void", "error", "logical*2" };
26122872Smckusick
26225815Sdonn static int typerange[NTYPES+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
26322872Smckusick
26422872Smckusick /* compare with typesize[] in init.c */
26525815Sdonn static int typebounds[2] [NTYPES+1] ={
26622872Smckusick /* "unknown", "addr","integer*2", "integer", "real", "double precision", */
26722872Smckusick { 0 , 0 , -32768, -2147483648, 4, 8,
26825815Sdonn /* "complex", "d-complex", "logical", "char", "void", "error", "logical*2" */
26925815Sdonn 8, 16, 4, 0, 0, 0, 2 },
27022872Smckusick /* "unknown", "addr","integer*2", "integer", "real", "double precision", */
27125815Sdonn { 0 , -1, 32767, 2147483647, 0, 0,
27225815Sdonn /* "complex", "d-complex", "logical", "char", "void", "error", "logical*2" */
27325815Sdonn 0, 0, 0, 127, 0, 0, 0 }
27422872Smckusick };
27522872Smckusick
27622872Smckusick
27725815Sdonn if (type < 0 || type > NTYPES)
27825815Sdonn badtype("writestabtype",type);
27922872Smckusick
28025815Sdonn /* substitute "logical*2" for "logical" when "-i2" compiler flag used */
28125815Sdonn if (type == TYLOGICAL && tylogical == TYSHORT)
28225815Sdonn type = NTYPES;
28325815Sdonn
28422872Smckusick if (typenum[type]) return(typenum[type]);
28522872Smckusick typenum[type] = type;
28622872Smckusick sprintf(asmline, "\t.stabs\t\"%s:t%d=r%d;%ld;%ld;\",0x%x,0,0,0 \n",
28722872Smckusick typename[type], type, typerange[type], typebounds[0][type],
28822872Smckusick typebounds[1][type], N_GSYM) ;
28922872Smckusick p2pass(asmline);
29022872Smckusick return(typenum[type]);
29122872Smckusick }
29222872Smckusick
29322872Smckusick
getbasenum(p)29422872Smckusick private getbasenum(p)
29522872Smckusick Namep p;
29622872Smckusick {
29722872Smckusick
29822872Smckusick int t;
29922872Smckusick
30025815Sdonn if (p->vclass == CLPROC && p->vstg == STGARG)
30125815Sdonn t = TYADDR;
30225815Sdonn else
30325815Sdonn t = p->vtype;
30425815Sdonn
30525815Sdonn if (t < TYADDR || t > TYSUBR)
30625815Sdonn dclerr("can't get dbx basetype information",p);
30725815Sdonn
30825815Sdonn if (p->vtype == TYCHAR || p->vdim != nil)
30925815Sdonn writestabtype(TYINT);
31022872Smckusick return(writestabtype(t));
31122872Smckusick }
31222872Smckusick
31322872Smckusick /*
31422872Smckusick * Generate debugging information for the given type of the given symbol.
31522872Smckusick */
31622872Smckusick
addtypeinfo(sym)31722872Smckusick private addtypeinfo(sym)
31822872Smckusick Namep sym;
31922872Smckusick {
32022872Smckusick Namep p;
32122872Smckusick int i,tnum;
32222872Smckusick char lb[20],ub[20];
32322872Smckusick
32422872Smckusick p = sym;
32522872Smckusick if (p->tag != TNAME) badtag("addtypeinfo",p->tag);
32625815Sdonn if (p->vclass == CLPARAM)
32725815Sdonn return;
32822872Smckusick
32922872Smckusick tnum = getbasenum(p);
33022872Smckusick if(p->vdim != (struct Dimblock *) ENULL) {
33122872Smckusick
33222872Smckusick for (i = p->vdim->ndim-1; i >=0 ; --i) {
33322872Smckusick if(p->vdim->dims[i].lbaddr == ENULL) {
33433257Sbostic sprintf(lb,"%d", p->vdim->dims[i].lb->constblock.constant.ci);
33522872Smckusick }
33622872Smckusick else {
33733257Sbostic sprintf(lb,"T%d", p->vdim->dims[i].lbaddr->addrblock.memoffset->constblock.constant.ci);
33822872Smckusick }
33922872Smckusick if(p->vdim->dims[i].ubaddr == ENULL) {
34033257Sbostic sprintf(ub,"%d",p->vdim->dims[i].ub->constblock.constant.ci);
34122872Smckusick }
34222872Smckusick else {
34333257Sbostic sprintf(ub,"T%d",p->vdim->dims[i].ubaddr->addrblock.memoffset->constblock.constant.ci);
34422872Smckusick }
34522872Smckusick sprintf(asmline+len, "ar%d;%s;%s;", TYINT, lb, ub);
34622872Smckusick len += strlen(asmline+len);
34722872Smckusick }
34822872Smckusick }
34922872Smckusick if (p->vtype == TYCHAR) {
35022872Smckusick /* character type always an array(1:?) */
35122872Smckusick if( ! (p->vleng ) )
35222872Smckusick fatalstr("missing length in addtypeinfo for character variable %s", varstr(p->varname));
35322872Smckusick
35433257Sbostic if (ISCONST(p->vleng)) sprintf(ub,"%d",p->vleng->constblock.constant.ci);
35522872Smckusick else sprintf(ub,"A%d",p->vleng->addrblock.memno + ARGOFFSET);
35622872Smckusick
35722872Smckusick sprintf(asmline+len,"ar%d;1;%s;", TYINT, ub);
35822872Smckusick len += strlen(asmline+len);
35922872Smckusick }
36022872Smckusick sprintf(asmline+len, "%d",tnum);
36122872Smckusick }
362