source: mainline/uspace/app/pcc/cc/ccom/stabs.c@ fae4d30

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fae4d30 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/* $Id: stabs.c,v 1.31 2010/08/11 14:08:44 ragge 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#undef BIT2BYTE /* from external.h */
48#define BIT2BYTE(x) ((x)/SZCHAR)
49
50#ifndef STABLBL
51#error macdefs.h must define STABLBL
52#endif
53
54/* defines taken from BSD <stab.h> */
55#define N_GSYM 0x20 /* global symbol */
56#define N_FUN 0x24 /* procedure name */
57#define N_LCSYM 0x28 /* bss segment variable */
58#define N_RSYM 0x40 /* register variable */
59#define N_SLINE 0x44 /* text segment line number */
60#define N_SO 0x64 /* main source file name */
61#define N_LSYM 0x80 /* stack variable */
62#define N_SOL 0x84 /* included source file name */
63#define N_PSYM 0xa0 /* parameter variable */
64#define N_LBRAC 0xc0 /* left bracket */
65#define N_RBRAC 0xe0 /* right bracket */
66
67/*
68 * Local type mapping
69 * Types are defined as a typeword, a dimension pointer (in the case
70 * of arrays) and struct/union/enum declarations.
71 * Function prototypes are ignored.
72 */
73static struct stabtype {
74 struct stabtype *next; /* linked list */
75 TWORD type; /* pcc type number */
76 union dimfun *df; /* dimension of arrays */
77 struct attr *ap; /* struct/union/enum declarations */
78 int num; /* local type number */
79} *stabhash[STABHASH];
80static int ntypes;
81static char *curfun;
82static int stablbl = 10;
83extern int inftn;
84
85void ptype(char *name, int num, int inhnum, long long min, long long max);
86struct stabtype *addtype(TWORD, union dimfun *, struct attr *);
87struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue);
88void printtype(struct symtab *s, char *str, int len);
89void cprint(int p2, char *fmt, ...);
90
91#define MAXPSTR 100
92
93extern int isinlining;
94
95/*
96 * Output type definitions for the stab debugging format.
97 * Note that "int" is always internal number 1.
98 */
99void
100stabs_init()
101{
102 struct stabtype *st;
103
104#define ADDTYPE(y) addtype(y, NULL, MKAP(y))
105
106 ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT);
107
108 st = ADDTYPE(CHAR);
109 ptype("char", st->num, st->num, 0, MAX_CHAR);
110 ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT);
111 ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG);
112 ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM,
113 MIN_LONGLONG, MAX_LONGLONG);
114 ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR);
115 ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT);
116 ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED);
117 ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG);
118 ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM,
119 0, MAX_ULONGLONG);
120
121 ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0);
122 ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
123 ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
124 st = ADDTYPE(VOID);
125 cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n",
126 st->num, st->num, N_LSYM);
127
128}
129
130/*
131 * Print a type in stabs format
132 */
133void
134ptype(char *name, int num, int inhnum, long long min, long long max)
135{
136 cprint(0, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n",
137 name, num, inhnum, min, max, N_LSYM);
138}
139
140/*
141 * Add a new local type to the hash table.
142 * The search key is the (type, df, sue) triple.
143 */
144struct stabtype *
145addtype(TWORD t, union dimfun *df, struct attr *ap)
146{
147 struct stabtype *st;
148
149 st = permalloc(sizeof(struct stabtype));
150 st->type = t;
151 st->df = df;
152 st->ap = ap;
153 st->num = ++ntypes;
154 st->next = stabhash[t & (STABHASH-1)];
155 stabhash[t & (STABHASH-1)] = st;
156 return st;
157}
158
159/*
160 * Search for a given type and return a type pointer (or NULL).
161 */
162struct stabtype *
163findtype(TWORD t, union dimfun *df, struct attr *ap)
164{
165 struct stabtype *st;
166 union dimfun *dw, *dx;
167 TWORD tw;
168
169 st = stabhash[t & (STABHASH-1)];
170 for (; st; st = st->next) {
171 if (t != st->type || ap != st->ap)
172 continue;
173 /* Ok, type and sue matches, check dimensions */
174 if (st->df == NULL)
175 return st; /* no arrays, got match */
176 dw = st->df;
177 dx = df;
178 tw = t;
179 for (; tw > BTMASK; tw = DECREF(tw)) {
180 if (ISARY(tw)) {
181 if (dw->ddim == dx->ddim)
182 dw++, dx++;
183 else
184 break;
185 }
186 }
187 if (tw <= BTMASK)
188 return st;
189 }
190 return NULL;
191}
192
193/*
194 * Print current line number.
195 */
196void
197stabs_line(int line)
198{
199 if (inftn == 0)
200 return; /* ignore */
201#ifdef STAB_LINE_ABSOLUTE
202 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
203 N_SLINE, line, stablbl, stablbl);
204#else
205 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
206 N_SLINE, line, stablbl, curfun, stablbl);
207#endif
208 stablbl++;
209}
210
211/*
212 * Start of block.
213 */
214void
215stabs_lbrac(int blklvl)
216{
217#ifdef STAB_LINE_ABSOLUTE
218 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
219 N_LBRAC, blklvl, stablbl, stablbl);
220#else
221 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
222 N_LBRAC, blklvl, stablbl, curfun, stablbl);
223#endif
224 stablbl++;
225}
226
227/*
228 * End of block.
229 */
230void
231stabs_rbrac(int blklvl)
232{
233#ifdef STAB_LINE_ABSOLUTE
234 cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
235 N_RBRAC, blklvl, stablbl, stablbl);
236#else
237 cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
238 N_RBRAC, blklvl, stablbl, curfun, stablbl);
239#endif
240 stablbl++;
241}
242
243static char *mainfile;
244
245/*
246 * Print current file and set mark.
247 */
248void
249stabs_file(char *fname)
250{
251 if (mainfile == NULL)
252 mainfile = fname; /* first call */
253 cprint(inftn, "\t.stabs \"%s\",%d,0,0," STABLBL "\n" STABLBL ":\n",
254 fname, fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
255 stablbl++;
256}
257
258/*
259 * Print end mark
260 */
261void
262stabs_efile(char *fname)
263{
264 cprint(inftn, "\t.stabs \"\",%d,0,0," STABLBL "\n" STABLBL ":\n",
265 fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
266 stablbl++;
267}
268
269/*
270 * Print beginning of function.
271 */
272void
273stabs_func(struct symtab *s)
274{
275 char str[MAXPSTR];
276
277 if ((curfun = s->soname) == NULL)
278 curfun = addname(exname(s->sname));
279 printtype(s, str, sizeof(str));
280 cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n",
281 curfun, s->sclass == STATIC ? 'f' : 'F', str,
282 N_FUN, 0, curfun);
283}
284
285/*
286 * Print a (complex) type.
287 * Will also create subtypes.
288 * Printed string is like "20=*21=*1".
289 */
290void
291printtype(struct symtab *s, char *ostr, int len)
292{
293 struct stabtype *st;
294 union dimfun *df = s->sdf;
295 struct attr *ap = s->sap;
296 TWORD t = s->stype;
297 int op = 0;
298
299 /* Print out not-yet-found types */
300 if (ISFTN(t))
301 t = DECREF(t);
302 st = findtype(t, df, ap);
303 while (st == NULL && t > BTMASK) {
304 st = addtype(t, df, ap);
305 op+=snprintf(ostr+op, len - op, "%d=", st->num);
306 if (ISFTN(t))
307 ostr[op++] = 'f';
308 else if (ISPTR(t))
309 ostr[op++] = '*';
310 else if (ISARY(t)) {
311 op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1);
312 } else
313 cerror("printtype: notype");
314 if (ISARY(t))
315 df++;
316 t = DECREF(t);
317 st = findtype(t, df, ap);
318 if (op > MAXPSTR-10)
319 cerror("printtype: too difficult expression");
320 }
321 /* print out basic type. may have to be entered in case of sue */
322 snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num);
323 /* snprintf here null-terminated the string */
324}
325
326void
327stabs_newsym(struct symtab *s)
328{
329 extern int fun_inline;
330 char *sname;
331 char ostr[MAXPSTR];
332 int suesize, sz;
333
334 if (ISFTN(s->stype))
335 return; /* functions are handled separate */
336
337 if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS ||
338 s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE ||
339 s->sclass == TYPEDEF || (s->sclass & FIELD) || ISSOU(s->stype))
340 return; /* XXX - fix structs */
341
342 if ((sname = s->soname) == NULL)
343 sname = exname(s->sname);
344 sz = tsize(s->stype, s->sdf, s->sap);
345 suesize = BIT2BYTE(sz);
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
391void
392stabs_chgsym(struct symtab *s)
393{
394}
395
396/*
397 * define a struct.
398 */
399void
400stabs_struct(struct symtab *p, struct attr *ap)
401{
402}
403
404struct stabsv {
405 SLIST_ENTRY(stabsv) next;
406 char *str;
407} ;
408static 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 */
424void
425cprint(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
Note: See TracBrowser for help on using the repository browser.