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