1 /* Id: stabs.c,v 1.35 2015/09/15 20:01:10 ragge Exp */ 2 /* $NetBSD: stabs.c,v 1.1.1.7 2016/02/09 20:28:52 plunky Exp $ */ 3 4 /* 5 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * Simple implementation of the "stabs" debugging format. 33 * Not complete but at least makes it possible to set breakpoints, 34 * examine simple variables and do stack traces. 35 * Based on the stabs documentation that follows gdb. 36 */ 37 38 #include "pass1.h" 39 40 #ifdef STABS 41 42 #include <sys/types.h> 43 #include <stdarg.h> 44 #include <string.h> 45 46 #define STABHASH 256 47 #define INTNUM 1 /* internal number of type "int" */ 48 #undef BIT2BYTE /* from external.h */ 49 #define BIT2BYTE(x) ((x)/SZCHAR) 50 51 #ifndef STABLBL 52 #error macdefs.h must define STABLBL 53 #endif 54 55 /* defines taken from BSD <stab.h> */ 56 #define N_GSYM 0x20 /* global symbol */ 57 #define N_FUN 0x24 /* procedure name */ 58 #define N_LCSYM 0x28 /* bss segment variable */ 59 #define N_RSYM 0x40 /* register variable */ 60 #define N_SLINE 0x44 /* text segment line number */ 61 #define N_SO 0x64 /* main source file name */ 62 #define N_LSYM 0x80 /* stack variable */ 63 #define N_SOL 0x84 /* included source file name */ 64 #define N_PSYM 0xa0 /* parameter variable */ 65 #define N_LBRAC 0xc0 /* left bracket */ 66 #define N_RBRAC 0xe0 /* right bracket */ 67 68 /* 69 * Local type mapping 70 * Types are defined as a typeword, a dimension pointer (in the case 71 * of arrays) and struct/union/enum declarations. 72 * Function prototypes are ignored. 73 */ 74 static struct stabtype { 75 struct stabtype *next; /* linked list */ 76 TWORD type; /* pcc type number */ 77 union dimfun *df; /* dimension of arrays */ 78 struct attr *ap; /* struct/union/enum declarations */ 79 int num; /* local type number */ 80 } *stabhash[STABHASH]; 81 static int ntypes; 82 static char *curfun; 83 static int stablbl = 10; 84 extern int inftn; 85 86 void ptype(char *name, int num, int inhnum, long long min, long long max); 87 struct stabtype *addtype(TWORD, union dimfun *, struct attr *); 88 struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue); 89 void printtype(struct symtab *s, char *str, int len); 90 void cprint(int p2, char *fmt, ...); 91 92 #define MAXPSTR 100 93 94 extern int isinlining; 95 96 /* 97 * Output type definitions for the stab debugging format. 98 * Note that "int" is always internal number 1. 99 */ 100 void 101 stabs_init(void) 102 { 103 struct stabtype *st; 104 105 #define ADDTYPE(y) addtype(y, NULL, 0) 106 107 ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT); 108 109 st = ADDTYPE(CHAR); 110 ptype("char", st->num, st->num, 0, MAX_CHAR); 111 ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT); 112 ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG); 113 ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM, 114 MIN_LONGLONG, MAX_LONGLONG); 115 ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR); 116 ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT); 117 ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED); 118 ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG); 119 ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM, 120 0, MAX_ULONGLONG); 121 122 ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0); 123 ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0); 124 ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0); 125 st = ADDTYPE(VOID); 126 cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n", 127 st->num, st->num, N_LSYM); 128 129 } 130 131 /* 132 * Print a type in stabs format 133 */ 134 void 135 ptype(char *name, int num, int inhnum, long long min, long long max) 136 { 137 cprint(0, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n", 138 name, num, inhnum, min, max, N_LSYM); 139 } 140 141 /* 142 * Add a new local type to the hash table. 143 * The search key is the (type, df, sue) triple. 144 */ 145 struct stabtype * 146 addtype(TWORD t, union dimfun *df, struct attr *ap) 147 { 148 struct stabtype *st; 149 150 st = permalloc(sizeof(struct stabtype)); 151 st->type = t; 152 st->df = df; 153 st->ap = ap; 154 st->num = ++ntypes; 155 st->next = stabhash[t & (STABHASH-1)]; 156 stabhash[t & (STABHASH-1)] = st; 157 return st; 158 } 159 160 /* 161 * Search for a given type and return a type pointer (or NULL). 162 */ 163 struct stabtype * 164 findtype(TWORD t, union dimfun *df, struct attr *ap) 165 { 166 struct stabtype *st; 167 union dimfun *dw, *dx; 168 TWORD tw; 169 170 st = stabhash[t & (STABHASH-1)]; 171 for (; st; st = st->next) { 172 if (t != st->type || ap != st->ap) 173 continue; 174 /* Ok, type and sue matches, check dimensions */ 175 if (st->df == NULL) 176 return st; /* no arrays, got match */ 177 dw = st->df; 178 dx = df; 179 tw = t; 180 for (; tw > BTMASK; tw = DECREF(tw)) { 181 if (ISARY(tw)) { 182 if (dw->ddim == dx->ddim) 183 dw++, dx++; 184 else 185 break; 186 } 187 } 188 if (tw <= BTMASK) 189 return st; 190 } 191 return NULL; 192 } 193 194 /* 195 * Print current line number. 196 */ 197 void 198 stabs_line(int line) 199 { 200 if (inftn == 0) 201 return; /* ignore */ 202 #ifdef STAB_LINE_ABSOLUTE 203 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", 204 N_SLINE, line, stablbl, stablbl); 205 #else 206 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", 207 N_SLINE, line, stablbl, curfun, stablbl); 208 #endif 209 stablbl++; 210 } 211 212 /* 213 * Start of block. 214 */ 215 void 216 stabs_lbrac(int blklvl) 217 { 218 #ifdef STAB_LINE_ABSOLUTE 219 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", 220 N_LBRAC, blklvl, stablbl, stablbl); 221 #else 222 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", 223 N_LBRAC, blklvl, stablbl, curfun, stablbl); 224 #endif 225 stablbl++; 226 } 227 228 /* 229 * End of block. 230 */ 231 void 232 stabs_rbrac(int blklvl) 233 { 234 #ifdef STAB_LINE_ABSOLUTE 235 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", 236 N_RBRAC, blklvl, stablbl, stablbl); 237 #else 238 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", 239 N_RBRAC, blklvl, stablbl, curfun, stablbl); 240 #endif 241 stablbl++; 242 } 243 244 static char *mainfile; 245 246 /* 247 * Print current file and set mark. 248 */ 249 void 250 stabs_file(char *fname) 251 { 252 if (mainfile == NULL) 253 mainfile = fname; /* first call */ 254 cprint(inftn, "\t.stabs \"%s\",%d,0,0," STABLBL "\n" STABLBL ":\n", 255 fname, fname == mainfile ? N_SO : N_SOL, stablbl, stablbl); 256 stablbl++; 257 } 258 259 /* 260 * Print end mark 261 */ 262 void 263 stabs_efile(char *fname) 264 { 265 cprint(inftn, "\t.stabs \"\",%d,0,0," STABLBL "\n" STABLBL ":\n", 266 fname == mainfile ? N_SO : N_SOL, stablbl, stablbl); 267 stablbl++; 268 } 269 270 /* 271 * Print beginning of function. 272 */ 273 void 274 stabs_func(struct symtab *s) 275 { 276 char str[MAXPSTR]; 277 278 curfun = getexname(s); 279 printtype(s, str, sizeof(str)); 280 cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n", 281 curfun, s->sclass == STATIC ? 'f' : 'F', str, 282 N_FUN, 0, curfun); 283 } 284 285 /* 286 * Print a (complex) type. 287 * Will also create subtypes. 288 * Printed string is like "20=*21=*1". 289 */ 290 void 291 printtype(struct symtab *s, char *ostr, int len) 292 { 293 struct stabtype *st; 294 union dimfun *df = s->sdf; 295 struct attr *ap = s->sap; 296 TWORD t = s->stype; 297 int op = 0; 298 299 /* Print out not-yet-found types */ 300 if (ISFTN(t)) 301 t = DECREF(t); 302 st = findtype(t, df, ap); 303 while (st == NULL && t > BTMASK) { 304 st = addtype(t, df, ap); 305 op+=snprintf(ostr+op, len - op, "%d=", st->num); 306 if (ISFTN(t)) 307 ostr[op++] = 'f'; 308 else if (ISPTR(t)) 309 ostr[op++] = '*'; 310 else if (ISARY(t)) { 311 op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1); 312 } else 313 cerror("printtype: notype"); 314 if (ISARY(t)) 315 df++; 316 t = DECREF(t); 317 st = findtype(t, df, ap); 318 if (op > MAXPSTR-10) 319 cerror("printtype: too difficult expression"); 320 } 321 /* print out basic type. may have to be entered in case of sue */ 322 snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num); 323 /* snprintf here null-terminated the string */ 324 } 325 326 void 327 stabs_newsym(struct symtab *s) 328 { 329 extern int fun_inline; 330 char *sname; 331 char ostr[MAXPSTR]; 332 OFFSZ suesize, sz; 333 334 if (ISFTN(s->stype)) 335 return; /* functions are handled separate */ 336 337 if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS || 338 s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE || 339 s->sclass == TYPEDEF || (s->sclass & FIELD) || ISSOU(s->stype)) 340 return; /* XXX - fix structs */ 341 342 sname = getexname(s); 343 sz = tsize(s->stype, s->sdf, s->sap); 344 suesize = BIT2BYTE(sz); 345 if (suesize > 32767) 346 suesize = 32767; 347 else if (suesize < -32768) 348 suesize = -32768; 349 350 printtype(s, ostr, sizeof(ostr)); 351 switch (s->sclass) { 352 case PARAM: 353 cprint(0, "\t.stabs \"%s:p%s\",%d,0," CONFMT ",%d\n", 354 sname, ostr, N_PSYM, (CONSZ)suesize, BIT2BYTE(s->soffset)); 355 break; 356 357 case AUTO: 358 cprint(0, "\t.stabs \"%s:%s\",%d,0," CONFMT ",%d\n", 359 sname, ostr, N_LSYM, (CONSZ)suesize, BIT2BYTE(s->soffset)); 360 break; 361 362 case STATIC: 363 if (blevel) 364 cprint(0, "\t.stabs \"%s:V%s\",%d,0," CONFMT "," LABFMT "\n", 365 sname, ostr, N_LCSYM, (CONSZ)suesize, s->soffset); 366 else 367 cprint(0, "\t.stabs \"%s:S%s\",%d,0," CONFMT ",%s\n", 368 sname, ostr, N_LCSYM, (CONSZ)suesize, sname); 369 break; 370 371 case EXTERN: 372 case EXTDEF: 373 cprint(0, "\t.stabs \"%s:G%s\",%d,0," CONFMT ",0\n", 374 sname, ostr, N_GSYM, (CONSZ)suesize); 375 break; 376 377 case REGISTER: 378 cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", 379 sname, ostr, N_RSYM, 1, s->soffset); 380 break; 381 382 case SNULL: 383 if (fun_inline) 384 break; 385 /* FALLTHROUGH */ 386 default: 387 cerror("fix stab_newsym; class %d", s->sclass); 388 } 389 } 390 391 void 392 stabs_chgsym(struct symtab *s) 393 { 394 } 395 396 /* 397 * define a struct. 398 */ 399 void 400 stabs_struct(struct symtab *p, struct attr *ap) 401 { 402 } 403 404 struct stabsv { 405 SLIST_ENTRY(stabsv) next; 406 char *str; 407 } ; 408 static SLIST_HEAD(, stabsv) stpole = { NULL, &stpole.q_forw }; 409 410 /* 411 * Global variable debug info is printed out directly. 412 * For functions and their declarations, both the labels and 413 * the debug info is put into ASM nodes and follows their statements 414 * into pass2. 415 * Due to the possible unsync between pass1 and 2 and where the 416 * stabs info for text is sent over the following syncing is used: 417 * curfun == 0 418 * print out everything; only data will be. 419 * curfun != 0 && inftn == 0 420 * save in linked list 421 * curfun != 0 && inftn != 0 422 * print linked list first, empty it, then arg. 423 */ 424 void 425 cprint(int p2, char *fmt, ...) 426 { 427 #define CPBSZ 200 428 char buf[CPBSZ]; 429 struct stabsv *w; 430 va_list ap; 431 char *str; 432 433 if (isinlining) 434 return; /* XXX do not save any inline functions currently */ 435 436 va_start(ap, fmt); 437 if (p2) { 438 if (vsnprintf(buf, CPBSZ, fmt, ap) >= CPBSZ) 439 werror("stab symbol line too long, truncating"); 440 str = tmpstrdup(buf); 441 if (inftn == 0) { 442 w = tmpalloc(sizeof(struct stabsv)); 443 w->str = str; 444 SLIST_INSERT_LAST(&stpole, w, next); 445 } else { 446 if (stpole.q_last != &stpole.q_forw) { 447 SLIST_FOREACH(w, &stpole, next) { 448 send_passt(IP_ASM, w->str); 449 } 450 SLIST_INIT(&stpole); 451 } 452 send_passt(IP_ASM, str); 453 } 454 } else 455 vprintf(fmt, ap); 456 va_end(ap); 457 } 458 459 #endif 460