xref: /netbsd-src/external/bsd/pcc/dist/pcc/cc/ccom/stabs.c (revision 4817a0b0b8fe9612e8ebe21a9bf2d97b95038a97)
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