1*43224Sbostic /* 2*43224Sbostic * Copyright (c) 1980 Regents of the University of California. 3*43224Sbostic * All rights reserved. The Berkeley software License Agreement 4*43224Sbostic * specifies the terms and conditions for redistribution. 5*43224Sbostic */ 6*43224Sbostic 7*43224Sbostic #ifndef lint 8*43224Sbostic static char sccsid[] = "@(#)stab.c 5.1 (Berkeley) 6/7/85"; 9*43224Sbostic #endif not lint 10*43224Sbostic 11*43224Sbostic /* 12*43224Sbostic * stab.c 13*43224Sbostic * 14*43224Sbostic * Symbolic debugging info interface for the f77 compiler. 15*43224Sbostic * 16*43224Sbostic * Here we generate pseudo-ops that cause the assembler to put 17*43224Sbostic * symbolic debugging information into the object file. 18*43224Sbostic * 19*43224Sbostic * University of Utah CS Dept modification history: 20*43224Sbostic * 21*43224Sbostic * $Log: stab.c,v $ 22*43224Sbostic * Revision 1.2 85/02/02 01:30:09 donn 23*43224Sbostic * Don't put the 'program' name into the file; it only confuses dbx, sigh. 24*43224Sbostic * 25*43224Sbostic */ 26*43224Sbostic 27*43224Sbostic #include "defs.h" 28*43224Sbostic 29*43224Sbostic #include <sys/types.h> 30*43224Sbostic #include <a.out.h> 31*43224Sbostic #include <stab.h> 32*43224Sbostic 33*43224Sbostic #define public 34*43224Sbostic #define private static 35*43224Sbostic #define and && 36*43224Sbostic #define or || 37*43224Sbostic #define not ! 38*43224Sbostic #define div / 39*43224Sbostic #define mod % 40*43224Sbostic #define nil 0 41*43224Sbostic 42*43224Sbostic typedef enum { false, true } Boolean; 43*43224Sbostic 44*43224Sbostic static char asmline[128]; 45*43224Sbostic int len; 46*43224Sbostic extern char *malloc(); 47*43224Sbostic 48*43224Sbostic prstab(s, code, type, loc) 49*43224Sbostic char *s, *loc; 50*43224Sbostic int code, type; 51*43224Sbostic { 52*43224Sbostic char *locout; 53*43224Sbostic 54*43224Sbostic if (sdbflag) { 55*43224Sbostic locout = (loc == nil) ? "0" : loc; 56*43224Sbostic if (s == nil) { 57*43224Sbostic sprintf(asmline, "\t.stabn\t0x%x,0,0x%x,%s\n", code, type, locout); 58*43224Sbostic } else { 59*43224Sbostic sprintf(asmline, "\t.stabs\t\"%s\",0x%x,0,0x%x,%s\n", s, code, type, 60*43224Sbostic locout); 61*43224Sbostic } 62*43224Sbostic p2pass( asmline ); 63*43224Sbostic } 64*43224Sbostic } 65*43224Sbostic 66*43224Sbostic filenamestab(s) 67*43224Sbostic char *s; 68*43224Sbostic { 69*43224Sbostic sprintf(asmline,"\t.stabs\t\"%s\",0x%x,0,0,0\n", s, N_SO); 70*43224Sbostic p2pass( asmline ); 71*43224Sbostic } 72*43224Sbostic 73*43224Sbostic linenostab(lineno) 74*43224Sbostic int lineno; 75*43224Sbostic { 76*43224Sbostic sprintf(asmline,"\t.stabd\t0x%x,0,%d\n", N_SLINE, lineno); 77*43224Sbostic p2pass( asmline ); 78*43224Sbostic } 79*43224Sbostic 80*43224Sbostic /* 81*43224Sbostic * Generate information for an entry point 82*43224Sbostic */ 83*43224Sbostic 84*43224Sbostic public entrystab(p,class) 85*43224Sbostic register struct Entrypoint *p; 86*43224Sbostic int class; 87*43224Sbostic { 88*43224Sbostic int et; 89*43224Sbostic Namep q; 90*43224Sbostic 91*43224Sbostic switch(class) { 92*43224Sbostic case CLMAIN: 93*43224Sbostic et=writestabtype(TYSUBR); 94*43224Sbostic sprintf(asmline, "\t.stabs\t\"MAIN:F%2d\",0x%x,0,0,L%d\n", 95*43224Sbostic et,N_FUN,p->entrylabel); 96*43224Sbostic p2pass(asmline); 97*43224Sbostic break; 98*43224Sbostic 99*43224Sbostic case CLBLOCK: /* May need to something with block data LATER */ 100*43224Sbostic break; 101*43224Sbostic 102*43224Sbostic default : 103*43224Sbostic if( (q=p->enamep) == nil) fatal("entrystab has no nameblock"); 104*43224Sbostic sprintf(asmline, "\t.stabs\t\"%s:F", varstr(VL,q->varname)); 105*43224Sbostic len = strlen(asmline); 106*43224Sbostic /* when insufficient information is around assume TYSUBR; enddcl 107*43224Sbostic will fill this in*/ 108*43224Sbostic if(q->vtype == TYUNKNOWN || (q->vtype == TYCHAR && q->vleng == nil) ){ 109*43224Sbostic sprintf(asmline+len, "%2d", writestabtype(TYSUBR)); 110*43224Sbostic } 111*43224Sbostic else addtypeinfo(q); 112*43224Sbostic len += strlen(asmline+len); 113*43224Sbostic sprintf(asmline+len, "\",0x%x,0,0,L%d\n",N_FUN,p->entrylabel); 114*43224Sbostic p2pass(asmline); 115*43224Sbostic break; 116*43224Sbostic } 117*43224Sbostic } 118*43224Sbostic 119*43224Sbostic /* 120*43224Sbostic * Generate information for a symbol table (name block ) entry. 121*43224Sbostic */ 122*43224Sbostic 123*43224Sbostic public namestab(sym) 124*43224Sbostic Namep sym; 125*43224Sbostic { 126*43224Sbostic register Namep p; 127*43224Sbostic char *varname, *classname; 128*43224Sbostic Boolean ignore; 129*43224Sbostic int vartype; 130*43224Sbostic 131*43224Sbostic ignore = false; 132*43224Sbostic p = sym; 133*43224Sbostic if(!p->vdcldone) return; 134*43224Sbostic vartype = p->vtype; 135*43224Sbostic varname = varstr(VL, p->varname); 136*43224Sbostic switch (p->vclass) { 137*43224Sbostic case CLPARAM: /* parameter (constant) */ 138*43224Sbostic classname = "c"; 139*43224Sbostic break; 140*43224Sbostic 141*43224Sbostic case CLVAR: /* variable */ 142*43224Sbostic case CLUNKNOWN: 143*43224Sbostic if(p->vstg == STGARG) classname = "v"; 144*43224Sbostic else classname = "V"; 145*43224Sbostic break; 146*43224Sbostic 147*43224Sbostic case CLMAIN: /* main program */ 148*43224Sbostic case CLENTRY: /* secondary entry point */ 149*43224Sbostic case CLBLOCK: /* block data name*/ 150*43224Sbostic case CLPROC: /* external or function or subroutine */ 151*43224Sbostic ignore = true; /* these are put out by entrystab */ 152*43224Sbostic break; 153*43224Sbostic 154*43224Sbostic 155*43224Sbostic } 156*43224Sbostic if (not ignore) { 157*43224Sbostic sprintf(asmline, "\t.stabs\t\"%s:%s", varname, classname); 158*43224Sbostic len = strlen(asmline); 159*43224Sbostic addtypeinfo(p); 160*43224Sbostic len += strlen(asmline+len); 161*43224Sbostic switch(p->vstg) { 162*43224Sbostic 163*43224Sbostic case STGUNKNOWN : 164*43224Sbostic case STGCONST : 165*43224Sbostic case STGEXT : 166*43224Sbostic case STGINTR : 167*43224Sbostic case STGSTFUNCT : 168*43224Sbostic case STGLENG : 169*43224Sbostic case STGNULL : 170*43224Sbostic case STGREG : 171*43224Sbostic case STGINIT : 172*43224Sbostic sprintf(asmline+len, 173*43224Sbostic "\",0x%x,0,0,0 /* don't know how to calc loc for stg %d*/ \n", 174*43224Sbostic N_LSYM,p->vstg); 175*43224Sbostic break; 176*43224Sbostic 177*43224Sbostic case STGARG : 178*43224Sbostic sprintf(asmline+len,"\",0x%x,0,0,%d \n", 179*43224Sbostic N_PSYM,p->vardesc.varno + ARGOFFSET ); 180*43224Sbostic break; 181*43224Sbostic 182*43224Sbostic case STGCOMMON : 183*43224Sbostic sprintf(asmline+len, "\",0x%x,0,0,%d\n", 184*43224Sbostic N_GSYM, p->voffset); 185*43224Sbostic break; 186*43224Sbostic 187*43224Sbostic case STGBSS : 188*43224Sbostic sprintf(asmline+len, "\",0x%x,0,0,v.%d\n", 189*43224Sbostic (p->inlcomm ? N_LCSYM : N_STSYM), 190*43224Sbostic p->vardesc.varno); 191*43224Sbostic break; 192*43224Sbostic 193*43224Sbostic case STGEQUIV : 194*43224Sbostic sprintf(asmline+len, "\",0x%x,0,0,%s + %d \n", 195*43224Sbostic (p->inlcomm ? N_LCSYM : N_STSYM) , 196*43224Sbostic memname(STGEQUIV,p->vardesc.varno),(p->voffset)) ; 197*43224Sbostic break; 198*43224Sbostic 199*43224Sbostic case STGAUTO : 200*43224Sbostic sprintf(asmline+len, "\",0x%x,0,0,-%d \n", 201*43224Sbostic N_LSYM, p->voffset); 202*43224Sbostic 203*43224Sbostic } 204*43224Sbostic p2pass(asmline); 205*43224Sbostic } 206*43224Sbostic } 207*43224Sbostic 208*43224Sbostic static typenum[NTYPES]; /* has the given type already been defined ?*/ 209*43224Sbostic 210*43224Sbostic private writestabtype(type) 211*43224Sbostic int type; 212*43224Sbostic { 213*43224Sbostic char asmline[130]; 214*43224Sbostic static char *typename[NTYPES] = 215*43224Sbostic { "unknown", "addr","integer*2", "integer", "real", "double precision", 216*43224Sbostic "complex", "double complex", "logical", "char", "void", "error" }; 217*43224Sbostic 218*43224Sbostic static int typerange[NTYPES] = { 0, 3, 2, 3, 4, 5, 6, 7, 3, 9, 10, 11 }; 219*43224Sbostic 220*43224Sbostic /* compare with typesize[] in init.c */ 221*43224Sbostic static int typebounds[2] [NTYPES] ={ 222*43224Sbostic /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ 223*43224Sbostic { 0 , 0 , -32768, -2147483648, 4, 8, 224*43224Sbostic /* "complex", "double complex", "logical", "char", "void", "error" }; */ 225*43224Sbostic 8, 16, 0, 0, 0, 0 }, 226*43224Sbostic /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ 227*43224Sbostic { 0 , -1, 32767, 2147483647, 0, 0, 228*43224Sbostic /* "complex", "double complex", "logical", "char", "void", "error" }; */ 229*43224Sbostic 0, 0, 1, 127, 0, 0 } 230*43224Sbostic }; 231*43224Sbostic 232*43224Sbostic 233*43224Sbostic if( type < 0 || type > NTYPES) badtype("writestabtype",type); 234*43224Sbostic 235*43224Sbostic if (typenum[type]) return(typenum[type]); 236*43224Sbostic typenum[type] = type; 237*43224Sbostic sprintf(asmline, "\t.stabs\t\"%s:t%d=r%d;%ld;%ld;\",0x%x,0,0,0 \n", 238*43224Sbostic typename[type], type, typerange[type], typebounds[0][type], 239*43224Sbostic typebounds[1][type], N_GSYM) ; 240*43224Sbostic p2pass(asmline); 241*43224Sbostic return(typenum[type]); 242*43224Sbostic } 243*43224Sbostic 244*43224Sbostic 245*43224Sbostic private getbasenum(p) 246*43224Sbostic Namep p; 247*43224Sbostic { 248*43224Sbostic 249*43224Sbostic int t; 250*43224Sbostic t = p->vtype; 251*43224Sbostic if( t < TYSHORT || t > TYSUBR) 252*43224Sbostic dclerr("can't get dbx basetype information",p); 253*43224Sbostic 254*43224Sbostic if (p->vtype == TYCHAR || p->vdim != nil ) writestabtype(TYINT); 255*43224Sbostic return(writestabtype(t)); 256*43224Sbostic } 257*43224Sbostic 258*43224Sbostic /* 259*43224Sbostic * Generate debugging information for the given type of the given symbol. 260*43224Sbostic */ 261*43224Sbostic 262*43224Sbostic private addtypeinfo(sym) 263*43224Sbostic Namep sym; 264*43224Sbostic { 265*43224Sbostic Namep p; 266*43224Sbostic int i,tnum; 267*43224Sbostic char lb[20],ub[20]; 268*43224Sbostic 269*43224Sbostic p = sym; 270*43224Sbostic if (p->tag != TNAME) badtag("addtypeinfo",p->tag); 271*43224Sbostic 272*43224Sbostic tnum = getbasenum(p); 273*43224Sbostic if(p->vdim != (struct Dimblock *) ENULL) { 274*43224Sbostic 275*43224Sbostic for (i = p->vdim->ndim-1; i >=0 ; --i) { 276*43224Sbostic if(p->vdim->dims[i].lbaddr == ENULL) { 277*43224Sbostic sprintf(lb,"%d", p->vdim->dims[i].lb->constblock.const.ci); 278*43224Sbostic } 279*43224Sbostic else { 280*43224Sbostic sprintf(lb,"T%d", p->vdim->dims[i].lbaddr->addrblock.memoffset->constblock.const.ci); 281*43224Sbostic } 282*43224Sbostic if(p->vdim->dims[i].ubaddr == ENULL) { 283*43224Sbostic sprintf(ub,"%d",p->vdim->dims[i].ub->constblock.const.ci); 284*43224Sbostic } 285*43224Sbostic else { 286*43224Sbostic sprintf(ub,"T%d",p->vdim->dims[i].ubaddr->addrblock.memoffset->constblock.const.ci); 287*43224Sbostic } 288*43224Sbostic sprintf(asmline+len, "ar%d;%s;%s;", TYINT, lb, ub); 289*43224Sbostic len += strlen(asmline+len); 290*43224Sbostic } 291*43224Sbostic } 292*43224Sbostic if (p->vtype == TYCHAR) { 293*43224Sbostic /* character type always an array(1:?) */ 294*43224Sbostic if( ! (p->vleng ) ) 295*43224Sbostic fatalstr("missing length in addtypeinfo for character variable %s", varstr(p->varname)); 296*43224Sbostic 297*43224Sbostic if (ISCONST(p->vleng)) sprintf(ub,"%d",p->vleng->constblock.const.ci); 298*43224Sbostic else sprintf(ub,"A%d",p->vleng->addrblock.memno + ARGOFFSET); 299*43224Sbostic 300*43224Sbostic sprintf(asmline+len,"ar%d;1;%s;", TYINT, ub); 301*43224Sbostic len += strlen(asmline+len); 302*43224Sbostic } 303*43224Sbostic sprintf(asmline+len, "%d",tnum); 304*43224Sbostic } 305