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