new date 20231021
[pcc.git] / cc / ccom / stabs.c
blob21c3bd52efec9c8a131e7f4987f8194230b74a87
1 /* $Id: stabs.c,v 1.38 2023/07/29 09:34:43 ragge Exp $ */
3 /*
4 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
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
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.
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.
37 #include "pass1.h"
39 #undef n_type
40 #define n_type ptype
41 #undef n_qual
42 #define n_qual pqual
43 #undef n_df
44 #define n_df pdf
47 #ifdef STABS
49 #include <sys/types.h>
50 #include <stdarg.h>
51 #include <string.h>
53 #define STABHASH 256
54 #define INTNUM 1 /* internal number of type "int" */
55 #undef BIT2BYTE /* from external.h */
56 #define BIT2BYTE(x) ((x)/SZCHAR)
58 #ifndef STABLBL
59 #error macdefs.h must define STABLBL
60 #endif
62 /* defines taken from BSD <stab.h> */
63 #define N_GSYM 0x20 /* global symbol */
64 #define N_FUN 0x24 /* procedure name */
65 #define N_LCSYM 0x28 /* bss segment variable */
66 #define N_RSYM 0x40 /* register variable */
67 #define N_SLINE 0x44 /* text segment line number */
68 #define N_SO 0x64 /* main source file name */
69 #define N_LSYM 0x80 /* stack variable */
70 #define N_SOL 0x84 /* included source file name */
71 #define N_PSYM 0xa0 /* parameter variable */
72 #define N_LBRAC 0xc0 /* left bracket */
73 #define N_RBRAC 0xe0 /* right bracket */
76 * Local type mapping
77 * Types are defined as a typeword, a dimension pointer (in the case
78 * of arrays) and struct/union/enum declarations.
79 * Function prototypes are ignored.
81 static struct stabtype {
82 struct stabtype *next; /* linked list */
83 TWORD type; /* pcc type number */
84 union dimfun *df; /* dimension of arrays */
85 struct attr *ap; /* struct/union/enum declarations */
86 int num; /* local type number */
87 } *stabhash[STABHASH];
88 static int ntypes;
89 static char *curfun;
90 static int stablbl = 10;
91 extern int inftn;
93 void sptype(char *name, int num, int inhnum, long long min, long long max);
94 struct stabtype *addtype(TWORD, union dimfun *, struct attr *);
95 struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue);
96 void printtype(struct symtab *s, char *str, int len);
97 void cprint(int p2, char *fmt, ...);
99 #define MAXPSTR 100
101 extern int isinlining;
104 * Output type definitions for the stab debugging format.
105 * Note that "int" is always internal number 1.
107 void
108 stabs_init(void)
110 struct stabtype *st;
112 #define ADDTYPE(y) addtype(y, NULL, 0)
114 sptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT);
116 st = ADDTYPE(CHAR);
117 sptype("char", st->num, st->num, 0, MAX_CHAR);
118 sptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT);
119 sptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG);
120 sptype("long long", ADDTYPE(LONGLONG)->num, INTNUM,
121 MIN_LONGLONG, MAX_LONGLONG);
122 sptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR);
123 sptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT);
124 sptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED);
125 sptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG);
126 sptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM,
127 0, MAX_ULONGLONG);
129 sptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0);
130 sptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
131 sptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
132 st = ADDTYPE(VOID);
133 cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n",
134 st->num, st->num, N_LSYM);
139 * Print a type in stabs format
141 void
142 sptype(char *name, int num, int inhnum, long long min, long long max)
144 cprint(0, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n",
145 name, num, inhnum, min, max, N_LSYM);
149 * Add a new local type to the hash table.
150 * The search key is the (type, df, sue) triple.
152 struct stabtype *
153 addtype(TWORD t, union dimfun *df, struct attr *ap)
155 struct stabtype *st;
157 st = permalloc(sizeof(struct stabtype));
158 st->type = t;
159 st->df = df;
160 st->ap = ap;
161 st->num = ++ntypes;
162 st->next = stabhash[t & (STABHASH-1)];
163 stabhash[t & (STABHASH-1)] = st;
164 return st;
168 * Search for a given type and return a type pointer (or NULL).
170 struct stabtype *
171 findtype(TWORD t, union dimfun *df, struct attr *ap)
173 struct stabtype *st;
174 union dimfun *dw, *dx;
175 TWORD tw;
177 st = stabhash[t & (STABHASH-1)];
178 for (; st; st = st->next) {
179 if (t != st->type || ap != st->ap)
180 continue;
181 /* Ok, type and sue matches, check dimensions */
182 if (st->df == NULL)
183 return st; /* no arrays, got match */
184 dw = st->df;
185 dx = df;
186 tw = t;
187 for (; tw > BTMASK; tw = DECREF(tw)) {
188 if (ISARY(tw)) {
189 if (dw->ddim == dx->ddim)
190 dw++, dx++;
191 else
192 break;
195 if (tw <= BTMASK)
196 return st;
198 return NULL;
202 * Print current line number.
204 void
205 stabs_line(int line)
207 if (inftn == 0)
208 return; /* ignore */
209 #ifdef STAB_LINE_ABSOLUTE
210 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
211 N_SLINE, line, stablbl, stablbl);
212 #else
213 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
214 N_SLINE, line, stablbl, curfun, stablbl);
215 #endif
216 stablbl++;
220 * Start of block.
222 void
223 stabs_lbrac(int blklvl)
225 #ifdef STAB_LINE_ABSOLUTE
226 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
227 N_LBRAC, blklvl, stablbl, stablbl);
228 #else
229 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
230 N_LBRAC, blklvl, stablbl, curfun, stablbl);
231 #endif
232 stablbl++;
236 * End of block.
238 void
239 stabs_rbrac(int blklvl)
241 #ifdef STAB_LINE_ABSOLUTE
242 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
243 N_RBRAC, blklvl, stablbl, stablbl);
244 #else
245 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
246 N_RBRAC, blklvl, stablbl, curfun, stablbl);
247 #endif
248 stablbl++;
251 static char *mainfile;
254 * Print current file and set mark.
256 void
257 stabs_file(char *fname)
259 if (mainfile == NULL)
260 mainfile = fname; /* first call */
261 cprint(inftn, "\t.stabs \"%s\",%d,0,0," STABLBL "\n" STABLBL ":\n",
262 fname, fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
263 stablbl++;
267 * Print end mark
269 void
270 stabs_efile(char *fname)
272 cprint(inftn, "\t.stabs \"\",%d,0,0," STABLBL "\n" STABLBL ":\n",
273 fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
274 stablbl++;
278 * Print beginning of function.
280 void
281 stabs_func(struct symtab *s)
283 char str[MAXPSTR];
285 curfun = getexname(s);
286 printtype(s, str, sizeof(str));
287 cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n",
288 curfun, s->sclass == STATIC ? 'f' : 'F', str,
289 N_FUN, 0, curfun);
293 * Print a (complex) type.
294 * Will also create subtypes.
295 * Printed string is like "20=*21=*1".
297 void
298 printtype(struct symtab *s, char *ostr, int len)
300 struct stabtype *st;
301 union dimfun *df = s->sdf;
302 struct attr *ap = s->sap;
303 TWORD t = s->stype;
304 int op = 0;
306 /* Print out not-yet-found types */
307 if (ISFTN(t))
308 t = DECREF(t);
309 st = findtype(t, df, ap);
310 while (st == NULL && t > BTMASK) {
311 st = addtype(t, df, ap);
312 op+=snprintf(ostr+op, len - op, "%d=", st->num);
313 if (ISFTN(t))
314 ostr[op++] = 'f';
315 else if (ISPTR(t))
316 ostr[op++] = '*';
317 else if (ISARY(t)) {
318 op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1);
319 } else
320 cerror("printtype: notype");
321 if (ISARY(t))
322 df++;
323 t = DECREF(t);
324 st = findtype(t, df, ap);
325 if (op > MAXPSTR-10)
326 cerror("printtype: too difficult expression");
328 /* print out basic type. may have to be entered in case of sue */
329 snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num);
330 /* snprintf here null-terminated the string */
333 void
334 stabs_newsym(struct symtab *s)
336 extern int fun_inline;
337 char *sname;
338 char ostr[MAXPSTR];
339 OFFSZ suesize, sz;
341 if (ISFTN(s->stype))
342 return; /* functions are handled separate */
344 if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS ||
345 s->sclass == ENAME || s->sclass == MOU || s->sclass == CCONST ||
346 s->sclass == TYPEDEF || (s->sclass & FIELD) || ISSOU(s->stype))
347 return; /* XXX - fix structs */
349 sname = getexname(s);
350 sz = tsize(s->stype, s->sdf, s->sss);
351 suesize = BIT2BYTE(sz);
352 if (suesize > 32767)
353 suesize = 32767;
354 else if (suesize < -32768)
355 suesize = -32768;
357 printtype(s, ostr, sizeof(ostr));
358 switch (s->sclass) {
359 case PARAM:
360 cprint(0, "\t.stabs \"%s:p%s\",%d,0," CONFMT ",%d\n",
361 sname, ostr, N_PSYM, (CONSZ)suesize, BIT2BYTE(s->soffset));
362 break;
364 case AUTO:
365 cprint(0, "\t.stabs \"%s:%s\",%d,0," CONFMT ",%d\n",
366 sname, ostr, N_LSYM, (CONSZ)suesize, BIT2BYTE(s->soffset));
367 break;
369 case STATIC:
370 if (blevel)
371 cprint(0, "\t.stabs \"%s:V%s\",%d,0," CONFMT "," LABFMT "\n",
372 sname, ostr, N_LCSYM, (CONSZ)suesize, s->soffset);
373 else
374 cprint(0, "\t.stabs \"%s:S%s\",%d,0," CONFMT ",%s\n",
375 sname, ostr, N_LCSYM, (CONSZ)suesize, sname);
376 break;
378 case EXTERN:
379 case EXTDEF:
380 cprint(0, "\t.stabs \"%s:G%s\",%d,0," CONFMT ",0\n",
381 sname, ostr, N_GSYM, (CONSZ)suesize);
382 break;
384 case REGISTER:
385 cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n",
386 sname, ostr, N_RSYM, 1, s->soffset);
387 break;
389 case SNULL:
390 if (fun_inline)
391 break;
392 /* FALLTHROUGH */
393 default:
394 cerror("fix stab_newsym; class %d", s->sclass);
398 void
399 stabs_chgsym(struct symtab *s)
404 * define a struct.
406 void
407 stabs_struct(struct symtab *p)
411 struct stabsv {
412 SLIST_ENTRY(stabsv) next;
413 char *str;
415 static SLIST_HEAD(, stabsv) stpole = { NULL, &stpole.q_forw };
418 * Global variable debug info is printed out directly.
419 * For functions and their declarations, both the labels and
420 * the debug info is put into ASM nodes and follows their statements
421 * into pass2.
422 * Due to the possible unsync between pass1 and 2 and where the
423 * stabs info for text is sent over the following syncing is used:
424 * curfun == 0
425 * print out everything; only data will be.
426 * curfun != 0 && inftn == 0
427 * save in linked list
428 * curfun != 0 && inftn != 0
429 * print linked list first, empty it, then arg.
431 void
432 cprint(int p2, char *fmt, ...)
434 #define CPBSZ 200
435 char buf[CPBSZ];
436 struct stabsv *w;
437 va_list ap;
438 char *str;
440 if (isinlining)
441 return; /* XXX do not save any inline functions currently */
443 va_start(ap, fmt);
444 if (p2) {
445 if (vsnprintf(buf, CPBSZ, fmt, ap) >= CPBSZ)
446 werror("stab symbol line too long, truncating");
447 str = tmpstrdup(buf);
448 if (inftn == 0) {
449 w = tmpalloc(sizeof(struct stabsv));
450 w->str = str;
451 SLIST_INSERT_LAST(&stpole, w, next);
452 } else {
453 if (stpole.q_last != &stpole.q_forw) {
454 SLIST_FOREACH(w, &stpole, next) {
455 send_passt(IP_ASM, w->str);
457 SLIST_INIT(&stpole);
459 send_passt(IP_ASM, str);
461 } else
462 vprintf(fmt, ap);
463 va_end(ap);
466 #endif