1 /* $Id: stabs.c,v 1.3 2012/04/22 21:07:41 plunky Exp $ */
4 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
41 #include <sys/types.h>
46 #define INTNUM 1 /* internal number of type "int" */
47 #undef BIT2BYTE /* from external.h */
48 #define BIT2BYTE(x) ((x)/SZCHAR)
51 #error macdefs.h must define STABLBL
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 */
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.
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
];
82 static int stablbl
= 10;
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
, ...);
93 extern int isinlining
;
96 * Output type definitions for the stab debugging format.
97 * Note that "int" is always internal number 1.
104 #define ADDTYPE(y) addtype(y, NULL, 0)
106 ptype("int", ADDTYPE(INT
)->num
, INTNUM
, MIN_INT
, MAX_INT
);
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
,
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);
125 cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n",
126 st
->num
, st
->num
, N_LSYM
);
131 * Print a type in stabs format
134 ptype(char *name
, int num
, int inhnum
, long long min
, long long max
)
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
);
141 * Add a new local type to the hash table.
142 * The search key is the (type, df, sue) triple.
145 addtype(TWORD t
, union dimfun
*df
, struct attr
*ap
)
149 st
= permalloc(sizeof(struct stabtype
));
154 st
->next
= stabhash
[t
& (STABHASH
-1)];
155 stabhash
[t
& (STABHASH
-1)] = st
;
160 * Search for a given type and return a type pointer (or NULL).
163 findtype(TWORD t
, union dimfun
*df
, struct attr
*ap
)
166 union dimfun
*dw
, *dx
;
169 st
= stabhash
[t
& (STABHASH
-1)];
170 for (; st
; st
= st
->next
) {
171 if (t
!= st
->type
|| ap
!= st
->ap
)
173 /* Ok, type and sue matches, check dimensions */
175 return st
; /* no arrays, got match */
179 for (; tw
> BTMASK
; tw
= DECREF(tw
)) {
181 if (dw
->ddim
== dx
->ddim
)
194 * Print current line number.
201 #ifdef STAB_LINE_ABSOLUTE
202 cprint(1, "\t.stabn %d,0,%d," STABLBL
"\n" STABLBL
":\n",
203 N_SLINE
, line
, stablbl
, stablbl
);
205 cprint(1, "\t.stabn %d,0,%d," STABLBL
"-%s\n" STABLBL
":\n",
206 N_SLINE
, line
, stablbl
, curfun
, stablbl
);
215 stabs_lbrac(int blklvl
)
217 #ifdef STAB_LINE_ABSOLUTE
218 cprint(1, "\t.stabn %d,0,%d," STABLBL
"\n" STABLBL
":\n",
219 N_LBRAC
, blklvl
, stablbl
, stablbl
);
221 cprint(1, "\t.stabn %d,0,%d," STABLBL
"-%s\n" STABLBL
":\n",
222 N_LBRAC
, blklvl
, stablbl
, curfun
, stablbl
);
231 stabs_rbrac(int blklvl
)
233 #ifdef STAB_LINE_ABSOLUTE
234 cprint(1, "\t.stabn %d,0,%d," STABLBL
"\n" STABLBL
":\n",
235 N_RBRAC
, blklvl
, stablbl
, stablbl
);
237 cprint(1, "\t.stabn %d,0,%d," STABLBL
"-%s\n" STABLBL
":\n",
238 N_RBRAC
, blklvl
, stablbl
, curfun
, stablbl
);
243 static char *mainfile
;
246 * Print current file and set mark.
249 stabs_file(char *fname
)
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
);
262 stabs_efile(char *fname
)
264 cprint(inftn
, "\t.stabs \"\",%d,0,0," STABLBL
"\n" STABLBL
":\n",
265 fname
== mainfile
? N_SO
: N_SOL
, stablbl
, stablbl
);
270 * Print beginning of function.
273 stabs_func(struct symtab
*s
)
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
,
286 * Print a (complex) type.
287 * Will also create subtypes.
288 * Printed string is like "20=*21=*1".
291 printtype(struct symtab
*s
, char *ostr
, int len
)
294 union dimfun
*df
= s
->sdf
;
295 struct attr
*ap
= s
->sap
;
299 /* Print out not-yet-found types */
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
);
311 op
+=snprintf(ostr
+op
, len
- op
, "ar%d;0;%d;", INTNUM
, df
->ddim
-1);
313 cerror("printtype: notype");
317 st
= findtype(t
, df
, ap
);
319 cerror("printtype: too difficult expression");
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 */
327 stabs_newsym(struct symtab
*s
)
329 extern int fun_inline
;
335 return; /* functions are handled separate */
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 */
342 if ((sname
= s
->soname
) == NULL
)
343 sname
= exname(s
->sname
);
344 sz
= tsize(s
->stype
, s
->sdf
, s
->sap
);
345 suesize
= BIT2BYTE(sz
);
348 else if (suesize
< -32768)
351 printtype(s
, ostr
, sizeof(ostr
));
354 cprint(0, "\t.stabs \"%s:p%s\",%d,0," CONFMT
",%d\n",
355 sname
, ostr
, N_PSYM
, (CONSZ
)suesize
, BIT2BYTE(s
->soffset
));
359 cprint(0, "\t.stabs \"%s:%s\",%d,0," CONFMT
",%d\n",
360 sname
, ostr
, N_LSYM
, (CONSZ
)suesize
, BIT2BYTE(s
->soffset
));
365 cprint(0, "\t.stabs \"%s:V%s\",%d,0," CONFMT
"," LABFMT
"\n",
366 sname
, ostr
, N_LCSYM
, (CONSZ
)suesize
, s
->soffset
);
368 cprint(0, "\t.stabs \"%s:S%s\",%d,0," CONFMT
",%s\n",
369 sname
, ostr
, N_LCSYM
, (CONSZ
)suesize
, sname
);
374 cprint(0, "\t.stabs \"%s:G%s\",%d,0," CONFMT
",0\n",
375 sname
, ostr
, N_GSYM
, (CONSZ
)suesize
);
379 cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n",
380 sname
, ostr
, N_RSYM
, 1, s
->soffset
);
388 cerror("fix stab_newsym; class %d", s
->sclass
);
393 stabs_chgsym(struct symtab
*s
)
401 stabs_struct(struct symtab
*p
, struct attr
*ap
)
406 SLIST_ENTRY(stabsv
) next
;
409 static SLIST_HEAD(, stabsv
) stpole
= { NULL
, &stpole
.q_forw
};
412 * Global variable debug info is printed out directly.
413 * For functions and their declarations, both the labels and
414 * the debug info is put into ASM nodes and follows their statements
416 * Due to the possible unsync between pass1 and 2 and where the
417 * stabs info for text is sent over the following syncing is used:
419 * print out everything; only data will be.
420 * curfun != 0 && inftn == 0
421 * save in linked list
422 * curfun != 0 && inftn != 0
423 * print linked list first, empty it, then arg.
426 cprint(int p2
, char *fmt
, ...)
435 return; /* XXX do not save any inline functions currently */
439 if (vsnprintf(buf
, CPBSZ
, fmt
, ap
) >= CPBSZ
)
440 werror("stab symbol line too long, truncating");
441 str
= tmpstrdup(buf
);
443 w
= tmpalloc(sizeof(struct stabsv
));
445 SLIST_INSERT_LAST(&stpole
, w
, next
);
447 if (stpole
.q_last
!= &stpole
.q_forw
) {
448 SLIST_FOREACH(w
, &stpole
, next
) {
449 send_passt(IP_ASM
, w
->str
);
453 send_passt(IP_ASM
, str
);