2 Copyright (C) 2001-2006, The Perl 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 #include <parrot/parrot.h>
32 #include "parrot/exec.h"
35 #define N_GSYM "32" /* global variable */
38 #define N_STSYM "38" /* variable in data section */
39 #define N_LCSYM "40" /* bss section */
47 #define N_RSYM "64" /* register variable */
60 #define N_SO "100" /* filename */
61 #define N_LSYM "128" /* stack variable */
64 #define N_PSYM "160" /* parameter */
75 #define N_NBTEXT "240"
76 #define N_NBDATA "242"
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))
95 =item C<static void write_types(FILE *stabs, Interp *interp)>
97 Writes the types to C<stabs>.
104 write_types(FILE *stabs
, Interp
*interp
)
107 /* borrowed from mono */
108 static BaseTypes base_types
[] = {
110 {"Char", ";-128;127;"},
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 */
124 {"INTVAL", "(0,7);"},
126 # if NUMVAL_SIZE == 8
127 {"FLOATVAL", "(0,10);"}, /* 13 */
129 {"FLOATVAL", "(0,11);"},
132 {"CharPtr", "*(0,1);"}, /* 15 */
135 for (i
= 0; base_types
[i
].name
; ++i
) {
136 if (! base_types
[i
].spec
)
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
);
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);
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* */
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");
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*));
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"
192 "flags:(0,12),%d,%d;"
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;"
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;"
209 "," N_LSYM
",0,0,0\n", i
+ 3, BYTE_SIZE(UnionVal
),
210 i
- 1, BIT_OFFSET(VTABLE
, base_type
), BIT_SIZE(INTVAL
)
219 write_vars(FILE *stabs, Interp *interp)>
221 Writes the contents of the registers to C<stabs>.
228 write_vars(FILE *stabs
, Interp
*interp
)
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
,
235 fprintf(stabs
, ".stabs \"N%d:S(0,13)\"," N_STSYM
",0,0,%p\n", i
,
237 fprintf(stabs
, ".stabs \"S%d:S(0,16)\"," N_STSYM
",0,0,%p\n", i
,
239 fprintf(stabs
, ".stabs \"P%d:S*(0,19)\"," N_STSYM
",0,0,%p\n", i
,
246 =item C<static STRING *
247 debug_file(Interp *interp, STRING *file, const char *ext)>
249 Returns C<file> with C<ext> appended.
256 debug_file(Interp
*interp
, STRING
*file
, const char *ext
)
259 ret
= string_copy(interp
, file
);
260 ret
= string_append(interp
, ret
,
261 string_make(interp
, ext
, strlen(ext
), NULL
,
262 PObj_external_FLAG
));
269 Parrot_jit_debug_stabs(Interp *interp)>
271 Writes the JIT debugging stabs.
278 Parrot_jit_debug_stabs(Interp
*interp
)
280 Parrot_jit_info_t
*jit_info
= interp
->code
->jit_info
;
282 STRING
*pasmfile
, *stabsfile
, *ofile
, *cmd
;
287 struct PackFile_Debug
*debug
;
289 if (interp
->code
->debugs
) {
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
,
296 file
= string_copy(interp
, pasmfile
);
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
));
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");
324 char *temp
= string_to_cstring(interp
, pasmfile
);
326 fprintf(stabs
, ".data\n.text\n"); /* darwin wants it */
327 fprintf(stabs
, ".stabs \"%s\"," N_SO
",0,0,0\n",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
341 fprintf(stabs
, ".stabn " N_SLINE
",0,1,0\n");
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
))
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
),
362 fprintf(stabs
, ".stabs \"\"," N_FUN
",0,1,%p\n",
363 (char *) jit_info
->arena
.size
);
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
);
378 Parrot_jit_debug(Interp* interp)>
380 Writes the JIT debugging stabs. Just calls C<Parrot_jit_debug_stabs()>.
387 Parrot_jit_debug(Interp
* interp
)
389 Parrot_jit_debug_stabs(interp
);
401 F<src/jit.c>, F<include/parrot/jit.h>, F<docs/jit.pod>.
410 * c-file-style: "parrot"
412 * vim: expandtab shiftwidth=4: