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