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