1 /* Id: stabs.c,v 1.30 2009/06/14 11:43:41 ragge Exp */ 2 /* $NetBSD: stabs.c,v 1.1.1.3 2010/06/03 18:57:43 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 suedef *sue; /* 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 suedef *); 88 struct stabtype *findtype(TWORD t, union dimfun *df, struct suedef *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() 102 { 103 struct stabtype *st; 104 105 #define ADDTYPE(y) addtype(y, NULL, MKSUE(y)) 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 suedef *sue) 147 { 148 struct stabtype *st; 149 150 st = permalloc(sizeof(struct stabtype)); 151 st->type = t; 152 st->df = df; 153 st->sue = sue; 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 suedef *sue) 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 || sue != st->sue) 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 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, BIT2BYTE(s->ssue->suesize), curfun); 284 } 285 286 /* 287 * Print a (complex) type. 288 * Will also create subtypes. 289 * Printed string is like "20=*21=*1". 290 */ 291 void 292 printtype(struct symtab *s, char *ostr, int len) 293 { 294 struct stabtype *st; 295 union dimfun *df = s->sdf; 296 struct suedef *sue = s->ssue; 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, sue); 304 while (st == NULL && t > BTMASK) { 305 st = addtype(t, df, sue); 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, sue); 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 327 void 328 stabs_newsym(struct symtab *s) 329 { 330 extern int fun_inline; 331 char *sname; 332 char ostr[MAXPSTR]; 333 int suesize; 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)) 341 return; /* XXX - fix structs */ 342 343 if ((sname = s->soname) == NULL) 344 sname = exname(s->sname); 345 suesize = BIT2BYTE(s->ssue->suesize); 346 if (suesize > 32767) 347 suesize = 32767; 348 else if (suesize < -32768) 349 suesize = -32768; 350 351 printtype(s, ostr, sizeof(ostr)); 352 switch (s->sclass) { 353 case PARAM: 354 cprint(0, "\t.stabs \"%s:p%s\",%d,0,%d,%d\n", sname, ostr, 355 N_PSYM, suesize, BIT2BYTE(s->soffset)); 356 break; 357 358 case AUTO: 359 cprint(0, "\t.stabs \"%s:%s\",%d,0,%d,%d\n", sname, ostr, 360 N_LSYM, suesize, BIT2BYTE(s->soffset)); 361 break; 362 363 case STATIC: 364 if (blevel) 365 cprint(0, "\t.stabs \"%s:V%s\",%d,0,%d," LABFMT "\n", sname, ostr, 366 N_LCSYM, suesize, s->soffset); 367 else 368 cprint(0, "\t.stabs \"%s:S%s\",%d,0,%d,%s\n", sname, ostr, 369 N_LCSYM, suesize, sname); 370 break; 371 372 case EXTERN: 373 case EXTDEF: 374 cprint(0, "\t.stabs \"%s:G%s\",%d,0,%d,0\n", sname, ostr, 375 N_GSYM, suesize); 376 break; 377 378 case REGISTER: 379 cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", sname, ostr, 380 N_RSYM, 1, s->soffset); 381 break; 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 suedef *sue) 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