~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/app/pcc/cc/ccom/stabs.c

  • Committer: Jakub Jermar
  • Date: 2011-09-07 22:19:24 UTC
  • mfrom: (1113.1.41 devel)
  • Revision ID: jakub@jermar.eu-20110907221924-cfgktigu4e8l0uyv
Merge from lp:~helenos-posix/helenos/devel.

* Petr Koupy's port of binutils.
* Jiri Zarevucky's port of pcc.
* Petr and Jiri's libposix library.
* Changes needed to make it all work together.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
73
static 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];
 
80
static int ntypes;
 
81
static char *curfun;
 
82
static int stablbl = 10;
 
83
extern int inftn;
 
84
 
 
85
void ptype(char *name, int num, int inhnum, long long min, long long max);
 
86
struct stabtype *addtype(TWORD, union dimfun *, struct attr *);
 
87
struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue);
 
88
void printtype(struct symtab *s, char *str, int len);
 
89
void cprint(int p2, char *fmt, ...);
 
90
 
 
91
#define MAXPSTR 100
 
92
 
 
93
extern int isinlining;
 
94
 
 
95
/*
 
96
 * Output type definitions for the stab debugging format.
 
97
 * Note that "int" is always internal number 1.
 
98
 */
 
99
void
 
100
stabs_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
 */
 
133
void
 
134
ptype(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
 */
 
144
struct stabtype *
 
145
addtype(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
 */
 
162
struct stabtype *
 
163
findtype(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
 */
 
196
void
 
197
stabs_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
 */
 
214
void
 
215
stabs_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
 */
 
230
void
 
231
stabs_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
 
 
243
static char *mainfile;
 
244
 
 
245
/*
 
246
 * Print current file and set mark.
 
247
 */
 
248
void
 
249
stabs_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
 */
 
261
void
 
262
stabs_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
 */
 
272
void
 
273
stabs_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
 */
 
290
void
 
291
printtype(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
 
 
326
void
 
327
stabs_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
 
 
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 attr *ap)
 
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