[t] Refactor some namespace pmc tests to use throws_like
[parrot.git] / src / jit_debug.c
blob179cdd652350dd5c52ca3f8e554019863fad59eb
1 /*
2 Copyright (C) 2001-2008, Parrot 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 /* HEADERIZER HFILE: none */
32 /* HEADERIZER STOP */
34 #include <parrot/parrot.h>
35 #include "parrot/exec.h"
36 #include "jit.h"
38 #define N_GSYM "32" /* global variable */
39 #define N_FNAME "34"
40 #define N_FUN "36"
41 #define N_STSYM "38" /* variable in data section */
42 #define N_LCSYM "40" /* bss section */
43 #define N_MAIN "42"
44 #define N_ROSYM "44"
45 #define N_PC "48"
46 #define N_NSYMS "50"
47 #define N_NOMAP "52"
48 #define N_OBJ "56"
49 #define N_OPT "60"
50 #define N_RSYM "64" /* register variable */
51 #define N_M2C "66"
52 #define N_SLINE "68"
53 #define N_DSLINE "70"
54 #define N_BSLINE "72"
55 #define N_BROWS "72"
56 #define N_DEFD "74"
57 #define N_FLINE "76"
58 #define N_EHDECL "80"
59 #define N_MOD2 "80"
60 #define N_CATCH "84"
61 #define N_SSYM "96"
62 #define N_ENDM "98"
63 #define N_SO "100" /* filename */
64 #define N_LSYM "128" /* stack variable */
65 #define N_BINCL "130"
66 #define N_SOL "132"
67 #define N_PSYM "160" /* parameter */
68 #define N_EINCL "162"
69 #define N_ENTRY "164"
70 #define N_LBRAC "192"
71 #define N_EXCL "194"
72 #define N_SCOPE "196"
73 #define N_RBRAC "224"
74 #define N_BCOMM "226"
75 #define N_ECOMM "228"
76 #define N_ECOML "232"
77 #define N_WITH "234"
78 #define N_NBTEXT "240"
79 #define N_NBDATA "242"
80 #define N_NBBSS "244"
81 #define N_NBSTS "246"
82 #define N_NBLCS "248"
84 #ifdef __GNUC__
85 void Parrot_jit_debug(PARROT_INTERP);
87 # define BIT_SIZE(t) ((int)(sizeof (t)*8))
88 # define BYTE_SIZE(t) ((int)sizeof (t))
89 # define BIT_OFFSET(str, field) ((int)(offsetof(str, field) * 8))
91 typedef struct BaseTypes {
92 const char *name;
93 const char *spec;
94 } BaseTypes;
98 =item C<static void write_types(FILE *stabs, PARROT_INTERP)>
100 Writes the types to C<stabs>.
102 =cut
106 static void
107 write_types(FILE *stabs, PARROT_INTERP)
109 /* It would be create if this function would be auto generated */
110 int i, j;
111 /* borrowed from mono */
112 static BaseTypes base_types[] = {
113 {"Void", "(0,1)"},
114 {"Char", ";-128;127;"},
115 {"Byte", ";0;255;"},
116 {"Int16", ";-32768;32767;"},
117 {"UInt16", ";0;65535;"},
118 {"Int32", ";0020000000000;0017777777777;"}, /* 5 */
119 {"UInt32", ";0000000000000;0037777777777;"},
120 {"Int64", ";01000000000000000000000;0777777777777777777777;"},
121 {"UInt64", ";0000000000000;01777777777777777777777;"},
122 {"Single", "r(0,8);4;0;"},
123 {"Double", "r(0,8);8;0;"}, /* 10 */
124 {"LongDouble", "r(0,8);12;0;"},
125 # if INTVAL_SIZE == 4
126 {"INTVAL", "(0,5);"}, /* 12 */
127 # else
128 {"INTVAL", "(0,7);"},
129 # endif
130 # if NUMVAL_SIZE == 8
131 {"FLOATVAL", "(0,10);"}, /* 13 */
132 # else
133 {"FLOATVAL", "(0,11);"},
134 # endif
135 {"Ptr", "*(0,0);"},
136 {"CharPtr", "*(0,1);"}, /* 15 */
137 {0, 0}
139 for (i = 0; base_types[i].name; ++i) {
140 if (! base_types[i].spec)
141 continue;
142 fprintf(stabs, ".stabs \"%s:t(0,%d)=", base_types[i].name, i);
143 if (base_types[i].spec [0] == ';') {
144 fprintf(stabs, "r(0,%d)%s\"", i, base_types[i].spec);
146 else {
147 fprintf(stabs, "%s\"", base_types[i].spec);
149 fprintf(stabs, "," N_LSYM ",0,0,0\n");
151 fprintf(stabs, ".stabs \"STRING:t(0,%d)=*(0,%d)\""
152 "," N_LSYM ",0,0,0\n", i, i+1);
153 ++i;
154 fprintf(stabs, ".stabs \"Parrot_String:T(0,%d)=s%d"
155 "bufstart:(0,14),%d,%d;"
156 "buflen:(0,6),%d,%d;"
157 "flags:(0,12),%d,%d;"
158 "bufused:(0,12),%d,%d;"
159 "strstart:(0,15),%d,%d;"
160 ";\""
161 "," N_LSYM ",0,0,0\n", i++, BYTE_SIZE(STRING),
162 BIT_OFFSET(STRING, _bufstart), BIT_SIZE(void*),
163 BIT_OFFSET(STRING, _buflen), BIT_SIZE(size_t),
164 BIT_OFFSET(STRING, flags), BIT_SIZE(UINTVAL),
165 BIT_OFFSET(STRING, bufused), BIT_SIZE(UINTVAL),
166 BIT_OFFSET(STRING, strstart), BIT_SIZE(void*));
168 fprintf(stabs, ".stabs \"PMCType:T(0,%d)=e", i++);
169 for (j = 0; j < interp->n_vtable_max; ++j) {
170 if (interp->vtables[j] && interp->vtables[j]->whoami) {
171 STRING *name = interp->vtables[j]->whoami;
172 size_t items = fwrite(name->strstart, name->strlen, 1, stabs);
173 if (!items)
174 fprintf(stderr, "Error writing stabs!\n");
175 fprintf(stabs, ":%d,", j);
179 fprintf(stabs, ";\"," N_LSYM ",0,0,0\n");
181 fprintf(stabs, ".stabs \"PMC:T(0,%d)=s%d"
182 "flags:(0,12),%d,%d;"
183 "vtable:*(0,%d),%d,%d;"
184 "data:(0,14),%d,%d;"
185 "_metadata:*(0,%d),%d,%d;"
186 "_next_for_GC:*(0,%d),%d,%d;"
187 ";\""
188 "," N_LSYM ",0,0,0\n", i, BYTE_SIZE(PMC),
189 BIT_OFFSET(PMC, flags), BIT_SIZE(UINTVAL),
190 i + 1, BIT_OFFSET(PMC, vtable), BIT_SIZE(void*),
191 BIT_OFFSET(PMC, data), BIT_SIZE(void*),
192 i, BIT_OFFSET(PMC, _metadata), BIT_SIZE(void*),
193 i, BIT_OFFSET(PMC, _next_for_GC), BIT_SIZE(void*));
195 i++;
197 /* someone can add some field to this one */
198 fprintf(stabs, ".stabs \"VTABLE:T(0,%d)=s%d"
199 "base_type:(0,12),%d,%d;"
200 ";\""
201 "," N_LSYM ",0,0,0\n", i, BYTE_SIZE(_vtable),
202 BIT_OFFSET(VTABLE, base_type), BIT_SIZE(INTVAL));
204 i++;
209 =item C<static void
210 write_vars(FILE *stabs, PARROT_INTERP)>
212 Writes the contents of the registers to C<stabs>.
214 =cut
218 static void
219 write_vars(FILE *stabs, PARROT_INTERP)
221 int i;
222 /* fake static var stabs */
223 for (i = 0; i < NUM_REGISTERS; i++) {
224 fprintf(stabs, ".stabs \"I%d:S(0,12)\"," N_STSYM ",0,0,%p\n", i,
225 (char*)&REG_INT(interp, i));
226 fprintf(stabs, ".stabs \"N%d:S(0,13)\"," N_STSYM ",0,0,%p\n", i,
227 (char*)&REG_NUM(interp, i));
228 fprintf(stabs, ".stabs \"S%d:S(0,16)\"," N_STSYM ",0,0,%p\n", i,
229 (char*)&REG_STR(interp, i));
230 fprintf(stabs, ".stabs \"P%d:S*(0,19)\"," N_STSYM ",0,0,%p\n", i,
231 (char*)&REG_PMC(interp, i));
237 =item C<static STRING *
238 debug_file(PARROT_INTERP, STRING *file, const char *ext)>
240 Returns C<file> with C<ext> appended.
242 =cut
246 static STRING *
247 debug_file(PARROT_INTERP, STRING *file, const char *ext)
249 STRING *ret;
250 ret = Parrot_str_copy(interp, file);
251 ret = Parrot_str_append(interp, ret,
252 string_make(interp, ext, strlen(ext), NULL,
253 PObj_external_FLAG));
254 return ret;
259 =item C<static void
260 Parrot_jit_debug_stabs(PARROT_INTERP)>
262 Writes the JIT debugging stabs.
264 =cut
268 static void
269 Parrot_jit_debug_stabs(PARROT_INTERP)
271 Parrot_jit_info_t *jit_info = interp->code->jit_info;
272 STRING *file = NULL;
273 STRING *pasmfile, *stabsfile, *ofile, *cmd;
274 FILE *stabs;
275 size_t i;
276 int line;
277 opcode_t lc;
278 PackFile_Debug *debug;
280 if (interp->code->debugs) {
281 char *ext;
282 char * const src = Parrot_str_to_cstring(interp,
283 Parrot_debug_pc_to_filename(interp,
284 interp->code->debugs, 0));
285 pasmfile = string_make(interp, src, strlen(src), NULL,
286 PObj_external_FLAG);
287 file = Parrot_str_copy(interp, pasmfile);
288 /* chop pasm/pir */
290 ext = strrchr(src, '.');
291 if (ext && STREQ(ext, ".pasm"))
292 Parrot_str_chopn_inplace(interp, file, 4);
293 else if (ext && STREQ(ext, ".pir"))
294 Parrot_str_chopn_inplace(interp, file, 3);
295 else if (!ext) /* EVAL_n */
296 file = Parrot_str_append(interp, file,
297 string_make(interp, ".", 1, NULL, PObj_external_FLAG));
299 Parrot_str_free_cstring(src);
301 else {
302 /* chop pbc */
303 Parrot_str_chopn_inplace(interp, file, 3);
304 pasmfile = debug_file(interp, file, "pasm");
306 stabsfile = debug_file(interp, file, "stabs.s");
307 ofile = debug_file(interp, file, "o");
309 char *const temp = Parrot_str_to_cstring(interp, stabsfile);
310 stabs = fopen(temp, "w");
311 Parrot_str_free_cstring(temp);
313 if (stabs == NULL)
314 return;
317 char * const temp = Parrot_str_to_cstring(interp, pasmfile);
318 /* filename info */
319 fprintf(stabs, ".data\n.text\n"); /* darwin wants it */
320 fprintf(stabs, ".stabs \"%s\"," N_SO ",0,0,0\n", temp);
321 Parrot_str_free_cstring(temp);
323 /* jit_func start addr */
324 fprintf(stabs, ".stabs \"jit_func:F(0,1)\"," N_FUN ",0,1,%p\n",
325 jit_info->arena.start);
327 write_types(stabs, interp);
328 write_vars(stabs, interp);
329 /* if we don't have line numbers, emit dummys, assuming there are
330 * no comments and spaces in source for testing
333 /* jit_begin */
334 fprintf(stabs, ".stabn " N_SLINE ",0,1,0\n");
335 line = 1;
336 lc = 0;
337 debug = interp->code->debugs;
338 for (i = 0; i < interp->code->base.size; i++) {
339 if (jit_info->arena.op_map[i].ptr) {
340 op_info_t* op = &interp->op_info_table[
341 interp->code->base.data[i]];
342 if (interp->code->debugs) {
343 if (lc >= (int)(debug->base.size))
344 break;
345 line = (int)debug->base.data[lc++];
347 fprintf(stabs, ".stabn " N_SLINE ",0,%d,%d /* %s */\n", line,
348 (int)((char *)jit_info->arena.op_map[i].ptr -
349 (char *)jit_info->arena.start),
350 op->full_name);
351 line++;
354 /* eof */
355 fprintf(stabs, ".stabs \"\"," N_FUN ",0,1,%p\n",
356 (char *) jit_info->arena.size);
357 fclose(stabs);
359 /* run the stabs file through C<as> generating file.o */
360 cmd = Parrot_sprintf_c(interp, "as %Ss -o %Ss", stabsfile, ofile);
363 char * const temp = Parrot_str_to_cstring(interp, cmd);
364 int status = system(temp);
365 if (status)
366 fprintf(stderr, "Assembly failed: %d\n%s\n", status, temp);
367 Parrot_str_free_cstring(temp);
373 =item C<void
374 Parrot_jit_debug(PARROT_INTERP)>
376 Writes the JIT debugging stabs. Just calls C<Parrot_jit_debug_stabs()>.
378 =cut
382 void
383 Parrot_jit_debug(PARROT_INTERP)
385 Parrot_jit_debug_stabs(interp);
389 #endif
393 =back
395 =head1 SEE ALSO
397 F<src/jit.c>, F<include/parrot/jit.h>, F<docs/jit.pod>.
399 =cut
405 * Local variables:
406 * c-file-style: "parrot"
407 * End:
408 * vim: expandtab shiftwidth=4: