+ Update 052_Rob_Ennals.pdf, courtesy of Elizabeth Mattijsen.
[parrot.git] / src / jit_debug.c
blobe02a5c6044f63d4595e868f8d78551d5da3127af
1 /*
2 Copyright (C) 2001-2006, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/jit_debug.c - Write stabs file for JIT code
9 =head1 SYNOPSIS
11 When debugging JIT code with C<gdb>, do:
13 add-symbol-file <file.o> 0
15 =head1 DESCRIPTION
17 Stabs is a file format for information that describes a program to a
18 debugger.
20 For more information see the stabs documentation at
21 http://sources.redhat.com/gdb/current/onlinedocs/stabs_toc.html.
23 =head2 Functions
25 =over 4
27 =cut
31 #include <parrot/parrot.h>
32 #include "parrot/exec.h"
33 #include "jit.h"
35 #define N_GSYM "32" /* global variable */
36 #define N_FNAME "34"
37 #define N_FUN "36"
38 #define N_STSYM "38" /* variable in data section */
39 #define N_LCSYM "40" /* bss section */
40 #define N_MAIN "42"
41 #define N_ROSYM "44"
42 #define N_PC "48"
43 #define N_NSYMS "50"
44 #define N_NOMAP "52"
45 #define N_OBJ "56"
46 #define N_OPT "60"
47 #define N_RSYM "64" /* register variable */
48 #define N_M2C "66"
49 #define N_SLINE "68"
50 #define N_DSLINE "70"
51 #define N_BSLINE "72"
52 #define N_BROWS "72"
53 #define N_DEFD "74"
54 #define N_FLINE "76"
55 #define N_EHDECL "80"
56 #define N_MOD2 "80"
57 #define N_CATCH "84"
58 #define N_SSYM "96"
59 #define N_ENDM "98"
60 #define N_SO "100" /* filename */
61 #define N_LSYM "128" /* stack variable */
62 #define N_BINCL "130"
63 #define N_SOL "132"
64 #define N_PSYM "160" /* parameter */
65 #define N_EINCL "162"
66 #define N_ENTRY "164"
67 #define N_LBRAC "192"
68 #define N_EXCL "194"
69 #define N_SCOPE "196"
70 #define N_RBRAC "224"
71 #define N_BCOMM "226"
72 #define N_ECOMM "228"
73 #define N_ECOML "232"
74 #define N_WITH "234"
75 #define N_NBTEXT "240"
76 #define N_NBDATA "242"
77 #define N_NBBSS "244"
78 #define N_NBSTS "246"
79 #define N_NBLCS "248"
81 #ifdef __GNUC__
82 void Parrot_jit_debug(Interp* interp);
84 # define BIT_SIZE(t) ((int)(sizeof (t)*8))
85 # define BYTE_SIZE(t) ((int)sizeof (t))
86 # define BIT_OFFSET(str, field) ((int)(offsetof(str, field) * 8))
88 typedef struct {
89 const char *name;
90 const char *spec;
91 } BaseTypes;
95 =item C<static void write_types(FILE *stabs, Interp *interp)>
97 Writes the types to C<stabs>.
99 =cut
103 static void
104 write_types(FILE *stabs, Interp *interp)
106 int i, j;
107 /* borrowed from mono */
108 static BaseTypes base_types[] = {
109 {"Void", "(0,1)"},
110 {"Char", ";-128;127;"},
111 {"Byte", ";0;255;"},
112 {"Int16", ";-32768;32767;"},
113 {"UInt16", ";0;65535;"},
114 {"Int32", ";0020000000000;0017777777777;"}, /* 5 */
115 {"UInt32", ";0000000000000;0037777777777;"},
116 {"Int64", ";01000000000000000000000;0777777777777777777777;"},
117 {"UInt64", ";0000000000000;01777777777777777777777;"},
118 {"Single", "r(0,8);4;0;"},
119 {"Double", "r(0,8);8;0;"}, /* 10 */
120 {"LongDouble", "r(0,8);12;0;"},
121 # if INTVAL_SIZE == 4
122 {"INTVAL", "(0,5);"}, /* 12 */
123 # else
124 {"INTVAL", "(0,7);"},
125 # endif
126 # if NUMVAL_SIZE == 8
127 {"FLOATVAL", "(0,10);"}, /* 13 */
128 # else
129 {"FLOATVAL", "(0,11);"},
130 # endif
131 {"Ptr", "*(0,0);"},
132 {"CharPtr", "*(0,1);"}, /* 15 */
133 {0, 0}
135 for (i = 0; base_types[i].name; ++i) {
136 if (! base_types[i].spec)
137 continue;
138 fprintf(stabs, ".stabs \"%s:t(0,%d)=", base_types[i].name, i);
139 if (base_types[i].spec [0] == ';') {
140 fprintf(stabs, "r(0,%d)%s\"", i, base_types[i].spec);
142 else {
143 fprintf(stabs, "%s\"", base_types[i].spec);
145 fprintf(stabs, "," N_LSYM ",0,0,0\n");
147 fprintf(stabs, ".stabs \"STRING:t(0,%d)=*(0,%d)\""
148 "," N_LSYM ",0,0,0\n", i, i+1);
149 ++i;
150 fprintf(stabs, ".stabs \"Parrot_String:T(0,%d)=s%d"
151 "bufstart:(0,14),%d,%d;"
152 "buflen:(0,6),%d,%d;" /* XXX type */
153 "flags:(0,12),%d,%d;"
154 "bufused:(0,12),%d,%d;"
155 "strstart:(0,15),%d,%d;" /* fake a char* */
156 ";\""
157 "," N_LSYM ",0,0,0\n", i++, BYTE_SIZE(STRING),
158 BIT_OFFSET(STRING, obj.u._b._bufstart), BIT_SIZE(void*),
159 BIT_OFFSET(STRING, obj.u._b._buflen), BIT_SIZE(size_t),
160 BIT_OFFSET(STRING, obj.flags), BIT_SIZE(UINTVAL),
161 BIT_OFFSET(STRING, bufused), BIT_SIZE(UINTVAL),
162 BIT_OFFSET(STRING, strstart), BIT_SIZE(void*)
165 fprintf(stabs, ".stabs \"PMCType:T(0,%d)=e", i++);
166 for (j = 0; j < interp->n_vtable_max; ++j) {
167 if (interp->vtables[j] && interp->vtables[j]->whoami) {
168 STRING* name = interp->vtables[j]->whoami;
169 fwrite(name->strstart, name->strlen, 1, stabs);
170 fprintf(stabs, ":%d,", j);
173 fprintf(stabs, ";\"," N_LSYM ",0,0,0\n");
175 /* PMC type */
176 fprintf(stabs, ".stabs \"PMC:T(0,%d)=s%d", i, BYTE_SIZE(PMC));
177 fprintf(stabs, "obj:(0,%d),%d,%d;",
178 i + 1, BIT_OFFSET(PMC, obj), BIT_SIZE(pobj_t));
179 fprintf(stabs, "vtable:*(0,%d),%d,%d;",
180 i + 3, BIT_OFFSET(PMC, vtable), BIT_SIZE(void*));
181 # if ! PMC_DATA_IN_EXT
182 fprintf(stabs, "data:(0,14),%d,%d;",
183 BIT_OFFSET(PMC, data), BIT_SIZE(void*));
184 # endif
185 fprintf(stabs, "pmc_ext:*(0,%d),%d,%d;",
186 i, BIT_OFFSET(PMC, pmc_ext), BIT_SIZE(void*));
187 fprintf(stabs, ";\"");
188 fprintf(stabs, "," N_LSYM ",0,0,0\n");
190 fprintf(stabs, ".stabs \"pobj_t:T(0,%d)=s%d"
191 "u:(0,%d),%d,%d;"
192 "flags:(0,12),%d,%d;"
193 ";\""
194 "," N_LSYM ",0,0,0\n", i + 1, (int)(sizeof (pobj_t)),
195 i + 2, BIT_OFFSET(pobj_t, u), BIT_SIZE(UnionVal),
196 BIT_OFFSET(pobj_t, flags), BIT_SIZE(Parrot_UInt)
198 fprintf(stabs, ".stabs \"UnionVal:T(0,%d)=u%d"
199 "int_val:(0,12),%d,%d;"
200 "pmc_val:*(0,%d),%d,%d;"
201 ";\""
202 "," N_LSYM ",0,0,0\n", i + 2, BYTE_SIZE(UnionVal),
203 BIT_OFFSET(UnionVal, _i._int_val), BIT_SIZE(INTVAL),
204 i, BIT_OFFSET(UnionVal, _ptrs._pmc_val), BIT_SIZE(void*)
206 fprintf(stabs, ".stabs \"VTABLE:T(0,%d)=s%d"
207 "base_type:(0,%d),%d,%d;"
208 ";\""
209 "," N_LSYM ",0,0,0\n", i + 3, BYTE_SIZE(UnionVal),
210 i - 1, BIT_OFFSET(VTABLE, base_type), BIT_SIZE(INTVAL)
212 i += 4;
218 =item C<static void
219 write_vars(FILE *stabs, Interp *interp)>
221 Writes the contents of the registers to C<stabs>.
223 =cut
227 static void
228 write_vars(FILE *stabs, Interp *interp)
230 int i;
231 /* fake static var stabs */
232 for (i = 0; i < NUM_REGISTERS; i++) {
233 fprintf(stabs, ".stabs \"I%d:S(0,12)\"," N_STSYM ",0,0,%p\n", i,
234 (char*)&REG_INT(i));
235 fprintf(stabs, ".stabs \"N%d:S(0,13)\"," N_STSYM ",0,0,%p\n", i,
236 (char*)&REG_NUM(i));
237 fprintf(stabs, ".stabs \"S%d:S(0,16)\"," N_STSYM ",0,0,%p\n", i,
238 (char*)&REG_STR(i));
239 fprintf(stabs, ".stabs \"P%d:S*(0,19)\"," N_STSYM ",0,0,%p\n", i,
240 (char*)&REG_PMC(i));
246 =item C<static STRING *
247 debug_file(Interp *interp, STRING *file, const char *ext)>
249 Returns C<file> with C<ext> appended.
251 =cut
255 static STRING *
256 debug_file(Interp *interp, STRING *file, const char *ext)
258 STRING *ret;
259 ret = string_copy(interp, file);
260 ret = string_append(interp, ret,
261 string_make(interp, ext, strlen(ext), NULL,
262 PObj_external_FLAG));
263 return ret;
268 =item C<static void
269 Parrot_jit_debug_stabs(Interp *interp)>
271 Writes the JIT debugging stabs.
273 =cut
277 static void
278 Parrot_jit_debug_stabs(Interp *interp)
280 Parrot_jit_info_t *jit_info = interp->code->jit_info;
281 STRING *file = NULL;
282 STRING *pasmfile, *stabsfile, *ofile, *cmd;
283 FILE *stabs;
284 size_t i;
285 int line;
286 opcode_t lc;
287 struct PackFile_Debug *debug;
289 if (interp->code->debugs) {
290 char *ext;
291 char *src = string_to_cstring(interp,
292 Parrot_debug_pc_to_filename(interp,
293 interp->code->debugs, 0));
294 pasmfile = string_make(interp, src, strlen(src), NULL,
295 PObj_external_FLAG);
296 file = string_copy(interp, pasmfile);
297 /* chop pasm/pir */
299 ext = strrchr(src, '.');
300 if (ext && strcmp(ext, ".pasm") == 0)
301 file = string_chopn(interp, file, 4, 1);
302 else if (ext && strcmp(ext, ".pir") == 0)
303 file = string_chopn(interp, file, 3, 1);
304 else if (!ext) /* EVAL_n */
305 file = string_append(interp, file,
306 string_make(interp, ".", 1, NULL, PObj_external_FLAG));
308 else {
309 /* chop pbc */
310 file = string_chopn(interp, file, 3, 1);
311 pasmfile = debug_file(interp, file, "pasm");
313 stabsfile = debug_file(interp, file, "stabs.s");
314 ofile = debug_file(interp, file, "o");
316 char *temp = string_to_cstring(interp,stabsfile);
317 stabs = fopen(temp, "w");
318 free(temp);
320 if (stabs == NULL)
321 return;
324 char *temp = string_to_cstring(interp, pasmfile);
325 /* filename info */
326 fprintf(stabs, ".data\n.text\n"); /* darwin wants it */
327 fprintf(stabs, ".stabs \"%s\"," N_SO ",0,0,0\n",temp);
328 free(temp);
330 /* jit_func start addr */
331 fprintf(stabs, ".stabs \"jit_func:F(0,1)\"," N_FUN ",0,1,%p\n",
332 jit_info->arena.start);
334 write_types(stabs, interp);
335 write_vars(stabs, interp);
336 /* if we don't have line numbers, emit dummys, assuming there are
337 * no comments and spaces in source for testing
340 /* jit_begin */
341 fprintf(stabs, ".stabn " N_SLINE ",0,1,0\n");
342 line = 1;
343 lc = 0;
344 debug = interp->code->debugs;
345 for (i = 0; i < interp->code->base.size; i++) {
346 if (jit_info->arena.op_map[i].ptr) {
347 op_info_t* op = &interp->op_info_table[
348 interp->code->base.data[i]];
349 if (interp->code->debugs) {
350 if (lc >= (int)(debug->base.size))
351 break;
352 line = (int)debug->base.data[lc++];
354 fprintf(stabs, ".stabn " N_SLINE ",0,%d,%d /* %s */\n", line,
355 (int)((char *)jit_info->arena.op_map[i].ptr -
356 (char *)jit_info->arena.start),
357 op->full_name);
358 line++;
361 /* eof */
362 fprintf(stabs, ".stabs \"\"," N_FUN ",0,1,%p\n",
363 (char *) jit_info->arena.size);
364 fclose(stabs);
365 /* run the stabs file through C<as> generating file.o */
366 cmd = Parrot_sprintf_c(interp, "as %Ss -o %Ss", stabsfile, ofile);
369 char *temp = string_to_cstring(interp, cmd);
370 system(temp);
371 free(temp);
377 =item C<void
378 Parrot_jit_debug(Interp* interp)>
380 Writes the JIT debugging stabs. Just calls C<Parrot_jit_debug_stabs()>.
382 =cut
386 void
387 Parrot_jit_debug(Interp* interp)
389 Parrot_jit_debug_stabs(interp);
393 #endif
397 =back
399 =head1 SEE ALSO
401 F<src/jit.c>, F<include/parrot/jit.h>, F<docs/jit.pod>.
403 =cut
409 * Local variables:
410 * c-file-style: "parrot"
411 * End:
412 * vim: expandtab shiftwidth=4: