2 Copyright (C) 2001-2008, Parrot Foundation.
7 src/jit_debug.c - Write stabs file for JIT code
11 When debugging JIT code with C<gdb>, do:
13 add-symbol-file <file.o> 0
17 Stabs is a file format for information that describes a program to a
20 For more information see the stabs documentation at
21 http://sources.redhat.com/gdb/current/onlinedocs/stabs_toc.html.
31 /* HEADERIZER HFILE: none */
34 #include <parrot/parrot.h>
35 #include "parrot/exec.h"
38 #define N_GSYM "32" /* global variable */
41 #define N_STSYM "38" /* variable in data section */
42 #define N_LCSYM "40" /* bss section */
50 #define N_RSYM "64" /* register variable */
63 #define N_SO "100" /* filename */
64 #define N_LSYM "128" /* stack variable */
67 #define N_PSYM "160" /* parameter */
78 #define N_NBTEXT "240"
79 #define N_NBDATA "242"
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
{
98 =item C<static void write_types(FILE *stabs, PARROT_INTERP)>
100 Writes the types to C<stabs>.
107 write_types(FILE *stabs
, PARROT_INTERP
)
109 /* It would be create if this function would be auto generated */
111 /* borrowed from mono */
112 static BaseTypes base_types
[] = {
114 {"Char", ";-128;127;"},
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 */
128 {"INTVAL", "(0,7);"},
130 # if NUMVAL_SIZE == 8
131 {"FLOATVAL", "(0,10);"}, /* 13 */
133 {"FLOATVAL", "(0,11);"},
136 {"CharPtr", "*(0,1);"}, /* 15 */
139 for (i
= 0; base_types
[i
].name
; ++i
) {
140 if (! base_types
[i
].spec
)
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
);
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);
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;"
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
);
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;"
185 "_metadata:*(0,%d),%d,%d;"
186 "_next_for_GC:*(0,%d),%d,%d;"
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*));
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;"
201 "," N_LSYM
",0,0,0\n", i
, BYTE_SIZE(_vtable
),
202 BIT_OFFSET(VTABLE
, base_type
), BIT_SIZE(INTVAL
));
210 write_vars(FILE *stabs, PARROT_INTERP)>
212 Writes the contents of the registers to C<stabs>.
219 write_vars(FILE *stabs
, PARROT_INTERP
)
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*)®_INT(interp
, i
));
226 fprintf(stabs
, ".stabs \"N%d:S(0,13)\"," N_STSYM
",0,0,%p\n", i
,
227 (char*)®_NUM(interp
, i
));
228 fprintf(stabs
, ".stabs \"S%d:S(0,16)\"," N_STSYM
",0,0,%p\n", i
,
229 (char*)®_STR(interp
, i
));
230 fprintf(stabs
, ".stabs \"P%d:S*(0,19)\"," N_STSYM
",0,0,%p\n", i
,
231 (char*)®_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.
247 debug_file(PARROT_INTERP
, STRING
*file
, const char *ext
)
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
));
260 Parrot_jit_debug_stabs(PARROT_INTERP)>
262 Writes the JIT debugging stabs.
269 Parrot_jit_debug_stabs(PARROT_INTERP
)
271 Parrot_jit_info_t
*jit_info
= interp
->code
->jit_info
;
273 STRING
*pasmfile
, *stabsfile
, *ofile
, *cmd
;
278 PackFile_Debug
*debug
;
280 if (interp
->code
->debugs
) {
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
,
287 file
= Parrot_str_copy(interp
, pasmfile
);
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
);
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
);
317 char * const temp
= Parrot_str_to_cstring(interp
, pasmfile
);
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
334 fprintf(stabs
, ".stabn " N_SLINE
",0,1,0\n");
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
))
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
),
355 fprintf(stabs
, ".stabs \"\"," N_FUN
",0,1,%p\n",
356 (char *) jit_info
->arena
.size
);
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
);
366 fprintf(stderr
, "Assembly failed: %d\n%s\n", status
, temp
);
367 Parrot_str_free_cstring(temp
);
374 Parrot_jit_debug(PARROT_INTERP)>
376 Writes the JIT debugging stabs. Just calls C<Parrot_jit_debug_stabs()>.
383 Parrot_jit_debug(PARROT_INTERP
)
385 Parrot_jit_debug_stabs(interp
);
397 F<src/jit.c>, F<include/parrot/jit.h>, F<docs/jit.pod>.
406 * c-file-style: "parrot"
408 * vim: expandtab shiftwidth=4: