1/* Id: stabs.c,v 1.3 2012/04/22 21:07:41 plunky Exp */ 2/* $NetBSD$ */ 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 */ 74static 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]; 81static int ntypes; 82static char *curfun; 83static int stablbl = 10; 84extern int inftn; 85 86void ptype(char *name, int num, int inhnum, long long min, long long max); 87struct stabtype *addtype(TWORD, union dimfun *, struct attr *); 88struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue); 89void printtype(struct symtab *s, char *str, int len); 90void cprint(int p2, char *fmt, ...); 91 92#define MAXPSTR 100 93 94extern int isinlining; 95 96/* 97 * Output type definitions for the stab debugging format. 98 * Note that "int" is always internal number 1. 99 */ 100void 101stabs_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 */ 134void 135ptype(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 */ 145struct stabtype * 146addtype(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 */ 163struct stabtype * 164findtype(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 */ 197void 198stabs_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 */ 215void 216stabs_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 */ 231void 232stabs_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 244static char *mainfile; 245 246/* 247 * Print current file and set mark. 248 */ 249void 250stabs_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 */ 262void 263stabs_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 */ 273void 274stabs_func(struct symtab *s) 275{ 276 char str[MAXPSTR]; 277 278 if ((curfun = s->soname) == NULL) 279 curfun = addname(exname(s->sname)); 280 printtype(s, str, sizeof(str)); 281 cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n", 282 curfun, s->sclass == STATIC ? 'f' : 'F', str, 283 N_FUN, 0, curfun); 284} 285 286/* 287 * Print a (complex) type. 288 * Will also create subtypes. 289 * Printed string is like "20=*21=*1". 290 */ 291void 292printtype(struct symtab *s, char *ostr, int len) 293{ 294 struct stabtype *st; 295 union dimfun *df = s->sdf; 296 struct attr *ap = s->sap; 297 TWORD t = s->stype; 298 int op = 0; 299 300 /* Print out not-yet-found types */ 301 if (ISFTN(t)) 302 t = DECREF(t); 303 st = findtype(t, df, ap); 304 while (st == NULL && t > BTMASK) { 305 st = addtype(t, df, ap); 306 op+=snprintf(ostr+op, len - op, "%d=", st->num); 307 if (ISFTN(t)) 308 ostr[op++] = 'f'; 309 else if (ISPTR(t)) 310 ostr[op++] = '*'; 311 else if (ISARY(t)) { 312 op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1); 313 } else 314 cerror("printtype: notype"); 315 if (ISARY(t)) 316 df++; 317 t = DECREF(t); 318 st = findtype(t, df, ap); 319 if (op > MAXPSTR-10) 320 cerror("printtype: too difficult expression"); 321 } 322 /* print out basic type. may have to be entered in case of sue */ 323 snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num); 324 /* snprintf here null-terminated the string */ 325} 326 327void 328stabs_newsym(struct symtab *s) 329{ 330 extern int fun_inline; 331 char *sname; 332 char ostr[MAXPSTR]; 333 OFFSZ suesize, sz; 334 335 if (ISFTN(s->stype)) 336 return; /* functions are handled separate */ 337 338 if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS || 339 s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE || 340 s->sclass == TYPEDEF || (s->sclass & FIELD) || ISSOU(s->stype)) 341 return; /* XXX - fix structs */ 342 343 if ((sname = s->soname) == NULL) 344 sname = exname(s->sname); 345 sz = tsize(s->stype, s->sdf, s->sap); 346 suesize = BIT2BYTE(sz); 347 if (suesize > 32767) 348 suesize = 32767; 349 else if (suesize < -32768) 350 suesize = -32768; 351 352 printtype(s, ostr, sizeof(ostr)); 353 switch (s->sclass) { 354 case PARAM: 355 cprint(0, "\t.stabs \"%s:p%s\",%d,0," CONFMT ",%d\n", 356 sname, ostr, N_PSYM, (CONSZ)suesize, BIT2BYTE(s->soffset)); 357 break; 358 359 case AUTO: 360 cprint(0, "\t.stabs \"%s:%s\",%d,0," CONFMT ",%d\n", 361 sname, ostr, N_LSYM, (CONSZ)suesize, BIT2BYTE(s->soffset)); 362 break; 363 364 case STATIC: 365 if (blevel) 366 cprint(0, "\t.stabs \"%s:V%s\",%d,0," CONFMT "," LABFMT "\n", 367 sname, ostr, N_LCSYM, (CONSZ)suesize, s->soffset); 368 else 369 cprint(0, "\t.stabs \"%s:S%s\",%d,0," CONFMT ",%s\n", 370 sname, ostr, N_LCSYM, (CONSZ)suesize, sname); 371 break; 372 373 case EXTERN: 374 case EXTDEF: 375 cprint(0, "\t.stabs \"%s:G%s\",%d,0," CONFMT ",0\n", 376 sname, ostr, N_GSYM, (CONSZ)suesize); 377 break; 378 379 case REGISTER: 380 cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", 381 sname, ostr, N_RSYM, 1, s->soffset); 382 break; 383 384 case SNULL: 385 if (fun_inline) 386 break; 387 /* FALLTHROUGH */ 388 default: 389 cerror("fix stab_newsym; class %d", s->sclass); 390 } 391} 392 393void 394stabs_chgsym(struct symtab *s) 395{ 396} 397 398/* 399 * define a struct. 400 */ 401void 402stabs_struct(struct symtab *p, struct attr *ap) 403{ 404} 405 406struct stabsv { 407 SLIST_ENTRY(stabsv) next; 408 char *str; 409} ; 410static SLIST_HEAD(, stabsv) stpole = { NULL, &stpole.q_forw }; 411 412/* 413 * Global variable debug info is printed out directly. 414 * For functions and their declarations, both the labels and 415 * the debug info is put into ASM nodes and follows their statements 416 * into pass2. 417 * Due to the possible unsync between pass1 and 2 and where the 418 * stabs info for text is sent over the following syncing is used: 419 * curfun == 0 420 * print out everything; only data will be. 421 * curfun != 0 && inftn == 0 422 * save in linked list 423 * curfun != 0 && inftn != 0 424 * print linked list first, empty it, then arg. 425 */ 426void 427cprint(int p2, char *fmt, ...) 428{ 429#define CPBSZ 200 430 char buf[CPBSZ]; 431 struct stabsv *w; 432 va_list ap; 433 char *str; 434 435 if (isinlining) 436 return; /* XXX do not save any inline functions currently */ 437 438 va_start(ap, fmt); 439 if (p2) { 440 if (vsnprintf(buf, CPBSZ, fmt, ap) >= CPBSZ) 441 werror("stab symbol line too long, truncating"); 442 str = tmpstrdup(buf); 443 if (inftn == 0) { 444 w = tmpalloc(sizeof(struct stabsv)); 445 w->str = str; 446 SLIST_INSERT_LAST(&stpole, w, next); 447 } else { 448 if (stpole.q_last != &stpole.q_forw) { 449 SLIST_FOREACH(w, &stpole, next) { 450 send_passt(IP_ASM, w->str); 451 } 452 SLIST_INIT(&stpole); 453 } 454 send_passt(IP_ASM, str); 455 } 456 } else 457 vprintf(fmt, ap); 458 va_end(ap); 459} 460 461#endif 462